]> source.dussan.org Git - poi.git/commitdiff
Improve the child record adding code
authorNick Burch <nick@apache.org>
Sun, 19 Mar 2006 16:29:31 +0000 (16:29 +0000)
committerNick Burch <nick@apache.org>
Sun, 19 Mar 2006 16:29:31 +0000 (16:29 +0000)
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@386996 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hslf/record/RecordContainer.java

index b3d9dee3fb85482df8fb776e99ada642fdb6b0e7..cd7aa16b326904e4a300c785f2fd37078bdc144a 100644 (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!");
                        }
+                               
+                       // Add one place after the supplied record
+                       addChildAt(newChild, loc+1);
                }
-               
-               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!");
+       }
+       
+       /**
+        * 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