FileDocCategorySizeDatePackage
RecordContainer.javaAPI DocApache Poi 3.0.19374Mon Jan 01 18:55:34 GMT 2007org.apache.poi.hslf.record

RecordContainer

public abstract class RecordContainer extends Record
Abstract class which all container records will extend. Providers helpful methods for writing child records out to disk
author
Nick Burch

Fields Summary
protected Record[]
_children
private Boolean
changingChildRecordsLock
Constructors Summary
Methods Summary
public voidaddChildAfter(org.apache.poi.hslf.record.Record newChild, org.apache.poi.hslf.record.Record after)
Adds the given Child Record after the supplied record

param
newChild
param
after

		synchronized(changingChildRecordsLock) {
			// Decide where we're going to put it
			int loc = findChildLocation(after);
			if(loc == -1) {
				throw new IllegalArgumentException("Asked to add a new child after another record, but that record wasn't one of our children!");
			}
				
			// Add one place after the supplied record
			addChildAt(newChild, loc+1);
		}
	
private voidaddChildAt(org.apache.poi.hslf.record.Record newChild, int position)
Adds the given new Child Record at the given location, shuffling everything from there on down by one

param
newChild
param
position

		synchronized(changingChildRecordsLock) {
			// Firstly, have the child added in at the end
			appendChild(newChild);
			
			// Now, have them moved to the right place
			moveChildRecords( (_children.length-1), position, 1 );
		}
	
public voidaddChildBefore(org.apache.poi.hslf.record.Record newChild, org.apache.poi.hslf.record.Record before)
Adds the given Child Record before the supplied record

param
newChild
param
after

		synchronized(changingChildRecordsLock) {
			// Decide where we're going to put it
			int loc = findChildLocation(before);
			if(loc == -1) {
				throw new IllegalArgumentException("Asked to add a new child before another record, but that record wasn't one of our children!");
			}
				
			// Add at the place of the supplied record
			addChildAt(newChild, loc);
		}
	
private voidappendChild(org.apache.poi.hslf.record.Record newChild)
Adds a child record, at the very end.

param
newChild The child record to add

		synchronized(changingChildRecordsLock) {
			// Copy over, and pop the child in at the end
			Record[] nc = new Record[(_children.length + 1)];
			System.arraycopy(_children, 0, nc, 0, _children.length);
			// Switch the arrays
			nc[_children.length] = newChild;
			_children = nc;
		}
	
public voidappendChildRecord(org.apache.poi.hslf.record.Record newChild)
Add a new child record onto a record's list of children.

		synchronized(changingChildRecordsLock) {
			appendChild(newChild);
		}
	
private intfindChildLocation(org.apache.poi.hslf.record.Record child)
Finds the location of the given child record

		// Synchronized as we don't want things changing 
		//  as we're doing our search
		synchronized(changingChildRecordsLock) {
			for(int i=0; i<_children.length; i++) {
				if(_children[i].equals(child)) {
					return i;
				}
			}
		}	
		return -1;
	
public org.apache.poi.hslf.record.Record[]getChildRecords()
Return any children

	
	     	 
	    return _children; 
public booleanisAnAtom()
We're not an atom

 return false; 
public voidmoveChildBefore(org.apache.poi.hslf.record.Record child, org.apache.poi.hslf.record.Record before)
Moves the given Child Record to before the supplied record

		moveChildrenBefore(child, 1, before);
	
private voidmoveChildRecords(int oldLoc, int newLoc, int number)
Moves number child records from oldLoc to newLoc. Caller must have the changingChildRecordsLock

param
oldLoc the current location of the records to move
param
newLoc the new location for the records
param
number the number of records to move

		if(oldLoc == newLoc) { return; }
		if(number == 0) { return; }
			
		// Check that we're not asked to move too many
		if(oldLoc+number > _children.length) {
			throw new IllegalArgumentException("Asked to move more records than there are!");
		}
		
		// Do the move
		ArrayUtil.arrayMoveWithin(_children, oldLoc, newLoc, number);
	
public voidmoveChildrenAfter(org.apache.poi.hslf.record.Record firstChild, int number, org.apache.poi.hslf.record.Record after)
Moves the given Child Records to after the supplied record

		if(number < 1) { return; }
		
		synchronized(changingChildRecordsLock) {
			// Decide where we're going to put them
			int newLoc = findChildLocation(after);
			if(newLoc == -1) {
				throw new IllegalArgumentException("Asked to move children before another record, but that record wasn't one of our children!");
			}
			// We actually want after this though
			newLoc++;
			
			// Figure out where they are now
			int oldLoc = findChildLocation(firstChild);
			if(oldLoc == -1) {
				throw new IllegalArgumentException("Asked to move a record that wasn't a child!");
			}
			
			// Actually move
			moveChildRecords(oldLoc, newLoc, number);
		}
	
public voidmoveChildrenBefore(org.apache.poi.hslf.record.Record firstChild, int number, org.apache.poi.hslf.record.Record before)
Moves the given Child Records to before the supplied record

		if(number < 1) { return; }
		
		synchronized(changingChildRecordsLock) {
			// Decide where we're going to put them
			int newLoc = findChildLocation(before);
			if(newLoc == -1) {
				throw new IllegalArgumentException("Asked to move children before another record, but that record wasn't one of our children!");
			}
			
			// Figure out where they are now
			int oldLoc = findChildLocation(firstChild);
			if(oldLoc == -1) {
				throw new IllegalArgumentException("Asked to move a record that wasn't a child!");
			}
			
			// Actually move
			moveChildRecords(oldLoc, newLoc, number);
		}
	
public voidwriteOut(byte headerA, byte headerB, long type, org.apache.poi.hslf.record.Record[] children, java.io.OutputStream out)
Write out our header, and our children.

param
headerA the first byte of the header
param
headerB the second byte of the header
param
type the record type
param
children our child records
param
out the stream to write to

		// If we have a mutable output stream, take advantage of that
		if(out instanceof MutableByteArrayOutputStream) {
			MutableByteArrayOutputStream mout = 
				(MutableByteArrayOutputStream)out;

			// Grab current size
			int oldSize = mout.getBytesWritten();

			// Write out our header, less the size
			mout.write(new byte[] {headerA,headerB});
			byte[] typeB = new byte[2];
			LittleEndian.putShort(typeB,(short)type);
			mout.write(typeB);
			mout.write(new byte[4]);

			// Write out the children
			for(int i=0; i<children.length; i++) {
				children[i].writeOut(mout);
			}

			// Update our header with the size
			// Don't forget to knock 8 more off, since we don't include the
			//  header in the size
			int length = mout.getBytesWritten() - oldSize - 8;
			byte[] size = new byte[4];
			LittleEndian.putInt(size,0,length);
			mout.overwrite(size, oldSize+4);
		} else {
			// Going to have to do it a slower way, because we have
			// to update the length come the end

			// Create a ByteArrayOutputStream to hold everything in
			ByteArrayOutputStream baos = new ByteArrayOutputStream();

			// Write out our header, less the size
			baos.write(new byte[] {headerA,headerB});
			byte[] typeB = new byte[2];
			LittleEndian.putShort(typeB,(short)type);
			baos.write(typeB);
			baos.write(new byte[] {0,0,0,0});

			// Write out our children
			for(int i=0; i<children.length; i++) {
				children[i].writeOut(baos);
			}

			// Grab the bytes back
			byte[] toWrite = baos.toByteArray();

			// Update our header with the size
			// Don't forget to knock 8 more off, since we don't include the
			//  header in the size
			LittleEndian.putInt(toWrite,4,(toWrite.length-8));

			// Write out the bytes
			out.write(toWrite);
		}