/**
 * LOGICAL-PARADOX.ORG variable record manager library
 * Copyright (C)2004 satoshi akabane(akabane@logical-paradox.org)
 *
 * Release 1.0
 * ・初期パージョン
 */
package org.logical_paradox.common.vrm;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import org.logical_paradox.common.io.ByteStream;

/**
 * 可変長サイズのレコード
 * 
 * @author satoshi akabane@logical-paradox.org
 * @version 1.0
 */
public abstract class Record implements ByteStream, Comparable {
	protected ByteStream o;

	/**
	 * デフォルトコンストラクタ
	 *
	 */
	public Record() {
	}
	/**
	 * コンストラクタ
	 * 引数のバイト列からこのレコードを復元する
	 * @param bstream バイト列
	 */
	public Record(byte[] bstream) {
		byteStreamToObject(bstream);
	}
	/**
	 * コンストラクタ
	 * バイトストリーム表現可能なオブジェクトを引数にとるタイプ
	 * @param stream 値オブジェクト
	 */
	public Record(ByteStream stream) {
		o = stream;
	}
	/**
	 * 値オブジェクトをセットする
	 * @param b 値オブジェクト
	 */
	public void setObject(ByteStream b) {
		o = b;
	}
	/**
	 * 値オブジェクトを返す
	 * @return 値オブジェクト
	 */
	public Object getObject() {
		return o;
	}
	/**
	 * 値オブジェクトのバイト列表現を返す
	 * @return バイト列
	 */
	public byte[] getObjectByteStream() {
		return o.byteStream();
	}
	/**
	 * このレコードのサイズを返す
	 * @return バイトサイズ
	 */
	public int size() {
		return byteStream().length;
	}
	/**
	 * このレコードのバイト列表現を返す
	 * @return バイト列
	 */
	public byte[] byteStream() {
		byte[] bstream = o.byteStream();
		ByteBuffer buffer = ByteBuffer.allocate(4 + bstream.length).order(ByteOrder.BIG_ENDIAN);

		buffer.putInt(bstream.length);				// データサイズ(4バイト)
		buffer.put(bstream);						// 格納するデータのバイト列(可変長)
		
		return buffer.array();
	}
	/**
	 * バイト列からレコードを復元する
	 * @param bstream バイト列
	 * @throws IllegalArgumentException 引数のバイト列がおかしい
	 */
	protected void byteStreamToObject(byte[] bstream) throws IllegalArgumentException {
		ByteBuffer buffer = ByteBuffer.allocate(bstream.length).order(ByteOrder.BIG_ENDIAN);
		buffer.put(bstream);
		buffer.rewind();
		try {
			byte[] object = new byte[bstream.length];
			buffer.get(object);
			createObjectFromByteStream(object);
		} catch(Exception e) {
			e.printStackTrace();
			throw new IllegalArgumentException(e.getMessage());
		}
	}
	/**
	 * レコード間の比較
	 * @param o 比較対象レコード
	 * @return 1:this>o 0:this==o -1:this<o
	 */
	public int compareTo(Object o) {
		Record r = (Record)o;
		if(size() < r.size()) {
			return -1;
		} else if(size() > r.size()) {
			return 1;
		} else {
			return 0;
		}
	}
	public abstract int getRecordSize();
	/**
	 * レコード値を比較する
	 * @param o 比較対象
	 * @return true:同じ / false:違う
	 */
	public abstract boolean equals(Object o);

	/**
	 * バイト列から値オブジェクトを復元する
	 * このメソッドは，派生クラスで実装する
	 * @param bstream バイト列
	 * @throws IllegalArgumentException バイト列からの値オブジェクトの復元に失敗した
	 */
	protected abstract void createObjectFromByteStream(byte[] bstream) throws IllegalArgumentException;
}
