Improve the child record adding code

git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@386996 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2006-03-19 16:29:31 +00:00
parent 7cfd0162a7
commit 7222245b33

View File

@ -35,6 +35,7 @@ import java.io.ByteArrayOutputStream;
public abstract class RecordContainer extends Record
{
protected Record[] _children;
private Boolean addingChildRecordLock = new Boolean(true);
/**
* Return any children
@ -51,40 +52,101 @@ public abstract class RecordContainer extends Record
* return the new list.
*/
public Record[] appendChildRecord(Record newChild, Record[] children) {
Record[] r = new Record[children.length + 1];
System.arraycopy(children,0,r,0,children.length);
r[r.length-1] = newChild;
Record[] r;
synchronized(addingChildRecordLock) {
r = new Record[children.length + 1];
System.arraycopy(children,0,r,0,children.length);
r[r.length-1] = newChild;
}
return r;
}
/**
* Finds the location of the given child record
*/
private int findChildLocation(Record child) {
// Synchronized as we don't want things changing
// as we're doing our search
synchronized(addingChildRecordLock) {
for(int i=0; i<_children.length; i++) {
if(_children[i].equals(child)) {
return i;
}
}
}
return -1;
}
/**
* Adds the given new Child Record at the given location,
* shuffling everything from there on down by one
* @param newChild
* @param position
*/
private void addChildAt(Record newChild, int position) {
synchronized(addingChildRecordLock) {
Record[] newChildren = new Record[_children.length+1];
// Move over to the new array, shuffling on by one after
// the addition point
for(int i=0; i<_children.length; i++) {
if(i == position) {
newChildren[i] = newChild;
}
if(i >= position) {
newChildren[i+1] = _children[i];
}
if(i < position) {
newChildren[i] = _children[i];
}
}
// Special case - new record goes at the end
if(position == _children.length) {
newChildren[position] = newChild;
}
// All done, replace our child list
_children = newChildren;
}
}
/**
* Adds the given Child Record after the supplied record
* @param newChild
* @param after
*/
public synchronized void addChildAfter(Record newChild, Record after) {
boolean added = false;
Record[] newChildren = new Record[_children.length+1];
for(int i=0; i<_children.length; i++) {
int newPos = i;
if(added) { newPos++; }
newChildren[newPos] = _children[i];
if(_children[i].equals(after)) {
// Found one to add after
added = true;
newPos++;
newChildren[newPos] = newChild;
public void addChildAfter(Record newChild, Record after) {
synchronized(addingChildRecordLock) {
// 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!");
}
}
if(added) {
_children = newChildren;
} else {
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);
}
}
/**
* Adds the given Child Record before the supplied record
* @param newChild
* @param after
*/
public void addChildBefore(Record newChild, Record before) {
synchronized(addingChildRecordLock) {
// 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);
}
}
/**
* Write out our header, and our children.
* @param headerA the first byte of the header