/**
 *
 * Copyright 2004 Hiram Chirino
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 **/
package org.codehaus.activemq.journal.impl;

import java.nio.ByteBuffer;


/**
 * Serializes/Deserializes data records. 
 * 
 * @version $Revision: 1.1 $
 */
public class Record {

	static final public int RECORD_BASE_SIZE=RecordHeader.RECORD_HEADER_SIZE+RecordFooter.RECORD_FOOTER_SIZE;
	
	final RecordHeader header = new RecordHeader();
	final RecordFooter footer = new RecordFooter();
	final ByteBuffer headerBuffer;
	final ByteBuffer dataBuffer;
	final ByteBuffer footerBuffer;
	final Mark mark;
	
	public Record(RecordHeader header, byte[] data) {
		this( header.sequenceId, header.recordType, data, null);
	}

	public Record(final long sequenceId, final byte recordType, final byte data[], final Mark visitData) {
		this.header.bulkSet(recordType, sequenceId, data);
	    this.headerBuffer = this.header.toByteBuffer();
	    this.dataBuffer = ByteBuffer.wrap( data );
	    this.footer.bulkSet(header, data);
	    this.footerBuffer = footer.toByteBuffer();
	    this.mark = visitData;
	}
	

	public RecordHeader getHeader() {
		return header;
	}
	
	public Mark getMark() {
		return mark;
	}

	public int remaining() {
		return headerBuffer.remaining() + dataBuffer.remaining();
	}
	
	public void fill(ByteBuffer byteBuffer) {
		fill( byteBuffer, headerBuffer);
		fill( byteBuffer, dataBuffer);
		fill( byteBuffer, footerBuffer);
	}

	/**
	 * Relative bulk put operation that copies bytes from src to dest.  Unlike
	 * <code>ByteBuffer.put(ByteBuffer)</code> this will not throw a 
	 * <code>java.nio.BufferOverflowException</code>.  It will just put
	 * as many bytes as can fit into the dest object.
	 * 
	 * @param byteBuffer
	 * @param headerBuffer2
	 */
	private void fill(ByteBuffer dest, ByteBuffer src) {
		int r =dest.remaining();
		if( r ==0 )
			return;
		// If the src won't fit into the dest.
		if( r < src.remaining() ) {
			// temporarly reduce the limit on the src so it does fit.
			int limit = src.limit();
			src.limit(src.position()+r);
			dest.put(src);
			// restore the limit.
			src.limit(limit);
		} else {
			dest.put(src);
		}
		
	}
	
}
