]> source.dussan.org Git - poi.git/commitdiff
More fixes to allow EscherContainerRecord to exclusively maintain 'child records...
authorJosh Micich <josh@apache.org>
Fri, 20 Feb 2009 01:55:47 +0000 (01:55 +0000)
committerJosh Micich <josh@apache.org>
Fri, 20 Feb 2009 01:55:47 +0000 (01:55 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@746085 13f79535-47bb-0310-9956-ffa450edef68

19 files changed:
src/java/org/apache/poi/hssf/model/Workbook.java
src/java/org/apache/poi/hssf/record/AbstractEscherHolderRecord.java
src/java/org/apache/poi/hssf/record/EscherAggregate.java
src/scratchpad/src/org/apache/poi/hslf/dev/SlideShowRecordDumper.java
src/scratchpad/src/org/apache/poi/hslf/model/ActiveXShape.java
src/scratchpad/src/org/apache/poi/hslf/model/Hyperlink.java
src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java
src/scratchpad/src/org/apache/poi/hslf/model/Shape.java
src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java
src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java
src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
src/scratchpad/src/org/apache/poi/hslf/model/Slide.java
src/scratchpad/src/org/apache/poi/hslf/model/Table.java
src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java
src/scratchpad/src/org/apache/poi/hslf/record/PPDrawingGroup.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java
src/testcases/org/apache/poi/ddf/TestEscherBlipRecord.java
src/testcases/org/apache/poi/hssf/record/TestEscherAggregate.java

index 765dc1afd305ba8a53d90d56587339059d6d6476..b2623ee6f3c68d5a8f83926e2c937efb3126d8a7 100644 (file)
@@ -2023,7 +2023,7 @@ public final class Workbook implements Model {
                 }
 
                 EscherDggRecord dgg = null;
-                for(Iterator it = cr.getChildRecords().iterator(); it.hasNext();) {
+                for(Iterator<EscherRecord> it = cr.getChildIterator(); it.hasNext();) {
                     Object er = it.next();
                     if(er instanceof EscherDggRecord) {
                         dgg = (EscherDggRecord)er;
@@ -2150,7 +2150,9 @@ public final class Workbook implements Model {
         {
             bstoreContainer = new EscherContainerRecord();
             bstoreContainer.setRecordId( EscherContainerRecord.BSTORE_CONTAINER );
-            dggContainer.getChildRecords().add( 1, bstoreContainer );
+            List<EscherRecord> childRecords = dggContainer.getChildRecords();
+            childRecords.add(1, bstoreContainer);
+            dggContainer.setChildRecords(childRecords);
         }
         bstoreContainer.setOptions( (short) ( (escherBSERecords.size() << 4) | 0xF ) );
 
@@ -2285,18 +2287,18 @@ public final class Workbook implements Model {
             dgg.setDrawingsSaved(dgg.getDrawingsSaved() + 1);
 
             EscherDgRecord dg = null;
-            for(Iterator it = escherContainer.getChildRecords().iterator(); it.hasNext();) {
-                Object er = it.next();
+            for(Iterator<EscherRecord> it = escherContainer.getChildIterator(); it.hasNext();) {
+                EscherRecord er = it.next();
                 if(er instanceof EscherDgRecord) {
                     dg = (EscherDgRecord)er;
                     //update id of the drawing in the cloned sheet
                     dg.setOptions( (short) ( dgId << 4 ) );
                 } else if (er instanceof EscherContainerRecord){
                     //recursively find shape records and re-generate shapeId
-                    ArrayList spRecords = new ArrayList();
+                    List<EscherRecord> spRecords = new ArrayList<EscherRecord>();
                     EscherContainerRecord cp = (EscherContainerRecord)er;
                     cp.getRecordsById(EscherSpRecord.RECORD_ID,  spRecords);
-                    for(Iterator spIt = spRecords.iterator(); spIt.hasNext();) {
+                    for(Iterator<EscherRecord> spIt = spRecords.iterator(); spIt.hasNext();) {
                         EscherSpRecord sp = (EscherSpRecord)spIt.next();
                         int shapeId = drawingManager.allocateShapeId((short)dgId, dg);
                         //allocateShapeId increments the number of shapes. roll back to the previous value
index 163d1fd6f691e8f9f6b1b0005a7df6c4d1e8e9a5..7bde77cc821b7e2e32b3118f77397df2a8ae0f7b 100644 (file)
@@ -196,21 +196,20 @@ public abstract class AbstractEscherHolderRecord extends Record {
     public EscherRecord findFirstWithId(short id) {
        return findFirstWithId(id, getEscherRecords());
     }
-    private EscherRecord findFirstWithId(short id, List records) {
+    private EscherRecord findFirstWithId(short id, List<EscherRecord> records) {
        // Check at our level
-       for(Iterator it = records.iterator(); it.hasNext();) {
-               EscherRecord r = (EscherRecord)it.next();
+       for(Iterator<EscherRecord> it = records.iterator(); it.hasNext();) {
+               EscherRecord r = it.next();
                if(r.getRecordId() == id) {
                        return r;
                }
        }
        
        // Then check our children in turn
-       for(Iterator it = records.iterator(); it.hasNext();) {
-               EscherRecord r = (EscherRecord)it.next();
+       for(Iterator<EscherRecord> it = records.iterator(); it.hasNext();) {
+               EscherRecord r = it.next();
                if(r.isContainerRecord()) {
-                       EscherRecord found =
-                               findFirstWithId(id, r.getChildRecords());
+                       EscherRecord found = findFirstWithId(id, r.getChildRecords());
                        if(found != null) {
                                return found;
                        }
index 8e6ad4515830cca5ec1a41cd26c2e96e216143ee..e96de6ec72cce6bc18842becb9ba07015ae67a4f 100644 (file)
@@ -70,823 +70,822 @@ import org.apache.poi.util.POILogger;
  * @author Glen Stampoultzis (glens at apache.org)
  */
 public final class EscherAggregate extends AbstractEscherHolderRecord {
-    public static final short sid = 9876; // not a real sid - dummy value
-    private static POILogger log = POILogFactory.getLogger(EscherAggregate.class);
-
-    public static final short ST_MIN = (short) 0;
-    public static final short ST_NOT_PRIMATIVE = ST_MIN;
-    public static final short ST_RECTANGLE = (short) 1;
-    public static final short ST_ROUNDRECTANGLE = (short) 2;
-    public static final short ST_ELLIPSE = (short) 3;
-    public static final short ST_DIAMOND = (short) 4;
-    public static final short ST_ISOCELESTRIANGLE = (short) 5;
-    public static final short ST_RIGHTTRIANGLE = (short) 6;
-    public static final short ST_PARALLELOGRAM = (short) 7;
-    public static final short ST_TRAPEZOID = (short) 8;
-    public static final short ST_HEXAGON = (short) 9;
-    public static final short ST_OCTAGON = (short) 10;
-    public static final short ST_PLUS = (short) 11;
-    public static final short ST_STAR = (short) 12;
-    public static final short ST_ARROW = (short) 13;
-    public static final short ST_THICKARROW = (short) 14;
-    public static final short ST_HOMEPLATE = (short) 15;
-    public static final short ST_CUBE = (short) 16;
-    public static final short ST_BALLOON = (short) 17;
-    public static final short ST_SEAL = (short) 18;
-    public static final short ST_ARC = (short) 19;
-    public static final short ST_LINE = (short) 20;
-    public static final short ST_PLAQUE = (short) 21;
-    public static final short ST_CAN = (short) 22;
-    public static final short ST_DONUT = (short) 23;
-    public static final short ST_TEXTSIMPLE = (short) 24;
-    public static final short ST_TEXTOCTAGON = (short) 25;
-    public static final short ST_TEXTHEXAGON = (short) 26;
-    public static final short ST_TEXTCURVE = (short) 27;
-    public static final short ST_TEXTWAVE = (short) 28;
-    public static final short ST_TEXTRING = (short) 29;
-    public static final short ST_TEXTONCURVE = (short) 30;
-    public static final short ST_TEXTONRING = (short) 31;
-    public static final short ST_STRAIGHTCONNECTOR1 = (short) 32;
-    public static final short ST_BENTCONNECTOR2 = (short) 33;
-    public static final short ST_BENTCONNECTOR3 = (short) 34;
-    public static final short ST_BENTCONNECTOR4 = (short) 35;
-    public static final short ST_BENTCONNECTOR5 = (short) 36;
-    public static final short ST_CURVEDCONNECTOR2 = (short) 37;
-    public static final short ST_CURVEDCONNECTOR3 = (short) 38;
-    public static final short ST_CURVEDCONNECTOR4 = (short) 39;
-    public static final short ST_CURVEDCONNECTOR5 = (short) 40;
-    public static final short ST_CALLOUT1 = (short) 41;
-    public static final short ST_CALLOUT2 = (short) 42;
-    public static final short ST_CALLOUT3 = (short) 43;
-    public static final short ST_ACCENTCALLOUT1 = (short) 44;
-    public static final short ST_ACCENTCALLOUT2 = (short) 45;
-    public static final short ST_ACCENTCALLOUT3 = (short) 46;
-    public static final short ST_BORDERCALLOUT1 = (short) 47;
-    public static final short ST_BORDERCALLOUT2 = (short) 48;
-    public static final short ST_BORDERCALLOUT3 = (short) 49;
-    public static final short ST_ACCENTBORDERCALLOUT1 = (short) 50;
-    public static final short ST_ACCENTBORDERCALLOUT2 = (short) 51;
-    public static final short ST_ACCENTBORDERCALLOUT3 = (short) 52;
-    public static final short ST_RIBBON = (short) 53;
-    public static final short ST_RIBBON2 = (short) 54;
-    public static final short ST_CHEVRON = (short) 55;
-    public static final short ST_PENTAGON = (short) 56;
-    public static final short ST_NOSMOKING = (short) 57;
-    public static final short ST_SEAL8 = (short) 58;
-    public static final short ST_SEAL16 = (short) 59;
-    public static final short ST_SEAL32 = (short) 60;
-    public static final short ST_WEDGERECTCALLOUT = (short) 61;
-    public static final short ST_WEDGERRECTCALLOUT = (short) 62;
-    public static final short ST_WEDGEELLIPSECALLOUT = (short) 63;
-    public static final short ST_WAVE = (short) 64;
-    public static final short ST_FOLDEDCORNER = (short) 65;
-    public static final short ST_LEFTARROW = (short) 66;
-    public static final short ST_DOWNARROW = (short) 67;
-    public static final short ST_UPARROW = (short) 68;
-    public static final short ST_LEFTRIGHTARROW = (short) 69;
-    public static final short ST_UPDOWNARROW = (short) 70;
-    public static final short ST_IRREGULARSEAL1 = (short) 71;
-    public static final short ST_IRREGULARSEAL2 = (short) 72;
-    public static final short ST_LIGHTNINGBOLT = (short) 73;
-    public static final short ST_HEART = (short) 74;
-    public static final short ST_PICTUREFRAME = (short) 75;
-    public static final short ST_QUADARROW = (short) 76;
-    public static final short ST_LEFTARROWCALLOUT = (short) 77;
-    public static final short ST_RIGHTARROWCALLOUT = (short) 78;
-    public static final short ST_UPARROWCALLOUT = (short) 79;
-    public static final short ST_DOWNARROWCALLOUT = (short) 80;
-    public static final short ST_LEFTRIGHTARROWCALLOUT = (short) 81;
-    public static final short ST_UPDOWNARROWCALLOUT = (short) 82;
-    public static final short ST_QUADARROWCALLOUT = (short) 83;
-    public static final short ST_BEVEL = (short) 84;
-    public static final short ST_LEFTBRACKET = (short) 85;
-    public static final short ST_RIGHTBRACKET = (short) 86;
-    public static final short ST_LEFTBRACE = (short) 87;
-    public static final short ST_RIGHTBRACE = (short) 88;
-    public static final short ST_LEFTUPARROW = (short) 89;
-    public static final short ST_BENTUPARROW = (short) 90;
-    public static final short ST_BENTARROW = (short) 91;
-    public static final short ST_SEAL24 = (short) 92;
-    public static final short ST_STRIPEDRIGHTARROW = (short) 93;
-    public static final short ST_NOTCHEDRIGHTARROW = (short) 94;
-    public static final short ST_BLOCKARC = (short) 95;
-    public static final short ST_SMILEYFACE = (short) 96;
-    public static final short ST_VERTICALSCROLL = (short) 97;
-    public static final short ST_HORIZONTALSCROLL = (short) 98;
-    public static final short ST_CIRCULARARROW = (short) 99;
-    public static final short ST_NOTCHEDCIRCULARARROW = (short) 100;
-    public static final short ST_UTURNARROW = (short) 101;
-    public static final short ST_CURVEDRIGHTARROW = (short) 102;
-    public static final short ST_CURVEDLEFTARROW = (short) 103;
-    public static final short ST_CURVEDUPARROW = (short) 104;
-    public static final short ST_CURVEDDOWNARROW = (short) 105;
-    public static final short ST_CLOUDCALLOUT = (short) 106;
-    public static final short ST_ELLIPSERIBBON = (short) 107;
-    public static final short ST_ELLIPSERIBBON2 = (short) 108;
-    public static final short ST_FLOWCHARTPROCESS = (short) 109;
-    public static final short ST_FLOWCHARTDECISION = (short) 110;
-    public static final short ST_FLOWCHARTINPUTOUTPUT = (short) 111;
-    public static final short ST_FLOWCHARTPREDEFINEDPROCESS = (short) 112;
-    public static final short ST_FLOWCHARTINTERNALSTORAGE = (short) 113;
-    public static final short ST_FLOWCHARTDOCUMENT = (short) 114;
-    public static final short ST_FLOWCHARTMULTIDOCUMENT = (short) 115;
-    public static final short ST_FLOWCHARTTERMINATOR = (short) 116;
-    public static final short ST_FLOWCHARTPREPARATION = (short) 117;
-    public static final short ST_FLOWCHARTMANUALINPUT = (short) 118;
-    public static final short ST_FLOWCHARTMANUALOPERATION = (short) 119;
-    public static final short ST_FLOWCHARTCONNECTOR = (short) 120;
-    public static final short ST_FLOWCHARTPUNCHEDCARD = (short) 121;
-    public static final short ST_FLOWCHARTPUNCHEDTAPE = (short) 122;
-    public static final short ST_FLOWCHARTSUMMINGJUNCTION = (short) 123;
-    public static final short ST_FLOWCHARTOR = (short) 124;
-    public static final short ST_FLOWCHARTCOLLATE = (short) 125;
-    public static final short ST_FLOWCHARTSORT = (short) 126;
-    public static final short ST_FLOWCHARTEXTRACT = (short) 127;
-    public static final short ST_FLOWCHARTMERGE = (short) 128;
-    public static final short ST_FLOWCHARTOFFLINESTORAGE = (short) 129;
-    public static final short ST_FLOWCHARTONLINESTORAGE = (short) 130;
-    public static final short ST_FLOWCHARTMAGNETICTAPE = (short) 131;
-    public static final short ST_FLOWCHARTMAGNETICDISK = (short) 132;
-    public static final short ST_FLOWCHARTMAGNETICDRUM = (short) 133;
-    public static final short ST_FLOWCHARTDISPLAY = (short) 134;
-    public static final short ST_FLOWCHARTDELAY = (short) 135;
-    public static final short ST_TEXTPLAINTEXT = (short) 136;
-    public static final short ST_TEXTSTOP = (short) 137;
-    public static final short ST_TEXTTRIANGLE = (short) 138;
-    public static final short ST_TEXTTRIANGLEINVERTED = (short) 139;
-    public static final short ST_TEXTCHEVRON = (short) 140;
-    public static final short ST_TEXTCHEVRONINVERTED = (short) 141;
-    public static final short ST_TEXTRINGINSIDE = (short) 142;
-    public static final short ST_TEXTRINGOUTSIDE = (short) 143;
-    public static final short ST_TEXTARCHUPCURVE = (short) 144;
-    public static final short ST_TEXTARCHDOWNCURVE = (short) 145;
-    public static final short ST_TEXTCIRCLECURVE = (short) 146;
-    public static final short ST_TEXTBUTTONCURVE = (short) 147;
-    public static final short ST_TEXTARCHUPPOUR = (short) 148;
-    public static final short ST_TEXTARCHDOWNPOUR = (short) 149;
-    public static final short ST_TEXTCIRCLEPOUR = (short) 150;
-    public static final short ST_TEXTBUTTONPOUR = (short) 151;
-    public static final short ST_TEXTCURVEUP = (short) 152;
-    public static final short ST_TEXTCURVEDOWN = (short) 153;
-    public static final short ST_TEXTCASCADEUP = (short) 154;
-    public static final short ST_TEXTCASCADEDOWN = (short) 155;
-    public static final short ST_TEXTWAVE1 = (short) 156;
-    public static final short ST_TEXTWAVE2 = (short) 157;
-    public static final short ST_TEXTWAVE3 = (short) 158;
-    public static final short ST_TEXTWAVE4 = (short) 159;
-    public static final short ST_TEXTINFLATE = (short) 160;
-    public static final short ST_TEXTDEFLATE = (short) 161;
-    public static final short ST_TEXTINFLATEBOTTOM = (short) 162;
-    public static final short ST_TEXTDEFLATEBOTTOM = (short) 163;
-    public static final short ST_TEXTINFLATETOP = (short) 164;
-    public static final short ST_TEXTDEFLATETOP = (short) 165;
-    public static final short ST_TEXTDEFLATEINFLATE = (short) 166;
-    public static final short ST_TEXTDEFLATEINFLATEDEFLATE = (short) 167;
-    public static final short ST_TEXTFADERIGHT = (short) 168;
-    public static final short ST_TEXTFADELEFT = (short) 169;
-    public static final short ST_TEXTFADEUP = (short) 170;
-    public static final short ST_TEXTFADEDOWN = (short) 171;
-    public static final short ST_TEXTSLANTUP = (short) 172;
-    public static final short ST_TEXTSLANTDOWN = (short) 173;
-    public static final short ST_TEXTCANUP = (short) 174;
-    public static final short ST_TEXTCANDOWN = (short) 175;
-    public static final short ST_FLOWCHARTALTERNATEPROCESS = (short) 176;
-    public static final short ST_FLOWCHARTOFFPAGECONNECTOR = (short) 177;
-    public static final short ST_CALLOUT90 = (short) 178;
-    public static final short ST_ACCENTCALLOUT90 = (short) 179;
-    public static final short ST_BORDERCALLOUT90 = (short) 180;
-    public static final short ST_ACCENTBORDERCALLOUT90 = (short) 181;
-    public static final short ST_LEFTRIGHTUPARROW = (short) 182;
-    public static final short ST_SUN = (short) 183;
-    public static final short ST_MOON = (short) 184;
-    public static final short ST_BRACKETPAIR = (short) 185;
-    public static final short ST_BRACEPAIR = (short) 186;
-    public static final short ST_SEAL4 = (short) 187;
-    public static final short ST_DOUBLEWAVE = (short) 188;
-    public static final short ST_ACTIONBUTTONBLANK = (short) 189;
-    public static final short ST_ACTIONBUTTONHOME = (short) 190;
-    public static final short ST_ACTIONBUTTONHELP = (short) 191;
-    public static final short ST_ACTIONBUTTONINFORMATION = (short) 192;
-    public static final short ST_ACTIONBUTTONFORWARDNEXT = (short) 193;
-    public static final short ST_ACTIONBUTTONBACKPREVIOUS = (short) 194;
-    public static final short ST_ACTIONBUTTONEND = (short) 195;
-    public static final short ST_ACTIONBUTTONBEGINNING = (short) 196;
-    public static final short ST_ACTIONBUTTONRETURN = (short) 197;
-    public static final short ST_ACTIONBUTTONDOCUMENT = (short) 198;
-    public static final short ST_ACTIONBUTTONSOUND = (short) 199;
-    public static final short ST_ACTIONBUTTONMOVIE = (short) 200;
-    public static final short ST_HOSTCONTROL = (short) 201;
-    public static final short ST_TEXTBOX = (short) 202;
-    public static final short ST_NIL = (short) 0x0FFF;
-
-    protected HSSFPatriarch patriarch;
-
-    /** Maps shape container objects to their OBJ records */
-    private Map shapeToObj = new HashMap();
-    private DrawingManager2 drawingManager;
-    private short drawingGroupId;
-
-    /**
-     * list of "tail" records that need to be serialized after all drawing group records
-     */
-    private List tailRec = new ArrayList();
-
-    public EscherAggregate( DrawingManager2 drawingManager )
-    {
-        this.drawingManager = drawingManager;
-    }
-
-    /**
-     * @return  Returns the current sid.
-     */
-    public short getSid()
-    {
-        return sid;
-    }
-
-    /**
-     * Calculates the string representation of this record.  This is
-     * simply a dump of all the records.
-     */
-    public String toString()
-    {
-        String nl = System.getProperty( "line.separtor" );
-
-        StringBuffer result = new StringBuffer();
-        result.append( '[' ).append( getRecordName() ).append( ']' + nl );
-        for ( Iterator iterator = getEscherRecords().iterator(); iterator.hasNext(); )
-        {
-            EscherRecord escherRecord = (EscherRecord) iterator.next();
-            result.append( escherRecord.toString() );
-        }
-        result.append( "[/" ).append( getRecordName() ).append( ']' + nl );
-
-        return result.toString();
-    }
-
-    /**
-     * Collapses the drawing records into an aggregate.
-     */
-    public static EscherAggregate createAggregate( List records, int locFirstDrawingRecord, DrawingManager2 drawingManager )
-    {
-        // Keep track of any shape records created so we can match them back to the object id's.
-        // Textbox objects are also treated as shape objects.
-        final List shapeRecords = new ArrayList();
-        EscherRecordFactory recordFactory = new DefaultEscherRecordFactory()
-        {
-            public EscherRecord createRecord( byte[] data, int offset )
-            {
-                EscherRecord r = super.createRecord( data, offset );
-                if ( r.getRecordId() == EscherClientDataRecord.RECORD_ID || r.getRecordId() == EscherTextboxRecord.RECORD_ID )
-                {
-                    shapeRecords.add( r );
-                }
-                return r;
-            }
-        };
-
-        // Calculate the size of the buffer
-        EscherAggregate agg = new EscherAggregate(drawingManager);
-        int loc = locFirstDrawingRecord;
-        int dataSize = 0;
-        while ( loc + 1 < records.size()
-                && sid( records, loc ) == DrawingRecord.sid
-                && isObjectRecord( records, loc + 1 ) )
-        {
-            dataSize += ( (DrawingRecord) records.get( loc ) ).getData().length;
-            loc += 2;
-        }
-
-        // Create one big buffer
-        byte buffer[] = new byte[dataSize];
-        int offset = 0;
-        loc = locFirstDrawingRecord;
-        while ( loc + 1 < records.size()
-                && sid( records, loc ) == DrawingRecord.sid
-                && isObjectRecord( records, loc + 1 ) )
-        {
-            DrawingRecord drawingRecord = (DrawingRecord) records.get( loc );
-            System.arraycopy( drawingRecord.getData(), 0, buffer, offset, drawingRecord.getData().length );
-            offset += drawingRecord.getData().length;
-            loc += 2;
-        }
-
-        // Decode the shapes
-        //        agg.escherRecords = new ArrayList();
-        int pos = 0;
-        while ( pos < dataSize )
-        {
-            EscherRecord r = recordFactory.createRecord( buffer, pos );
-            int bytesRead = r.fillFields( buffer, pos, recordFactory );
-            agg.addEscherRecord( r );
-            pos += bytesRead;
-        }
-
-        // Associate the object records with the shapes
-        loc = locFirstDrawingRecord;
-        int shapeIndex = 0;
-        agg.shapeToObj = new HashMap();
-        while ( loc + 1 < records.size()
-                && sid( records, loc ) == DrawingRecord.sid
-                && isObjectRecord( records, loc + 1 ) )
-        {
-            Record objRecord = (Record) records.get( loc + 1 );
-            agg.shapeToObj.put( shapeRecords.get( shapeIndex++ ), objRecord );
-            loc += 2;
-        }
-
-        return agg;
-
-    }
-
-    /**
-     * Serializes this aggregate to a byte array.  Since this is an aggregate
-     * record it will effectively serialize the aggregated records.
-     *
-     * @param offset    The offset into the start of the array.
-     * @param data      The byte array to serialize to.
-     * @return          The number of bytes serialized.
-     */
-    public int serialize( int offset, byte[] data )
-    {
-        convertUserModelToRecords();
-
-        // Determine buffer size
-        List records = getEscherRecords();
-        int size = getEscherRecordSize( records );
-        byte[] buffer = new byte[size];
-
-
-        // Serialize escher records into one big data structure and keep note of ending offsets.
-        final List spEndingOffsets = new ArrayList();
-        final List shapes = new ArrayList();
-        int pos = 0;
-        for ( Iterator iterator = records.iterator(); iterator.hasNext(); )
-        {
-            EscherRecord e = (EscherRecord) iterator.next();
-            pos += e.serialize( pos, buffer, new EscherSerializationListener()
-            {
-                public void beforeRecordSerialize( int offset, short recordId, EscherRecord record )
-                {
-                }
-
-                public void afterRecordSerialize( int offset, short recordId, int size, EscherRecord record )
-                {
-                    if ( recordId == EscherClientDataRecord.RECORD_ID || recordId == EscherTextboxRecord.RECORD_ID )
-                    {
-                        spEndingOffsets.add( new Integer( offset ) );
-                        shapes.add( record );
-                    }
-                }
-            } );
-        }
-        // todo: fix this
-        shapes.add( 0, null );
-        spEndingOffsets.add( 0, null );
-
-        // Split escher records into separate MSODRAWING and OBJ, TXO records.  (We don't break on
-        // the first one because it's the patriach).
-        pos = offset;
-        for ( int i = 1; i < shapes.size(); i++ )
-        {
-            int endOffset = ( (Integer) spEndingOffsets.get( i ) ).intValue() - 1;
-            int startOffset;
-            if ( i == 1 )
-                startOffset = 0;
-            else
-                startOffset = ( (Integer) spEndingOffsets.get( i - 1 ) ).intValue();
-
-            // Create and write a new MSODRAWING record
-            DrawingRecord drawing = new DrawingRecord();
-            byte[] drawingData = new byte[endOffset - startOffset + 1];
-            System.arraycopy( buffer, startOffset, drawingData, 0, drawingData.length );
-            drawing.setData( drawingData );
-            int temp = drawing.serialize( pos, data );
-            pos += temp;
-
-            // Write the matching OBJ record
-            Record obj = (Record) shapeToObj.get( shapes.get( i ) );
-            temp = obj.serialize( pos, data );
-            pos += temp;
-
-        }
-
-        // write records that need to be serialized after all drawing group records
-        for ( int i = 0; i < tailRec.size(); i++ )
-        {
-            Record rec = (Record)tailRec.get(i);
-            pos += rec.serialize( pos, data );
-        }
-
-        int bytesWritten = pos - offset;
-        if ( bytesWritten != getRecordSize() )
-            throw new RecordFormatException( bytesWritten + " bytes written but getRecordSize() reports " + getRecordSize() );
-        return bytesWritten;
-    }
-
-    /**
-     * How many bytes do the raw escher records contain.
-     * @param records   List of escher records
-     * @return  the number of bytes
-     */
-    private int getEscherRecordSize( List records )
-    {
-        int size = 0;
-        for ( Iterator iterator = records.iterator(); iterator.hasNext(); )
-            size += ( (EscherRecord) iterator.next() ).getRecordSize();
-        return size;
-    }
-
-    public int getRecordSize() {
-        // TODO - convert this to RecordAggregate
-        convertUserModelToRecords();
-        List records = getEscherRecords();
-        int rawEscherSize = getEscherRecordSize( records );
-        int drawingRecordSize = rawEscherSize + ( shapeToObj.size() ) * 4;
-        int objRecordSize = 0;
-        for ( Iterator iterator = shapeToObj.values().iterator(); iterator.hasNext(); )
-        {
-            Record r = (Record) iterator.next();
-            objRecordSize += r.getRecordSize();
-        }
-        int tailRecordSize = 0;
-        for ( Iterator iterator = tailRec.iterator(); iterator.hasNext(); )
-        {
-            Record r = (Record) iterator.next();
-            tailRecordSize += r.getRecordSize();
-        }
-        return drawingRecordSize + objRecordSize + tailRecordSize;
-    }
-
-    /**
-     * Associates an escher record to an OBJ record or a TXO record.
-     */
-    public Object assoicateShapeToObjRecord( EscherRecord r, Record objRecord )
-    {
-        return shapeToObj.put( r, objRecord );
-    }
-
-    public HSSFPatriarch getPatriarch()
-    {
-        return patriarch;
-    }
-
-    public void setPatriarch( HSSFPatriarch patriarch )
-    {
-        this.patriarch = patriarch;
-    }
-    
-    /**
-     * Converts the Records into UserModel
-     *  objects on the bound HSSFPatriarch
-     */
-    public void convertRecordsToUserModel() {
-       if(patriarch == null) {
-               throw new IllegalStateException("Must call setPatriarch() first");
-       }
-       
-       // The top level container ought to have
-       //  the DgRecord and the container of one container
-       //  per shape group (patriach overall first)
-       EscherContainerRecord topContainer = getEscherContainer();
-       if(topContainer == null) {
-               return;
-       }
-       topContainer = (EscherContainerRecord) 
-               topContainer.getChildContainers().get(0);
-       
-       List tcc = topContainer.getChildContainers();
-       if(tcc.size() == 0) {
-               throw new IllegalStateException("No child escher containers at the point that should hold the patriach data, and one container per top level shape!");
-       }
-       
-       // First up, get the patriach position
-       // This is in the first EscherSpgrRecord, in
-       //  the first container, with a EscherSRecord too
-       EscherContainerRecord patriachContainer =
-               (EscherContainerRecord)tcc.get(0);
-       EscherSpgrRecord spgr = null;
-       for(Iterator it = patriachContainer.getChildRecords().iterator(); it.hasNext();) {
-               EscherRecord r = (EscherRecord)it.next();
-               if(r instanceof EscherSpgrRecord) {
-                       spgr = (EscherSpgrRecord)r;
-                       break;
-               }
-       }
-       if(spgr != null) {
-               patriarch.setCoordinates(
-                               spgr.getRectX1(), spgr.getRectY1(),
-                               spgr.getRectX2(), spgr.getRectY2()
-               );
-       }
-       
-       // Now process the containers for each group
-       //  and objects
-       for(int i=1; i<tcc.size(); i++) {
-               EscherContainerRecord shapeContainer =
-                       (EscherContainerRecord)tcc.get(i);
-               //System.err.println("\n\n*****\n\n");
-               //System.err.println(shapeContainer);
-               
-               // Could be a group, or a base object
-               if(shapeContainer.getChildRecords().size() == 1 &&
-                               shapeContainer.getChildContainers().size() == 1) {
-                       // Group
-                       HSSFShapeGroup group =
-                               new HSSFShapeGroup(null, new HSSFClientAnchor());
-                       patriarch.getChildren().add(group);
-                       
-                       EscherContainerRecord groupContainer =
-                               (EscherContainerRecord)shapeContainer.getChild(0);
-                       convertRecordsToUserModel(groupContainer, group);
-               } else if(shapeContainer.hasChildOfType((short)0xF00D)) {
-                       // TextBox
-                       HSSFTextbox box =
-                               new HSSFTextbox(null, new HSSFClientAnchor());
-                       patriarch.getChildren().add(box);
-                       
-                       convertRecordsToUserModel(shapeContainer, box);
-               } else if(shapeContainer.hasChildOfType((short)0xF011)) {
-                       // Not yet supporting EscherClientDataRecord stuff
-               } else {
-                       // Base level
-                       convertRecordsToUserModel(shapeContainer, patriarch);
-               }
-       }
-       
-       // Now, clear any trace of what records make up
-       //  the patriarch
-       // Otherwise, everything will go horribly wrong
-       //  when we try to write out again....
-//     clearEscherRecords();
-       drawingManager.getDgg().setFileIdClusters(new EscherDggRecord.FileIdCluster[0]);
-
-       // TODO: Support converting our records
-       //  back into shapes
-       log.log(POILogger.WARN, "Not processing objects into Patriarch!");
-    }
-    
-    private void convertRecordsToUserModel(EscherContainerRecord shapeContainer, Object model) {
-       for(Iterator it = shapeContainer.getChildRecords().iterator(); it.hasNext();) {
-               EscherRecord r = (EscherRecord)it.next();
-               if(r instanceof EscherSpgrRecord) {
-                       // This may be overriden by a later EscherClientAnchorRecord
-                       EscherSpgrRecord spgr = (EscherSpgrRecord)r;
-                       
-                       if(model instanceof HSSFShapeGroup) {
-                               HSSFShapeGroup g = (HSSFShapeGroup)model;
-                               g.setCoordinates(
-                                               spgr.getRectX1(), spgr.getRectY1(),
-                                               spgr.getRectX2(), spgr.getRectY2()
-                               );
-                       } else {
-                               throw new IllegalStateException("Got top level anchor but not processing a group");
-                       }
-               } 
-               else if(r instanceof EscherClientAnchorRecord) {
-                       EscherClientAnchorRecord car = (EscherClientAnchorRecord)r;
-                       
-                       if(model instanceof HSSFShape) {
-                               HSSFShape g = (HSSFShape)model;
-                               g.getAnchor().setDx1(car.getDx1());
-                               g.getAnchor().setDx2(car.getDx2());
-                               g.getAnchor().setDy1(car.getDy1());
-                               g.getAnchor().setDy2(car.getDy2());
-                       } else {
-                               throw new IllegalStateException("Got top level anchor but not processing a group or shape");
-                       }
-               }
-               else if(r instanceof EscherTextboxRecord) {
-                       EscherTextboxRecord tbr = (EscherTextboxRecord)r;
-                       
-                       // Also need to find the TextObjectRecord too
-                       // TODO
-               }
-               else if(r instanceof EscherSpRecord) {
-                       // Use flags if needed
-               }
-               else if(r instanceof EscherOptRecord) {
-                       // Use properties if needed
-               }
-               else {
-                       //System.err.println(r);
-               }
-       }
-    }
-    
-    public void clear()
-    {
-        clearEscherRecords();
-        shapeToObj.clear();
-//        lastShapeId = 1024;
-    }
-
-    protected String getRecordName()
-    {
-        return "ESCHERAGGREGATE";
-    }
-
-    // =============== Private methods ========================
-
-    private static boolean isObjectRecord( List records, int loc )
-    {
-        return sid( records, loc ) == ObjRecord.sid || sid( records, loc ) == TextObjectRecord.sid;
-    }
-
-    private void convertUserModelToRecords()
-    {
-        if ( patriarch != null )
-        {
-            shapeToObj.clear();
-            tailRec.clear();
-            clearEscherRecords();
-            if ( patriarch.getChildren().size() != 0 )
-            {
-                convertPatriarch( patriarch );
-                EscherContainerRecord dgContainer = (EscherContainerRecord) getEscherRecord( 0 );
-                EscherContainerRecord spgrContainer = null;
-                for ( int i = 0; i < dgContainer.getChildRecords().size(); i++ )
-                    if ( dgContainer.getChild( i ).getRecordId() == EscherContainerRecord.SPGR_CONTAINER )
-                        spgrContainer = (EscherContainerRecord) dgContainer.getChild( i );
-                convertShapes( patriarch, spgrContainer, shapeToObj );
-
-                patriarch = null;
-            }
-        }
-    }
-
-    private void convertShapes( HSSFShapeContainer parent, EscherContainerRecord escherParent, Map shapeToObj )
-    {
-        if ( escherParent == null ) throw new IllegalArgumentException( "Parent record required" );
-
-        List shapes = parent.getChildren();
-        for ( Iterator iterator = shapes.iterator(); iterator.hasNext(); )
-        {
-            HSSFShape shape = (HSSFShape) iterator.next();
-            if ( shape instanceof HSSFShapeGroup )
-            {
-                convertGroup( (HSSFShapeGroup) shape, escherParent, shapeToObj );
-            }
-            else
-            {
-                AbstractShape shapeModel = AbstractShape.createShape(
-                        shape,
-                        drawingManager.allocateShapeId(drawingGroupId) );
-                shapeToObj.put( findClientData( shapeModel.getSpContainer() ), shapeModel.getObjRecord() );
-                if ( shapeModel instanceof TextboxShape )
-                {
-                    EscherRecord escherTextbox = ( (TextboxShape) shapeModel ).getEscherTextbox();
-                    shapeToObj.put( escherTextbox, ( (TextboxShape) shapeModel ).getTextObjectRecord() );
-                    //                    escherParent.addChildRecord(escherTextbox);
-                    
-                    if ( shapeModel instanceof CommentShape ){
-                        CommentShape comment = (CommentShape)shapeModel;
-                        tailRec.add(comment.getNoteRecord());
-                    }
-
-                }
-                escherParent.addChildRecord( shapeModel.getSpContainer() );
-            }
-        }
-//        drawingManager.newCluster( (short)1 );
-//        drawingManager.newCluster( (short)2 );
-
-    }
-
-    private void convertGroup( HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj )
-    {
-        EscherContainerRecord spgrContainer = new EscherContainerRecord();
-        EscherContainerRecord spContainer = new EscherContainerRecord();
-        EscherSpgrRecord spgr = new EscherSpgrRecord();
-        EscherSpRecord sp = new EscherSpRecord();
-        EscherOptRecord opt = new EscherOptRecord();
-        EscherRecord anchor;
-        EscherClientDataRecord clientData = new EscherClientDataRecord();
-
-        spgrContainer.setRecordId( EscherContainerRecord.SPGR_CONTAINER );
-        spgrContainer.setOptions( (short) 0x000F );
-        spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
-        spContainer.setOptions( (short) 0x000F );
-        spgr.setRecordId( EscherSpgrRecord.RECORD_ID );
-        spgr.setOptions( (short) 0x0001 );
-        spgr.setRectX1( shape.getX1() );
-        spgr.setRectY1( shape.getY1() );
-        spgr.setRectX2( shape.getX2() );
-        spgr.setRectY2( shape.getY2() );
-        sp.setRecordId( EscherSpRecord.RECORD_ID );
-        sp.setOptions( (short) 0x0002 );
-        int shapeId = drawingManager.allocateShapeId(drawingGroupId);
-        sp.setShapeId( shapeId );
-        if (shape.getAnchor() instanceof HSSFClientAnchor)
-            sp.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR );
-        else
-            sp.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD );
-        opt.setRecordId( EscherOptRecord.RECORD_ID );
-        opt.setOptions( (short) 0x0023 );
-        opt.addEscherProperty( new EscherBoolProperty( EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004 ) );
-        opt.addEscherProperty( new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x00080000 ) );
-
-        anchor = ConvertAnchor.createAnchor( shape.getAnchor() );
-//        clientAnchor.setCol1( ( (HSSFClientAnchor) shape.getAnchor() ).getCol1() );
-//        clientAnchor.setRow1( (short) ( (HSSFClientAnchor) shape.getAnchor() ).getRow1() );
-//        clientAnchor.setDx1( (short) shape.getAnchor().getDx1() );
-//        clientAnchor.setDy1( (short) shape.getAnchor().getDy1() );
-//        clientAnchor.setCol2( ( (HSSFClientAnchor) shape.getAnchor() ).getCol2() );
-//        clientAnchor.setRow2( (short) ( (HSSFClientAnchor) shape.getAnchor() ).getRow2() );
-//        clientAnchor.setDx2( (short) shape.getAnchor().getDx2() );
-//        clientAnchor.setDy2( (short) shape.getAnchor().getDy2() );
-        clientData.setRecordId( EscherClientDataRecord.RECORD_ID );
-        clientData.setOptions( (short) 0x0000 );
-
-        spgrContainer.addChildRecord( spContainer );
-        spContainer.addChildRecord( spgr );
-        spContainer.addChildRecord( sp );
-        spContainer.addChildRecord( opt );
-        spContainer.addChildRecord( anchor );
-        spContainer.addChildRecord( clientData );
-
-        ObjRecord obj = new ObjRecord();
-        CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord();
-        cmo.setObjectType( CommonObjectDataSubRecord.OBJECT_TYPE_GROUP );
-        cmo.setObjectId( (short) ( shapeId ) );
-        cmo.setLocked( true );
-        cmo.setPrintable( true );
-        cmo.setAutofill( true );
-        cmo.setAutoline( true );
-        GroupMarkerSubRecord gmo = new GroupMarkerSubRecord();
-        EndSubRecord end = new EndSubRecord();
-        obj.addSubRecord( cmo );
-        obj.addSubRecord( gmo );
-        obj.addSubRecord( end );
-        shapeToObj.put( clientData, obj );
-
-        escherParent.addChildRecord( spgrContainer );
-
-        convertShapes( shape, spgrContainer, shapeToObj );
-
-    }
-
-    private EscherRecord findClientData( EscherContainerRecord spContainer )
-    {
-        for ( Iterator iterator = spContainer.getChildRecords().iterator(); iterator.hasNext(); )
-        {
-            EscherRecord r = (EscherRecord) iterator.next();
-            if ( r.getRecordId() == EscherClientDataRecord.RECORD_ID )
-                return r;
-        }
-        throw new IllegalArgumentException( "Can not find client data record" );
-    }
-
-    private void convertPatriarch( HSSFPatriarch patriarch )
-    {
-        EscherContainerRecord dgContainer = new EscherContainerRecord();
-        EscherDgRecord dg;
-        EscherContainerRecord spgrContainer = new EscherContainerRecord();
-        EscherContainerRecord spContainer1 = new EscherContainerRecord();
-        EscherSpgrRecord spgr = new EscherSpgrRecord();
-        EscherSpRecord sp1 = new EscherSpRecord();
-
-        dgContainer.setRecordId( EscherContainerRecord.DG_CONTAINER );
-        dgContainer.setOptions( (short) 0x000F );
-        dg = drawingManager.createDgRecord();
-        drawingGroupId = dg.getDrawingGroupId();
-//        dg.setOptions( (short) ( drawingId << 4 ) );
-//        dg.setNumShapes( getNumberOfShapes( patriarch ) );
-//        dg.setLastMSOSPID( 0 );  // populated after all shape id's are assigned.
-        spgrContainer.setRecordId( EscherContainerRecord.SPGR_CONTAINER );
-        spgrContainer.setOptions( (short) 0x000F );
-        spContainer1.setRecordId( EscherContainerRecord.SP_CONTAINER );
-        spContainer1.setOptions( (short) 0x000F );
-        spgr.setRecordId( EscherSpgrRecord.RECORD_ID );
-        spgr.setOptions( (short) 0x0001 );    // version
-        spgr.setRectX1( patriarch.getX1() );
-        spgr.setRectY1( patriarch.getY1() );
-        spgr.setRectX2( patriarch.getX2() );
-        spgr.setRectY2( patriarch.getY2() );
-        sp1.setRecordId( EscherSpRecord.RECORD_ID );
-        sp1.setOptions( (short) 0x0002 );
-        sp1.setShapeId( drawingManager.allocateShapeId(dg.getDrawingGroupId()) );
-        sp1.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_PATRIARCH );
-
-        dgContainer.addChildRecord( dg );
-        dgContainer.addChildRecord( spgrContainer );
-        spgrContainer.addChildRecord( spContainer1 );
-        spContainer1.addChildRecord( spgr );
-        spContainer1.addChildRecord( sp1 );
-
-        addEscherRecord( dgContainer );
-    }
-
-    /** Retrieve the number of shapes (including the patriarch). */
-//    private int getNumberOfShapes( HSSFPatriarch patriarch )
-//    {
-//        return patriarch.countOfAllChildren();
-//    }
-
-    private static short sid( List records, int loc )
-    {
-        return ( (Record) records.get( loc ) ).getSid();
-    }
+       public static final short sid = 9876; // not a real sid - dummy value
+       private static POILogger log = POILogFactory.getLogger(EscherAggregate.class);
+
+       public static final short ST_MIN = (short) 0;
+       public static final short ST_NOT_PRIMATIVE = ST_MIN;
+       public static final short ST_RECTANGLE = (short) 1;
+       public static final short ST_ROUNDRECTANGLE = (short) 2;
+       public static final short ST_ELLIPSE = (short) 3;
+       public static final short ST_DIAMOND = (short) 4;
+       public static final short ST_ISOCELESTRIANGLE = (short) 5;
+       public static final short ST_RIGHTTRIANGLE = (short) 6;
+       public static final short ST_PARALLELOGRAM = (short) 7;
+       public static final short ST_TRAPEZOID = (short) 8;
+       public static final short ST_HEXAGON = (short) 9;
+       public static final short ST_OCTAGON = (short) 10;
+       public static final short ST_PLUS = (short) 11;
+       public static final short ST_STAR = (short) 12;
+       public static final short ST_ARROW = (short) 13;
+       public static final short ST_THICKARROW = (short) 14;
+       public static final short ST_HOMEPLATE = (short) 15;
+       public static final short ST_CUBE = (short) 16;
+       public static final short ST_BALLOON = (short) 17;
+       public static final short ST_SEAL = (short) 18;
+       public static final short ST_ARC = (short) 19;
+       public static final short ST_LINE = (short) 20;
+       public static final short ST_PLAQUE = (short) 21;
+       public static final short ST_CAN = (short) 22;
+       public static final short ST_DONUT = (short) 23;
+       public static final short ST_TEXTSIMPLE = (short) 24;
+       public static final short ST_TEXTOCTAGON = (short) 25;
+       public static final short ST_TEXTHEXAGON = (short) 26;
+       public static final short ST_TEXTCURVE = (short) 27;
+       public static final short ST_TEXTWAVE = (short) 28;
+       public static final short ST_TEXTRING = (short) 29;
+       public static final short ST_TEXTONCURVE = (short) 30;
+       public static final short ST_TEXTONRING = (short) 31;
+       public static final short ST_STRAIGHTCONNECTOR1 = (short) 32;
+       public static final short ST_BENTCONNECTOR2 = (short) 33;
+       public static final short ST_BENTCONNECTOR3 = (short) 34;
+       public static final short ST_BENTCONNECTOR4 = (short) 35;
+       public static final short ST_BENTCONNECTOR5 = (short) 36;
+       public static final short ST_CURVEDCONNECTOR2 = (short) 37;
+       public static final short ST_CURVEDCONNECTOR3 = (short) 38;
+       public static final short ST_CURVEDCONNECTOR4 = (short) 39;
+       public static final short ST_CURVEDCONNECTOR5 = (short) 40;
+       public static final short ST_CALLOUT1 = (short) 41;
+       public static final short ST_CALLOUT2 = (short) 42;
+       public static final short ST_CALLOUT3 = (short) 43;
+       public static final short ST_ACCENTCALLOUT1 = (short) 44;
+       public static final short ST_ACCENTCALLOUT2 = (short) 45;
+       public static final short ST_ACCENTCALLOUT3 = (short) 46;
+       public static final short ST_BORDERCALLOUT1 = (short) 47;
+       public static final short ST_BORDERCALLOUT2 = (short) 48;
+       public static final short ST_BORDERCALLOUT3 = (short) 49;
+       public static final short ST_ACCENTBORDERCALLOUT1 = (short) 50;
+       public static final short ST_ACCENTBORDERCALLOUT2 = (short) 51;
+       public static final short ST_ACCENTBORDERCALLOUT3 = (short) 52;
+       public static final short ST_RIBBON = (short) 53;
+       public static final short ST_RIBBON2 = (short) 54;
+       public static final short ST_CHEVRON = (short) 55;
+       public static final short ST_PENTAGON = (short) 56;
+       public static final short ST_NOSMOKING = (short) 57;
+       public static final short ST_SEAL8 = (short) 58;
+       public static final short ST_SEAL16 = (short) 59;
+       public static final short ST_SEAL32 = (short) 60;
+       public static final short ST_WEDGERECTCALLOUT = (short) 61;
+       public static final short ST_WEDGERRECTCALLOUT = (short) 62;
+       public static final short ST_WEDGEELLIPSECALLOUT = (short) 63;
+       public static final short ST_WAVE = (short) 64;
+       public static final short ST_FOLDEDCORNER = (short) 65;
+       public static final short ST_LEFTARROW = (short) 66;
+       public static final short ST_DOWNARROW = (short) 67;
+       public static final short ST_UPARROW = (short) 68;
+       public static final short ST_LEFTRIGHTARROW = (short) 69;
+       public static final short ST_UPDOWNARROW = (short) 70;
+       public static final short ST_IRREGULARSEAL1 = (short) 71;
+       public static final short ST_IRREGULARSEAL2 = (short) 72;
+       public static final short ST_LIGHTNINGBOLT = (short) 73;
+       public static final short ST_HEART = (short) 74;
+       public static final short ST_PICTUREFRAME = (short) 75;
+       public static final short ST_QUADARROW = (short) 76;
+       public static final short ST_LEFTARROWCALLOUT = (short) 77;
+       public static final short ST_RIGHTARROWCALLOUT = (short) 78;
+       public static final short ST_UPARROWCALLOUT = (short) 79;
+       public static final short ST_DOWNARROWCALLOUT = (short) 80;
+       public static final short ST_LEFTRIGHTARROWCALLOUT = (short) 81;
+       public static final short ST_UPDOWNARROWCALLOUT = (short) 82;
+       public static final short ST_QUADARROWCALLOUT = (short) 83;
+       public static final short ST_BEVEL = (short) 84;
+       public static final short ST_LEFTBRACKET = (short) 85;
+       public static final short ST_RIGHTBRACKET = (short) 86;
+       public static final short ST_LEFTBRACE = (short) 87;
+       public static final short ST_RIGHTBRACE = (short) 88;
+       public static final short ST_LEFTUPARROW = (short) 89;
+       public static final short ST_BENTUPARROW = (short) 90;
+       public static final short ST_BENTARROW = (short) 91;
+       public static final short ST_SEAL24 = (short) 92;
+       public static final short ST_STRIPEDRIGHTARROW = (short) 93;
+       public static final short ST_NOTCHEDRIGHTARROW = (short) 94;
+       public static final short ST_BLOCKARC = (short) 95;
+       public static final short ST_SMILEYFACE = (short) 96;
+       public static final short ST_VERTICALSCROLL = (short) 97;
+       public static final short ST_HORIZONTALSCROLL = (short) 98;
+       public static final short ST_CIRCULARARROW = (short) 99;
+       public static final short ST_NOTCHEDCIRCULARARROW = (short) 100;
+       public static final short ST_UTURNARROW = (short) 101;
+       public static final short ST_CURVEDRIGHTARROW = (short) 102;
+       public static final short ST_CURVEDLEFTARROW = (short) 103;
+       public static final short ST_CURVEDUPARROW = (short) 104;
+       public static final short ST_CURVEDDOWNARROW = (short) 105;
+       public static final short ST_CLOUDCALLOUT = (short) 106;
+       public static final short ST_ELLIPSERIBBON = (short) 107;
+       public static final short ST_ELLIPSERIBBON2 = (short) 108;
+       public static final short ST_FLOWCHARTPROCESS = (short) 109;
+       public static final short ST_FLOWCHARTDECISION = (short) 110;
+       public static final short ST_FLOWCHARTINPUTOUTPUT = (short) 111;
+       public static final short ST_FLOWCHARTPREDEFINEDPROCESS = (short) 112;
+       public static final short ST_FLOWCHARTINTERNALSTORAGE = (short) 113;
+       public static final short ST_FLOWCHARTDOCUMENT = (short) 114;
+       public static final short ST_FLOWCHARTMULTIDOCUMENT = (short) 115;
+       public static final short ST_FLOWCHARTTERMINATOR = (short) 116;
+       public static final short ST_FLOWCHARTPREPARATION = (short) 117;
+       public static final short ST_FLOWCHARTMANUALINPUT = (short) 118;
+       public static final short ST_FLOWCHARTMANUALOPERATION = (short) 119;
+       public static final short ST_FLOWCHARTCONNECTOR = (short) 120;
+       public static final short ST_FLOWCHARTPUNCHEDCARD = (short) 121;
+       public static final short ST_FLOWCHARTPUNCHEDTAPE = (short) 122;
+       public static final short ST_FLOWCHARTSUMMINGJUNCTION = (short) 123;
+       public static final short ST_FLOWCHARTOR = (short) 124;
+       public static final short ST_FLOWCHARTCOLLATE = (short) 125;
+       public static final short ST_FLOWCHARTSORT = (short) 126;
+       public static final short ST_FLOWCHARTEXTRACT = (short) 127;
+       public static final short ST_FLOWCHARTMERGE = (short) 128;
+       public static final short ST_FLOWCHARTOFFLINESTORAGE = (short) 129;
+       public static final short ST_FLOWCHARTONLINESTORAGE = (short) 130;
+       public static final short ST_FLOWCHARTMAGNETICTAPE = (short) 131;
+       public static final short ST_FLOWCHARTMAGNETICDISK = (short) 132;
+       public static final short ST_FLOWCHARTMAGNETICDRUM = (short) 133;
+       public static final short ST_FLOWCHARTDISPLAY = (short) 134;
+       public static final short ST_FLOWCHARTDELAY = (short) 135;
+       public static final short ST_TEXTPLAINTEXT = (short) 136;
+       public static final short ST_TEXTSTOP = (short) 137;
+       public static final short ST_TEXTTRIANGLE = (short) 138;
+       public static final short ST_TEXTTRIANGLEINVERTED = (short) 139;
+       public static final short ST_TEXTCHEVRON = (short) 140;
+       public static final short ST_TEXTCHEVRONINVERTED = (short) 141;
+       public static final short ST_TEXTRINGINSIDE = (short) 142;
+       public static final short ST_TEXTRINGOUTSIDE = (short) 143;
+       public static final short ST_TEXTARCHUPCURVE = (short) 144;
+       public static final short ST_TEXTARCHDOWNCURVE = (short) 145;
+       public static final short ST_TEXTCIRCLECURVE = (short) 146;
+       public static final short ST_TEXTBUTTONCURVE = (short) 147;
+       public static final short ST_TEXTARCHUPPOUR = (short) 148;
+       public static final short ST_TEXTARCHDOWNPOUR = (short) 149;
+       public static final short ST_TEXTCIRCLEPOUR = (short) 150;
+       public static final short ST_TEXTBUTTONPOUR = (short) 151;
+       public static final short ST_TEXTCURVEUP = (short) 152;
+       public static final short ST_TEXTCURVEDOWN = (short) 153;
+       public static final short ST_TEXTCASCADEUP = (short) 154;
+       public static final short ST_TEXTCASCADEDOWN = (short) 155;
+       public static final short ST_TEXTWAVE1 = (short) 156;
+       public static final short ST_TEXTWAVE2 = (short) 157;
+       public static final short ST_TEXTWAVE3 = (short) 158;
+       public static final short ST_TEXTWAVE4 = (short) 159;
+       public static final short ST_TEXTINFLATE = (short) 160;
+       public static final short ST_TEXTDEFLATE = (short) 161;
+       public static final short ST_TEXTINFLATEBOTTOM = (short) 162;
+       public static final short ST_TEXTDEFLATEBOTTOM = (short) 163;
+       public static final short ST_TEXTINFLATETOP = (short) 164;
+       public static final short ST_TEXTDEFLATETOP = (short) 165;
+       public static final short ST_TEXTDEFLATEINFLATE = (short) 166;
+       public static final short ST_TEXTDEFLATEINFLATEDEFLATE = (short) 167;
+       public static final short ST_TEXTFADERIGHT = (short) 168;
+       public static final short ST_TEXTFADELEFT = (short) 169;
+       public static final short ST_TEXTFADEUP = (short) 170;
+       public static final short ST_TEXTFADEDOWN = (short) 171;
+       public static final short ST_TEXTSLANTUP = (short) 172;
+       public static final short ST_TEXTSLANTDOWN = (short) 173;
+       public static final short ST_TEXTCANUP = (short) 174;
+       public static final short ST_TEXTCANDOWN = (short) 175;
+       public static final short ST_FLOWCHARTALTERNATEPROCESS = (short) 176;
+       public static final short ST_FLOWCHARTOFFPAGECONNECTOR = (short) 177;
+       public static final short ST_CALLOUT90 = (short) 178;
+       public static final short ST_ACCENTCALLOUT90 = (short) 179;
+       public static final short ST_BORDERCALLOUT90 = (short) 180;
+       public static final short ST_ACCENTBORDERCALLOUT90 = (short) 181;
+       public static final short ST_LEFTRIGHTUPARROW = (short) 182;
+       public static final short ST_SUN = (short) 183;
+       public static final short ST_MOON = (short) 184;
+       public static final short ST_BRACKETPAIR = (short) 185;
+       public static final short ST_BRACEPAIR = (short) 186;
+       public static final short ST_SEAL4 = (short) 187;
+       public static final short ST_DOUBLEWAVE = (short) 188;
+       public static final short ST_ACTIONBUTTONBLANK = (short) 189;
+       public static final short ST_ACTIONBUTTONHOME = (short) 190;
+       public static final short ST_ACTIONBUTTONHELP = (short) 191;
+       public static final short ST_ACTIONBUTTONINFORMATION = (short) 192;
+       public static final short ST_ACTIONBUTTONFORWARDNEXT = (short) 193;
+       public static final short ST_ACTIONBUTTONBACKPREVIOUS = (short) 194;
+       public static final short ST_ACTIONBUTTONEND = (short) 195;
+       public static final short ST_ACTIONBUTTONBEGINNING = (short) 196;
+       public static final short ST_ACTIONBUTTONRETURN = (short) 197;
+       public static final short ST_ACTIONBUTTONDOCUMENT = (short) 198;
+       public static final short ST_ACTIONBUTTONSOUND = (short) 199;
+       public static final short ST_ACTIONBUTTONMOVIE = (short) 200;
+       public static final short ST_HOSTCONTROL = (short) 201;
+       public static final short ST_TEXTBOX = (short) 202;
+       public static final short ST_NIL = (short) 0x0FFF;
+
+       protected HSSFPatriarch patriarch;
+
+       /** Maps shape container objects to their {@link TextObjectRecord} or {@link ObjRecord} */
+       private Map<EscherRecord, Record> shapeToObj = new HashMap<EscherRecord, Record>();
+       private DrawingManager2 drawingManager;
+       private short drawingGroupId;
+
+       /**
+        * list of "tail" records that need to be serialized after all drawing group records
+        */
+       private List tailRec = new ArrayList();
+
+       public EscherAggregate( DrawingManager2 drawingManager )
+       {
+               this.drawingManager = drawingManager;
+       }
+
+       /**
+        * @return  Returns the current sid.
+        */
+       public short getSid()
+       {
+               return sid;
+       }
+
+       /**
+        * Calculates the string representation of this record.  This is
+        * simply a dump of all the records.
+        */
+       public String toString()
+       {
+               String nl = System.getProperty( "line.separtor" );
+
+               StringBuffer result = new StringBuffer();
+               result.append( '[' ).append( getRecordName() ).append( ']' + nl );
+               for ( Iterator iterator = getEscherRecords().iterator(); iterator.hasNext(); )
+               {
+                       EscherRecord escherRecord = (EscherRecord) iterator.next();
+                       result.append( escherRecord.toString() );
+               }
+               result.append( "[/" ).append( getRecordName() ).append( ']' + nl );
+
+               return result.toString();
+       }
+
+       /**
+        * Collapses the drawing records into an aggregate.
+        */
+       public static EscherAggregate createAggregate( List records, int locFirstDrawingRecord, DrawingManager2 drawingManager )
+       {
+               // Keep track of any shape records created so we can match them back to the object id's.
+               // Textbox objects are also treated as shape objects.
+               final List<EscherRecord> shapeRecords = new ArrayList<EscherRecord>();
+               EscherRecordFactory recordFactory = new DefaultEscherRecordFactory()
+               {
+                       public EscherRecord createRecord( byte[] data, int offset )
+                       {
+                               EscherRecord r = super.createRecord( data, offset );
+                               if ( r.getRecordId() == EscherClientDataRecord.RECORD_ID || r.getRecordId() == EscherTextboxRecord.RECORD_ID )
+                               {
+                                       shapeRecords.add( r );
+                               }
+                               return r;
+                       }
+               };
+
+               // Calculate the size of the buffer
+               EscherAggregate agg = new EscherAggregate(drawingManager);
+               int loc = locFirstDrawingRecord;
+               int dataSize = 0;
+               while ( loc + 1 < records.size()
+                               && sid( records, loc ) == DrawingRecord.sid
+                               && isObjectRecord( records, loc + 1 ) )
+               {
+                       dataSize += ( (DrawingRecord) records.get( loc ) ).getData().length;
+                       loc += 2;
+               }
+
+               // Create one big buffer
+               byte buffer[] = new byte[dataSize];
+               int offset = 0;
+               loc = locFirstDrawingRecord;
+               while ( loc + 1 < records.size()
+                               && sid( records, loc ) == DrawingRecord.sid
+                               && isObjectRecord( records, loc + 1 ) )
+               {
+                       DrawingRecord drawingRecord = (DrawingRecord) records.get( loc );
+                       System.arraycopy( drawingRecord.getData(), 0, buffer, offset, drawingRecord.getData().length );
+                       offset += drawingRecord.getData().length;
+                       loc += 2;
+               }
+
+               // Decode the shapes
+               //              agg.escherRecords = new ArrayList();
+               int pos = 0;
+               while ( pos < dataSize )
+               {
+                       EscherRecord r = recordFactory.createRecord( buffer, pos );
+                       int bytesRead = r.fillFields( buffer, pos, recordFactory );
+                       agg.addEscherRecord( r );
+                       pos += bytesRead;
+               }
+
+               // Associate the object records with the shapes
+               loc = locFirstDrawingRecord;
+               int shapeIndex = 0;
+               agg.shapeToObj = new HashMap<EscherRecord, Record>();
+               while ( loc + 1 < records.size()
+                               && sid( records, loc ) == DrawingRecord.sid
+                               && isObjectRecord( records, loc + 1 ) )
+               {
+                       Record objRecord = (Record) records.get( loc + 1 );
+                       agg.shapeToObj.put( shapeRecords.get( shapeIndex++ ), objRecord );
+                       loc += 2;
+               }
+
+               return agg;
+
+       }
+
+       /**
+        * Serializes this aggregate to a byte array.  Since this is an aggregate
+        * record it will effectively serialize the aggregated records.
+        *
+        * @param offset        The offset into the start of the array.
+        * @param data    The byte array to serialize to.
+        * @return                The number of bytes serialized.
+        */
+       public int serialize( int offset, byte[] data )
+       {
+               convertUserModelToRecords();
+
+               // Determine buffer size
+               List records = getEscherRecords();
+               int size = getEscherRecordSize( records );
+               byte[] buffer = new byte[size];
+
+
+               // Serialize escher records into one big data structure and keep note of ending offsets.
+               final List spEndingOffsets = new ArrayList();
+               final List shapes = new ArrayList();
+               int pos = 0;
+               for ( Iterator iterator = records.iterator(); iterator.hasNext(); )
+               {
+                       EscherRecord e = (EscherRecord) iterator.next();
+                       pos += e.serialize( pos, buffer, new EscherSerializationListener()
+                       {
+                               public void beforeRecordSerialize( int offset, short recordId, EscherRecord record )
+                               {
+                               }
+
+                               public void afterRecordSerialize( int offset, short recordId, int size, EscherRecord record )
+                               {
+                                       if ( recordId == EscherClientDataRecord.RECORD_ID || recordId == EscherTextboxRecord.RECORD_ID )
+                                       {
+                                               spEndingOffsets.add( new Integer( offset ) );
+                                               shapes.add( record );
+                                       }
+                               }
+                       } );
+               }
+               // todo: fix this
+               shapes.add( 0, null );
+               spEndingOffsets.add( 0, null );
+
+               // Split escher records into separate MSODRAWING and OBJ, TXO records.  (We don't break on
+               // the first one because it's the patriach).
+               pos = offset;
+               for ( int i = 1; i < shapes.size(); i++ )
+               {
+                       int endOffset = ( (Integer) spEndingOffsets.get( i ) ).intValue() - 1;
+                       int startOffset;
+                       if ( i == 1 )
+                               startOffset = 0;
+                       else
+                               startOffset = ( (Integer) spEndingOffsets.get( i - 1 ) ).intValue();
+
+                       // Create and write a new MSODRAWING record
+                       DrawingRecord drawing = new DrawingRecord();
+                       byte[] drawingData = new byte[endOffset - startOffset + 1];
+                       System.arraycopy( buffer, startOffset, drawingData, 0, drawingData.length );
+                       drawing.setData( drawingData );
+                       int temp = drawing.serialize( pos, data );
+                       pos += temp;
+
+                       // Write the matching OBJ record
+                       Record obj = (Record) shapeToObj.get( shapes.get( i ) );
+                       temp = obj.serialize( pos, data );
+                       pos += temp;
+
+               }
+
+               // write records that need to be serialized after all drawing group records
+               for ( int i = 0; i < tailRec.size(); i++ )
+               {
+                       Record rec = (Record)tailRec.get(i);
+                       pos += rec.serialize( pos, data );
+               }
+
+               int bytesWritten = pos - offset;
+               if ( bytesWritten != getRecordSize() )
+                       throw new RecordFormatException( bytesWritten + " bytes written but getRecordSize() reports " + getRecordSize() );
+               return bytesWritten;
+       }
+
+       /**
+        * How many bytes do the raw escher records contain.
+        * @param records   List of escher records
+        * @return  the number of bytes
+        */
+       private int getEscherRecordSize( List records )
+       {
+               int size = 0;
+               for ( Iterator iterator = records.iterator(); iterator.hasNext(); )
+                       size += ( (EscherRecord) iterator.next() ).getRecordSize();
+               return size;
+       }
+
+       public int getRecordSize() {
+               // TODO - convert this to RecordAggregate
+               convertUserModelToRecords();
+               List records = getEscherRecords();
+               int rawEscherSize = getEscherRecordSize( records );
+               int drawingRecordSize = rawEscherSize + ( shapeToObj.size() ) * 4;
+               int objRecordSize = 0;
+               for ( Iterator iterator = shapeToObj.values().iterator(); iterator.hasNext(); )
+               {
+                       Record r = (Record) iterator.next();
+                       objRecordSize += r.getRecordSize();
+               }
+               int tailRecordSize = 0;
+               for ( Iterator iterator = tailRec.iterator(); iterator.hasNext(); )
+               {
+                       Record r = (Record) iterator.next();
+                       tailRecordSize += r.getRecordSize();
+               }
+               return drawingRecordSize + objRecordSize + tailRecordSize;
+       }
+
+       /**
+        * Associates an escher record to an OBJ record or a TXO record.
+        */
+       Object associateShapeToObjRecord( EscherRecord r, ObjRecord objRecord )
+       {
+               return shapeToObj.put( r, objRecord );
+       }
+
+       public HSSFPatriarch getPatriarch()
+       {
+               return patriarch;
+       }
+
+       public void setPatriarch( HSSFPatriarch patriarch )
+       {
+               this.patriarch = patriarch;
+       }
+       
+       /**
+        * Converts the Records into UserModel
+        *  objects on the bound HSSFPatriarch
+        */
+       public void convertRecordsToUserModel() {
+               if(patriarch == null) {
+                       throw new IllegalStateException("Must call setPatriarch() first");
+               }
+               
+               // The top level container ought to have
+               //  the DgRecord and the container of one container
+               //  per shape group (patriach overall first)
+               EscherContainerRecord topContainer = getEscherContainer();
+               if(topContainer == null) {
+                       return;
+               }
+               topContainer = (EscherContainerRecord) 
+                       topContainer.getChildContainers().get(0);
+               
+               List tcc = topContainer.getChildContainers();
+               if(tcc.size() == 0) {
+                       throw new IllegalStateException("No child escher containers at the point that should hold the patriach data, and one container per top level shape!");
+               }
+               
+               // First up, get the patriach position
+               // This is in the first EscherSpgrRecord, in
+               //  the first container, with a EscherSRecord too
+               EscherContainerRecord patriachContainer =
+                       (EscherContainerRecord)tcc.get(0);
+               EscherSpgrRecord spgr = null;
+               for(Iterator<EscherRecord> it = patriachContainer.getChildIterator(); it.hasNext();) {
+                       EscherRecord r = it.next();
+                       if(r instanceof EscherSpgrRecord) {
+                               spgr = (EscherSpgrRecord)r;
+                               break;
+                       }
+               }
+               if(spgr != null) {
+                       patriarch.setCoordinates(
+                                       spgr.getRectX1(), spgr.getRectY1(),
+                                       spgr.getRectX2(), spgr.getRectY2()
+                       );
+               }
+               
+               // Now process the containers for each group
+               //  and objects
+               for(int i=1; i<tcc.size(); i++) {
+                       EscherContainerRecord shapeContainer =
+                               (EscherContainerRecord)tcc.get(i);
+                       //System.err.println("\n\n*****\n\n");
+                       //System.err.println(shapeContainer);
+                       
+                       // Could be a group, or a base object
+                       if(shapeContainer.getChildRecords().size() == 1 &&
+                                       shapeContainer.getChildContainers().size() == 1) {
+                               // Group
+                               HSSFShapeGroup group =
+                                       new HSSFShapeGroup(null, new HSSFClientAnchor());
+                               patriarch.getChildren().add(group);
+                               
+                               EscherContainerRecord groupContainer =
+                                       (EscherContainerRecord)shapeContainer.getChild(0);
+                               convertRecordsToUserModel(groupContainer, group);
+                       } else if(shapeContainer.hasChildOfType((short)0xF00D)) {
+                               // TextBox
+                               HSSFTextbox box =
+                                       new HSSFTextbox(null, new HSSFClientAnchor());
+                               patriarch.getChildren().add(box);
+                               
+                               convertRecordsToUserModel(shapeContainer, box);
+                       } else if(shapeContainer.hasChildOfType((short)0xF011)) {
+                               // Not yet supporting EscherClientDataRecord stuff
+                       } else {
+                               // Base level
+                               convertRecordsToUserModel(shapeContainer, patriarch);
+                       }
+               }
+               
+               // Now, clear any trace of what records make up
+               //  the patriarch
+               // Otherwise, everything will go horribly wrong
+               //  when we try to write out again....
+//             clearEscherRecords();
+               drawingManager.getDgg().setFileIdClusters(new EscherDggRecord.FileIdCluster[0]);
+
+               // TODO: Support converting our records
+               //  back into shapes
+               log.log(POILogger.WARN, "Not processing objects into Patriarch!");
+       }
+       
+       private void convertRecordsToUserModel(EscherContainerRecord shapeContainer, Object model) {
+               for(Iterator<EscherRecord> it = shapeContainer.getChildIterator(); it.hasNext();) {
+                       EscherRecord r = it.next();
+                       if(r instanceof EscherSpgrRecord) {
+                               // This may be overriden by a later EscherClientAnchorRecord
+                               EscherSpgrRecord spgr = (EscherSpgrRecord)r;
+                               
+                               if(model instanceof HSSFShapeGroup) {
+                                       HSSFShapeGroup g = (HSSFShapeGroup)model;
+                                       g.setCoordinates(
+                                                       spgr.getRectX1(), spgr.getRectY1(),
+                                                       spgr.getRectX2(), spgr.getRectY2()
+                                       );
+                               } else {
+                                       throw new IllegalStateException("Got top level anchor but not processing a group");
+                               }
+                       } 
+                       else if(r instanceof EscherClientAnchorRecord) {
+                               EscherClientAnchorRecord car = (EscherClientAnchorRecord)r;
+                               
+                               if(model instanceof HSSFShape) {
+                                       HSSFShape g = (HSSFShape)model;
+                                       g.getAnchor().setDx1(car.getDx1());
+                                       g.getAnchor().setDx2(car.getDx2());
+                                       g.getAnchor().setDy1(car.getDy1());
+                                       g.getAnchor().setDy2(car.getDy2());
+                               } else {
+                                       throw new IllegalStateException("Got top level anchor but not processing a group or shape");
+                               }
+                       }
+                       else if(r instanceof EscherTextboxRecord) {
+                               EscherTextboxRecord tbr = (EscherTextboxRecord)r;
+                               
+                               // Also need to find the TextObjectRecord too
+                               // TODO
+                       }
+                       else if(r instanceof EscherSpRecord) {
+                               // Use flags if needed
+                       }
+                       else if(r instanceof EscherOptRecord) {
+                               // Use properties if needed
+                       }
+                       else {
+                               //System.err.println(r);
+                       }
+               }
+       }
+       
+       public void clear()
+       {
+               clearEscherRecords();
+               shapeToObj.clear();
+//             lastShapeId = 1024;
+       }
+
+       protected String getRecordName()
+       {
+               return "ESCHERAGGREGATE";
+       }
+
+       // =============== Private methods ========================
+
+       private static boolean isObjectRecord( List records, int loc )
+       {
+               return sid( records, loc ) == ObjRecord.sid || sid( records, loc ) == TextObjectRecord.sid;
+       }
+
+       private void convertUserModelToRecords()
+       {
+               if ( patriarch != null )
+               {
+                       shapeToObj.clear();
+                       tailRec.clear();
+                       clearEscherRecords();
+                       if ( patriarch.getChildren().size() != 0 )
+                       {
+                               convertPatriarch( patriarch );
+                               EscherContainerRecord dgContainer = (EscherContainerRecord) getEscherRecord( 0 );
+                               EscherContainerRecord spgrContainer = null;
+                               Iterator<EscherRecord> iter = dgContainer.getChildIterator();
+                               while (iter.hasNext()) {
+                                       EscherRecord child = iter.next();
+                                       if (child.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) {
+                                               spgrContainer = (EscherContainerRecord) child;
+                                       }
+                               }
+                               convertShapes( patriarch, spgrContainer, shapeToObj );
+
+                               patriarch = null;
+                       }
+               }
+       }
+
+       private void convertShapes( HSSFShapeContainer parent, EscherContainerRecord escherParent, Map shapeToObj )
+       {
+               if ( escherParent == null ) throw new IllegalArgumentException( "Parent record required" );
+
+               List shapes = parent.getChildren();
+               for ( Iterator iterator = shapes.iterator(); iterator.hasNext(); )
+               {
+                       HSSFShape shape = (HSSFShape) iterator.next();
+                       if ( shape instanceof HSSFShapeGroup )
+                       {
+                               convertGroup( (HSSFShapeGroup) shape, escherParent, shapeToObj );
+                       }
+                       else
+                       {
+                               AbstractShape shapeModel = AbstractShape.createShape(
+                                               shape,
+                                               drawingManager.allocateShapeId(drawingGroupId) );
+                               shapeToObj.put( findClientData( shapeModel.getSpContainer() ), shapeModel.getObjRecord() );
+                               if ( shapeModel instanceof TextboxShape )
+                               {
+                                       EscherRecord escherTextbox = ( (TextboxShape) shapeModel ).getEscherTextbox();
+                                       shapeToObj.put( escherTextbox, ( (TextboxShape) shapeModel ).getTextObjectRecord() );
+                                       //                                      escherParent.addChildRecord(escherTextbox);
+                                       
+                                       if ( shapeModel instanceof CommentShape ){
+                                               CommentShape comment = (CommentShape)shapeModel;
+                                               tailRec.add(comment.getNoteRecord());
+                                       }
+
+                               }
+                               escherParent.addChildRecord( shapeModel.getSpContainer() );
+                       }
+               }
+//             drawingManager.newCluster( (short)1 );
+//             drawingManager.newCluster( (short)2 );
+
+       }
+
+       private void convertGroup( HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj )
+       {
+               EscherContainerRecord spgrContainer = new EscherContainerRecord();
+               EscherContainerRecord spContainer = new EscherContainerRecord();
+               EscherSpgrRecord spgr = new EscherSpgrRecord();
+               EscherSpRecord sp = new EscherSpRecord();
+               EscherOptRecord opt = new EscherOptRecord();
+               EscherRecord anchor;
+               EscherClientDataRecord clientData = new EscherClientDataRecord();
+
+               spgrContainer.setRecordId( EscherContainerRecord.SPGR_CONTAINER );
+               spgrContainer.setOptions( (short) 0x000F );
+               spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
+               spContainer.setOptions( (short) 0x000F );
+               spgr.setRecordId( EscherSpgrRecord.RECORD_ID );
+               spgr.setOptions( (short) 0x0001 );
+               spgr.setRectX1( shape.getX1() );
+               spgr.setRectY1( shape.getY1() );
+               spgr.setRectX2( shape.getX2() );
+               spgr.setRectY2( shape.getY2() );
+               sp.setRecordId( EscherSpRecord.RECORD_ID );
+               sp.setOptions( (short) 0x0002 );
+               int shapeId = drawingManager.allocateShapeId(drawingGroupId);
+               sp.setShapeId( shapeId );
+               if (shape.getAnchor() instanceof HSSFClientAnchor)
+                       sp.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR );
+               else
+                       sp.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD );
+               opt.setRecordId( EscherOptRecord.RECORD_ID );
+               opt.setOptions( (short) 0x0023 );
+               opt.addEscherProperty( new EscherBoolProperty( EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004 ) );
+               opt.addEscherProperty( new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x00080000 ) );
+
+               anchor = ConvertAnchor.createAnchor( shape.getAnchor() );
+//             clientAnchor.setCol1( ( (HSSFClientAnchor) shape.getAnchor() ).getCol1() );
+//             clientAnchor.setRow1( (short) ( (HSSFClientAnchor) shape.getAnchor() ).getRow1() );
+//             clientAnchor.setDx1( (short) shape.getAnchor().getDx1() );
+//             clientAnchor.setDy1( (short) shape.getAnchor().getDy1() );
+//             clientAnchor.setCol2( ( (HSSFClientAnchor) shape.getAnchor() ).getCol2() );
+//             clientAnchor.setRow2( (short) ( (HSSFClientAnchor) shape.getAnchor() ).getRow2() );
+//             clientAnchor.setDx2( (short) shape.getAnchor().getDx2() );
+//             clientAnchor.setDy2( (short) shape.getAnchor().getDy2() );
+               clientData.setRecordId( EscherClientDataRecord.RECORD_ID );
+               clientData.setOptions( (short) 0x0000 );
+
+               spgrContainer.addChildRecord( spContainer );
+               spContainer.addChildRecord( spgr );
+               spContainer.addChildRecord( sp );
+               spContainer.addChildRecord( opt );
+               spContainer.addChildRecord( anchor );
+               spContainer.addChildRecord( clientData );
+
+               ObjRecord obj = new ObjRecord();
+               CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord();
+               cmo.setObjectType( CommonObjectDataSubRecord.OBJECT_TYPE_GROUP );
+               cmo.setObjectId( (short) ( shapeId ) );
+               cmo.setLocked( true );
+               cmo.setPrintable( true );
+               cmo.setAutofill( true );
+               cmo.setAutoline( true );
+               GroupMarkerSubRecord gmo = new GroupMarkerSubRecord();
+               EndSubRecord end = new EndSubRecord();
+               obj.addSubRecord( cmo );
+               obj.addSubRecord( gmo );
+               obj.addSubRecord( end );
+               shapeToObj.put( clientData, obj );
+
+               escherParent.addChildRecord( spgrContainer );
+
+               convertShapes( shape, spgrContainer, shapeToObj );
+
+       }
+
+       private EscherRecord findClientData( EscherContainerRecord spContainer )
+       {
+               for (Iterator<EscherRecord> iterator = spContainer.getChildIterator(); iterator.hasNext();) {
+                       EscherRecord r = iterator.next();
+                       if (r.getRecordId() == EscherClientDataRecord.RECORD_ID) {
+                               return r;
+                       }
+               }
+               throw new IllegalArgumentException( "Can not find client data record" );
+       }
+
+       private void convertPatriarch( HSSFPatriarch patriarch )
+       {
+               EscherContainerRecord dgContainer = new EscherContainerRecord();
+               EscherDgRecord dg;
+               EscherContainerRecord spgrContainer = new EscherContainerRecord();
+               EscherContainerRecord spContainer1 = new EscherContainerRecord();
+               EscherSpgrRecord spgr = new EscherSpgrRecord();
+               EscherSpRecord sp1 = new EscherSpRecord();
+
+               dgContainer.setRecordId( EscherContainerRecord.DG_CONTAINER );
+               dgContainer.setOptions( (short) 0x000F );
+               dg = drawingManager.createDgRecord();
+               drawingGroupId = dg.getDrawingGroupId();
+//             dg.setOptions( (short) ( drawingId << 4 ) );
+//             dg.setNumShapes( getNumberOfShapes( patriarch ) );
+//             dg.setLastMSOSPID( 0 );  // populated after all shape id's are assigned.
+               spgrContainer.setRecordId( EscherContainerRecord.SPGR_CONTAINER );
+               spgrContainer.setOptions( (short) 0x000F );
+               spContainer1.setRecordId( EscherContainerRecord.SP_CONTAINER );
+               spContainer1.setOptions( (short) 0x000F );
+               spgr.setRecordId( EscherSpgrRecord.RECORD_ID );
+               spgr.setOptions( (short) 0x0001 );      // version
+               spgr.setRectX1( patriarch.getX1() );
+               spgr.setRectY1( patriarch.getY1() );
+               spgr.setRectX2( patriarch.getX2() );
+               spgr.setRectY2( patriarch.getY2() );
+               sp1.setRecordId( EscherSpRecord.RECORD_ID );
+               sp1.setOptions( (short) 0x0002 );
+               sp1.setShapeId( drawingManager.allocateShapeId(dg.getDrawingGroupId()) );
+               sp1.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_PATRIARCH );
+
+               dgContainer.addChildRecord( dg );
+               dgContainer.addChildRecord( spgrContainer );
+               spgrContainer.addChildRecord( spContainer1 );
+               spContainer1.addChildRecord( spgr );
+               spContainer1.addChildRecord( sp1 );
+
+               addEscherRecord( dgContainer );
+       }
+
+
+       private static short sid( List records, int loc )
+       {
+               return ( (Record) records.get( loc ) ).getSid();
+       }
 
 
 }
index 46860213c9e84f3374b0106d96c9778d2dff6a68..2296f7077ca791455dc85a859154857b6421cd3a 100644 (file)
@@ -201,22 +201,20 @@ public final class SlideShowRecordDumper {
         String nl = System.getProperty( "line.separator" );
 
         StringBuffer children = new StringBuffer();
-        if ( ecr.getChildRecords().size() > 0 )
+        int count = 0;
+        for ( Iterator<EscherRecord> iterator = ecr.getChildIterator(); iterator.hasNext(); )
         {
-            children.append( "  children: " + nl );
-            
-            int count = 0;
-            for ( Iterator iterator = ecr.getChildRecords().iterator(); iterator.hasNext(); )
-            {
-               String newIndent = "   ";
-               
-                EscherRecord record = (EscherRecord) iterator.next();
-                children.append(newIndent + "Child " + count + ":" + nl);
-                
-                       children.append( printEscherRecord(record) );
-
-                count++;
+            if (count < 1) {
+                children.append( "  children: " + nl );
             }
+            String newIndent = "   ";
+
+            EscherRecord record = iterator.next();
+            children.append(newIndent + "Child " + count + ":" + nl);
+            
+               children.append( printEscherRecord(record) );
+
+            count++;
         }
 
         return 
index 45e5a45d980f9e4634460f0fa1e6d24dc3508f30..829e0104a76349951557bf2b556382b0f3147eb2 100755 (executable)
@@ -76,7 +76,7 @@ public final class ActiveXShape extends Picture {
 \r
         EscherClientDataRecord cldata = new EscherClientDataRecord();\r
         cldata.setOptions((short)0xF);\r
-        _escherContainer.getChildRecords().add(cldata);\r
+        _escherContainer.addChildRecord(cldata); // TODO unit test to prove getChildRecords().add is wrong\r
 \r
         OEShapeAtom oe = new OEShapeAtom();\r
 \r
@@ -100,7 +100,7 @@ public final class ActiveXShape extends Picture {
      */\r
     public void setActiveXIndex(int idx){\r
         EscherContainerRecord spContainer = getSpContainer();\r
-        for (Iterator<EscherRecord> it = spContainer.getChildRecords().iterator(); it.hasNext();) {\r
+        for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext();) {\r
             EscherRecord obj = it.next();\r
             if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {\r
                 EscherClientDataRecord clientRecord = (EscherClientDataRecord)obj;\r
index f0691c45c799fc73d207f4b251be941bed31eb1e..c92935f7a8c32120ba74b4350c325c923a7b56a3 100644 (file)
@@ -177,11 +177,10 @@ public class Hyperlink {
         }\r
 \r
         EscherContainerRecord spContainer = shape.getSpContainer();\r
-        List spchild = spContainer.getChildRecords();\r
-        for (Iterator it = spchild.iterator(); it.hasNext(); ) {\r
-            EscherRecord obj = (EscherRecord)it.next();\r
+        for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext(); ) {\r
+            EscherRecord obj = it.next();\r
             if (obj.getRecordId() ==  EscherClientDataRecord.RECORD_ID){\r
-                byte[] data = ((EscherContainerRecord)obj).serialize();\r
+                byte[] data = obj.serialize();\r
                 Record[] records = Record.findChildRecords(data, 8, data.length-8);\r
                 if(records != null) find(records, exobj, lst);\r
             }\r
index f0bc74558fe3d28cfc46c29335c88f9207a7b949..1474fdc7c082cef2b85a412f8aa8c93a8251448c 100644 (file)
@@ -86,13 +86,7 @@ public class Placeholder extends TextBox {
         cldata.setRemainingData(out.toByteArray());
 
         //append placeholder container before EscherTextboxRecord
-        List lst = _escherContainer.getChildRecords();
-        for (int i = 0; i < lst.size(); i++) {
-              EscherRecord rec = (EscherRecord)lst.get(i);
-              if(rec.getRecordId() == EscherTextboxRecord.RECORD_ID){
-                  lst.add(i++, cldata);
-              }
-        }
+        _escherContainer.addChildBefore(cldata, EscherTextboxRecord.RECORD_ID);
 
         return _escherContainer;
     }
index fbea17e88f424d4c319bbf4a3102945e8031f4fd..ec6435d70296f4e5cef2869eab5b4ce0fb8a650b 100644 (file)
@@ -246,9 +246,9 @@ public abstract class Shape {
      * @return escher record or <code>null</code> if not found.
      */
     public static EscherRecord getEscherChild(EscherContainerRecord owner, int recordId){
-        for ( Iterator iterator = owner.getChildRecords().iterator(); iterator.hasNext(); )
+        for ( Iterator<EscherRecord> iterator = owner.getChildIterator(); iterator.hasNext(); )
         {
-            EscherRecord escherRecord = (EscherRecord) iterator.next();
+            EscherRecord escherRecord = iterator.next();
             if (escherRecord.getRecordId() == recordId)
                 return escherRecord;
         }
index 8b4abd5e590e5680058bf0e288192bd4a9ee1f88..ab95fae66a5387c1cf0950856f7c6ca0ff26605f 100644 (file)
@@ -125,8 +125,8 @@ public class ShapeFactory {
 
     protected static Record getClientDataRecord(EscherContainerRecord spContainer, int recordType) {
         Record oep = null;
-        for (Iterator it = spContainer.getChildRecords().iterator(); it.hasNext();) {
-            EscherRecord obj = (EscherRecord) it.next();
+        for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext();) {
+            EscherRecord obj = it.next();
             if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
                 byte[] data = obj.serialize();
                 Record[] records = Record.findChildRecords(data, 8, data.length - 8);
index cfa8296713d6c44a1057ebffd904b19e98d8f3fc..50119b6bff99b0ed5e9be0cc773da7f039bfd155 100644 (file)
    See the License for the specific language governing permissions and
    limitations under the License.
 ==================================================================== */
-package org.apache.poi.hslf.model;
 
-import org.apache.poi.ddf.*;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.POILogger;
-import org.apache.poi.hslf.record.EscherTextboxWrapper;
+package org.apache.poi.hslf.model;
 
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.AffineTransform;
-import java.awt.*;
+
+import org.apache.poi.ddf.EscherChildAnchorRecord;
+import org.apache.poi.ddf.EscherClientAnchorRecord;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.ddf.EscherSpRecord;
+import org.apache.poi.ddf.EscherSpgrRecord;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.POILogger;
 
 /**
  *  Represents a group of shapes.
@@ -57,14 +63,17 @@ public class ShapeGroup extends Shape{
      * @return the shapes contained in this group container
      */
     public Shape[] getShapes() {
-       // Out escher container record should contain serveral
+       // Out escher container record should contain several
         //  SpContainers, the first of which is the group shape itself
-        List lst = _escherContainer.getChildRecords();
+        Iterator<EscherRecord> iter = _escherContainer.getChildIterator();
 
-        ArrayList shapeList = new ArrayList();
         // Don't include the first SpContainer, it is always NotPrimitive
-        for (int i = 1; i < lst.size(); i++){
-               EscherRecord r = (EscherRecord)lst.get(i);
+        if (iter.hasNext()) {
+               iter.next();
+        }
+        List<Shape> shapeList = new ArrayList<Shape>();
+        while (iter.hasNext()) {
+               EscherRecord r = iter.next();
                if(r instanceof EscherContainerRecord) {
                        // Create the Shape for it
                        EscherContainerRecord container = (EscherContainerRecord)r;
@@ -79,7 +88,7 @@ public class ShapeGroup extends Shape{
         }
         
         // Put the shapes into an array, and return
-        Shape[] shapes = (Shape[])shapeList.toArray(new Shape[shapeList.size()]);
+        Shape[] shapes = shapeList.toArray(new Shape[shapeList.size()]);
         return shapes;
     }
 
@@ -91,7 +100,7 @@ public class ShapeGroup extends Shape{
      */
     public void setAnchor(java.awt.Rectangle anchor){
 
-        EscherContainerRecord spContainer = (EscherContainerRecord)_escherContainer.getChildRecords().get(0);
+        EscherContainerRecord spContainer = (EscherContainerRecord)_escherContainer.getChild(0);
 
         EscherClientAnchorRecord clientAnchor = (EscherClientAnchorRecord)getEscherChild(spContainer, EscherClientAnchorRecord.RECORD_ID);
         //hack. internal variable EscherClientAnchorRecord.shortRecord can be
@@ -122,7 +131,7 @@ public class ShapeGroup extends Shape{
      * @param anchor the coordinate space of this group
      */
     public void setCoordinates(Rectangle2D anchor){
-        EscherContainerRecord spContainer = (EscherContainerRecord)_escherContainer.getChildRecords().get(0);
+        EscherContainerRecord spContainer = (EscherContainerRecord)_escherContainer.getChild(0);
         EscherSpgrRecord spgr = (EscherSpgrRecord)getEscherChild(spContainer, EscherSpgrRecord.RECORD_ID);
 
         int x1 = (int)Math.round(anchor.getX()*MASTER_DPI/POINT_DPI);
@@ -144,7 +153,7 @@ public class ShapeGroup extends Shape{
      * @return the coordinate space of this group
      */
     public Rectangle2D getCoordinates(){
-        EscherContainerRecord spContainer = (EscherContainerRecord)_escherContainer.getChildRecords().get(0);
+        EscherContainerRecord spContainer = (EscherContainerRecord)_escherContainer.getChild(0);
         EscherSpgrRecord spgr = (EscherSpgrRecord)getEscherChild(spContainer, EscherSpgrRecord.RECORD_ID);
 
         Rectangle2D.Float anchor = new Rectangle2D.Float();
@@ -228,7 +237,7 @@ public class ShapeGroup extends Shape{
      * @return the anchor of this shape group
      */
     public Rectangle2D getAnchor2D(){
-        EscherContainerRecord spContainer = (EscherContainerRecord)_escherContainer.getChildRecords().get(0);
+        EscherContainerRecord spContainer = (EscherContainerRecord)_escherContainer.getChild(0);
         EscherClientAnchorRecord clientAnchor = (EscherClientAnchorRecord)getEscherChild(spContainer, EscherClientAnchorRecord.RECORD_ID);
         Rectangle2D.Float anchor = new Rectangle2D.Float();
         if(clientAnchor == null){
index c4d542aa0567e2811267316dcc3308deb7855357..26597118b8d9c903c6ba1ba22e8c6460ab11a800 100644 (file)
@@ -211,26 +211,32 @@ public abstract class Sheet {
 
         EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
         EscherContainerRecord spgr = null;
-        List ch = dg.getChildRecords();
 
-        for (Iterator it = ch.iterator(); it.hasNext();) {
-            EscherRecord rec = (EscherRecord) it.next();
+        for (Iterator<EscherRecord> it = dg.getChildIterator(); it.hasNext();) {
+            EscherRecord rec = it.next();
             if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) {
                 spgr = (EscherContainerRecord) rec;
                 break;
             }
         }
-        ch = spgr.getChildRecords();
+        if (spgr == null) {
+            throw new IllegalStateException("spgr not found");
+        }
 
-        ArrayList shapes = new ArrayList();
-        for (int i = 1; i < ch.size(); i++) {
-            EscherContainerRecord sp = (EscherContainerRecord) ch.get(i);
+        List<Shape> shapes = new ArrayList<Shape>();
+        Iterator<EscherRecord> it = spgr.getChildIterator();
+        if (it.hasNext()) {
+            // skip first item
+            it.next();
+        }
+        for (; it.hasNext();) {
+            EscherContainerRecord sp = (EscherContainerRecord) it.next();
             Shape sh = ShapeFactory.createShape(sp, null);
             sh.setSheet(this);
             shapes.add(sh);
         }
 
-        return (Shape[]) shapes.toArray(new Shape[shapes.size()]);
+        return shapes.toArray(new Shape[shapes.size()]);
     }
 
     /**
@@ -301,17 +307,21 @@ public abstract class Sheet {
         EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
         EscherContainerRecord spgr = null;
 
-        for (Iterator it = dg.getChildRecords().iterator(); it.hasNext();) {
-            EscherRecord rec = (EscherRecord) it.next();
+        for (Iterator<EscherRecord> it = dg.getChildIterator(); it.hasNext();) {
+            EscherRecord rec = it.next();
             if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) {
                 spgr = (EscherContainerRecord) rec;
                 break;
             }
         }
-        if(spgr == null) return false;
+        if(spgr == null) {
+            return false;
+        }
 
-        List lst = spgr.getChildRecords();
-        return lst.remove(shape.getSpContainer());
+        List<EscherRecord> lst = spgr.getChildRecords();
+        boolean result = lst.remove(shape.getSpContainer());
+        spgr.setChildRecords(lst);
+        return result;
     }
 
     /**
@@ -344,10 +354,9 @@ public abstract class Sheet {
 
             EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
             EscherContainerRecord spContainer = null;
-            List ch = dg.getChildRecords();
 
-            for (Iterator it = ch.iterator(); it.hasNext();) {
-                EscherRecord rec = (EscherRecord) it.next();
+            for (Iterator<EscherRecord> it = dg.getChildIterator(); it.hasNext();) {
+                EscherRecord rec = it.next();
                 if (rec.getRecordId() == EscherContainerRecord.SP_CONTAINER) {
                     spContainer = (EscherContainerRecord) rec;
                     break;
index d5816b0aad09ee2a78d6167fde741c85ae50fbb1..0d8992f36ae3aa60fabb41ed1b7e4bd2eb2b397b 100644 (file)
 
 package org.apache.poi.hslf.model;
 
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.io.ByteArrayOutputStream;
+
 import org.apache.poi.ddf.*;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.ddf.EscherSpRecord;
+import org.apache.poi.hslf.exceptions.HSLFException;
 import org.apache.poi.hslf.record.ColorSchemeAtom;
-import org.apache.poi.hslf.record.Record;
 import org.apache.poi.hslf.record.InteractiveInfo;
 import org.apache.poi.hslf.record.InteractiveInfoAtom;
-import org.apache.poi.hslf.exceptions.HSLFException;
-
-import java.awt.*;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Rectangle2D;
-import java.util.Iterator;
-import java.io.ByteArrayOutputStream;
+import org.apache.poi.hslf.record.Record;
+import org.apache.poi.util.LittleEndian;
 
 /**
  *  An abstract simple (non-group) shape.
@@ -256,8 +257,8 @@ public class SimpleShape extends Shape {
             Rectangle2D clientAnchor = top.getAnchor2D();
             Rectangle2D spgrAnchor = ((ShapeGroup)top).getCoordinates();
 
-            double scalex = (double)spgrAnchor.getWidth()/clientAnchor.getWidth();
-            double scaley = (double)spgrAnchor.getHeight()/clientAnchor.getHeight();
+            double scalex = spgrAnchor.getWidth()/clientAnchor.getWidth();
+            double scaley = spgrAnchor.getHeight()/clientAnchor.getHeight();
 
             double x = clientAnchor.getX() + (anchor.getX() - spgrAnchor.getX())/scalex;
             double y = clientAnchor.getY() + (anchor.getY() - spgrAnchor.getY())/scaley;
@@ -353,7 +354,7 @@ public class SimpleShape extends Shape {
 
         EscherClientDataRecord cldata = new EscherClientDataRecord();
         cldata.setOptions((short)0xF);
-        getSpContainer().getChildRecords().add(cldata);
+        getSpContainer().addChildRecord(cldata); // TODO - junit to prove getChildRecords().add is wrong
 
         InteractiveInfo info = new InteractiveInfo();
         InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom();
index 8acbca5ac93e47f81d9a0de35c6c9cf8e07946a5..bb2e8fc79f9d4246eb49e4835b86b8f0e7eca282 100644 (file)
@@ -152,7 +152,7 @@ public class Slide extends Sheet
             EscherSpRecord spr = null;
             switch(c.getRecordId()){
                 case EscherContainerRecord.SPGR_CONTAINER:
-                    EscherContainerRecord dc = (EscherContainerRecord)c.getChildRecords().get(0);
+                    EscherContainerRecord dc = (EscherContainerRecord)c.getChild(0);
                     spr = dc.getChildById(EscherSpRecord.RECORD_ID);
                     break;
                 case EscherContainerRecord.SP_CONTAINER:
index bd27969fafe3dbfc9ad4b68803f51f1a1b42885e..907bce377355eb062e1723d78af08422d53c975a 100755 (executable)
@@ -73,7 +73,6 @@ public class Table extends ShapeGroup {
         setAnchor(new Rectangle(0, 0, tblWidth, tblHeight));\r
 \r
         EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);\r
-        List lst = spCont.getChildRecords();\r
         EscherOptRecord opt = new EscherOptRecord();\r
         opt.setRecordId((short)0xF122);\r
         opt.addEscherProperty(new EscherSimpleProperty((short)0x39F, 1));\r
@@ -82,8 +81,9 @@ public class Table extends ShapeGroup {
         p.setNumberOfElementsInArray(numrows);\r
         p.setNumberOfElementsInMemory(numrows);\r
         opt.addEscherProperty(p);\r
+        List<EscherRecord> lst = spCont.getChildRecords();\r
         lst.add(lst.size()-1, opt);\r
-\r
+        spCont.setChildRecords(lst);\r
     }\r
 \r
     /**\r
@@ -118,7 +118,7 @@ public class Table extends ShapeGroup {
         super.afterInsert(sh);\r
 \r
         EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);\r
-        List lst = spCont.getChildRecords();\r
+        List<EscherRecord> lst = spCont.getChildRecords();\r
         EscherOptRecord opt = (EscherOptRecord)lst.get(lst.size()-2);\r
         EscherArrayProperty p = (EscherArrayProperty)opt.getEscherProperty(1);\r
         for (int i = 0; i < cells.length; i++) {\r
index 3a1ed8dbe5c865424407dccfd356f03864b82339..1705a8cede5d2af23bfb3cef5ddab9c906329331 100644 (file)
@@ -175,11 +175,9 @@ public class PPDrawing extends RecordAtom
                        } else {
                                // If it has children, walk them
                                if(toSearch[i].isContainerRecord()) {
-                                       List childrenL = toSearch[i].getChildRecords();
+                                       List<EscherRecord> childrenL = toSearch[i].getChildRecords();
                                        EscherRecord[] children = new EscherRecord[childrenL.size()];
-                                       for(int j=0; j< children.length; j++) {
-                                               children[j] = (EscherRecord)childrenL.get(j);
-                                       }
+                                       childrenL.toArray(children);
                                        findEscherTextboxRecord(children,found);
                                }
                        }
@@ -309,8 +307,8 @@ public class PPDrawing extends RecordAtom
     public EscherDgRecord getEscherDgRecord(){
         if(dg == null){
             EscherContainerRecord dgContainer = (EscherContainerRecord)childRecords[0];
-            for(Iterator it = dgContainer.getChildRecords().iterator(); it.hasNext();){
-                EscherRecord r = (EscherRecord) it.next();
+            for(Iterator<EscherRecord> it = dgContainer.getChildIterator(); it.hasNext();){
+                EscherRecord r = it.next();
                 if(r instanceof EscherDgRecord){
                     dg = (EscherDgRecord)r;
                     break;
index c7de1fccd7ad1bc8d2803e9e15d552d76b482902..a9ccd7071d27e5b93a8274ca9fd61fcd7dd31951 100644 (file)
@@ -71,15 +71,14 @@ public class PPDrawingGroup extends RecordAtom {
 
     public void writeOut(OutputStream out) throws IOException {
         ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        List child = dggContainer.getChildRecords();
-        for (int i = 0; i < child.size(); i++) {
-            EscherRecord r = (EscherRecord)child.get(i);
+        Iterator<EscherRecord> iter = dggContainer.getChildIterator();
+        while (iter.hasNext()) {
+               EscherRecord r = iter.next();
             if (r.getRecordId() == EscherContainerRecord.BSTORE_CONTAINER){
                 EscherContainerRecord bstore = (EscherContainerRecord)r;
 
                 ByteArrayOutputStream b2 = new ByteArrayOutputStream();
-                List blip = bstore.getChildRecords();
-                for (Iterator it=blip.iterator(); it.hasNext();) {
+                for (Iterator<EscherRecord> it= bstore.getChildIterator(); it.hasNext();) {
                     EscherBSERecord bse = (EscherBSERecord)it.next();
                     byte[] b = new byte[36+8];
                     bse.serialize(0, b);
@@ -121,8 +120,8 @@ public class PPDrawingGroup extends RecordAtom {
 
     public EscherDggRecord getEscherDggRecord(){
         if(dgg == null){
-            for(Iterator it = dggContainer.getChildRecords().iterator(); it.hasNext();){
-                EscherRecord r = (EscherRecord) it.next();
+            for(Iterator<EscherRecord> it = dggContainer.getChildIterator(); it.hasNext();){
+                EscherRecord r = it.next();
                 if(r instanceof EscherDggRecord){
                     dgg = (EscherDggRecord)r;
                     break;
index 1c210365129b0d00d6610def48612c6ca4712a76..e5fbf12412d4b38c375b1cb6a29c62244418fcd6 100644 (file)
@@ -746,19 +746,11 @@ public final class SlideShow {
             bstore = new EscherContainerRecord();
             bstore.setRecordId( EscherContainerRecord.BSTORE_CONTAINER);
 
-            List child = dggContainer.getChildRecords();
-            for ( int i = 0; i < child.size(); i++ ) {
-                EscherRecord rec = (EscherRecord)child.get(i);
-                if (rec.getRecordId() == EscherOptRecord.RECORD_ID){
-                    child.add(i, bstore);
-                    i++;
-                }
-            }
-            dggContainer.setChildRecords(child);
+            dggContainer.addChildBefore(bstore, EscherOptRecord.RECORD_ID);
         } else {
-            List lst = bstore.getChildRecords();
-            for ( int i = 0; i < lst.size(); i++ ) {
-                EscherBSERecord bse = (EscherBSERecord) lst.get(i);
+            Iterator<EscherRecord> iter = bstore.getChildIterator();
+            for (int i = 0; iter.hasNext(); i++) {
+                EscherBSERecord bse = (EscherBSERecord) iter.next();
                 if (Arrays.equals(bse.getUid(), uid)){
                     return i + 1;
                 }
index f7fecb666e6df70daeab9e0767c982fcde84a7a7..9d067d6eaf648c92f386f900a15013e093fae639 100755 (executable)
@@ -44,8 +44,8 @@ public class TestEscherBlipRecord extends TestCase
 \r
         EscherContainerRecord record = new EscherContainerRecord();\r
         record.fillFields(data, 0, new DefaultEscherRecordFactory());\r
-        EscherContainerRecord bstore = (EscherContainerRecord)record.getChildRecords().get(1);\r
-        EscherBSERecord bse1 = (EscherBSERecord)bstore.getChildRecords().get(0);\r
+        EscherContainerRecord bstore = (EscherContainerRecord)record.getChild(1);\r
+        EscherBSERecord bse1 = (EscherBSERecord)bstore.getChild(0);\r
         assertEquals(EscherBSERecord.BT_PNG, bse1.getBlipTypeWin32());\r
         assertEquals(EscherBSERecord.BT_PNG, bse1.getBlipTypeMacOS());\r
         assertTrue(Arrays.equals(new byte[]{\r
@@ -89,8 +89,8 @@ public class TestEscherBlipRecord extends TestCase
 \r
         EscherContainerRecord record = new EscherContainerRecord();\r
         record.fillFields(data, 0, new DefaultEscherRecordFactory());\r
-        EscherContainerRecord bstore = (EscherContainerRecord)record.getChildRecords().get(1);\r
-        EscherBSERecord bse1 = (EscherBSERecord)bstore.getChildRecords().get(1);\r
+        EscherContainerRecord bstore = (EscherContainerRecord)record.getChild(1);\r
+        EscherBSERecord bse1 = (EscherBSERecord)bstore.getChild(1);\r
         //System.out.println(bse1);\r
         assertEquals(EscherBSERecord.BT_WMF, bse1.getBlipTypeWin32());\r
         assertEquals(EscherBSERecord.BT_PICT, bse1.getBlipTypeMacOS());\r
index 593290b337649c900fde68cb6ba899ef8dfb6e43..a70f166a1dbfd546c7bd299e8af622018f035389 100644 (file)
@@ -34,15 +34,11 @@ import java.util.List;
  *
  * @author Glen Stampoultzis (glens at apache.org)
  */
-public class TestEscherAggregate extends TestCase
-{
+public final class TestEscherAggregate extends TestCase {
     /**
      * Tests that the create aggregate method correctly rejoins escher records together.
-     *
-     * @throws Exception
      */
-    public void testCreateAggregate() throws Exception
-    {
+    public void testCreateAggregate() {
         String msoDrawingRecord1 =
                 "0F 00 02 F0 20 01 00 00 10 00 08 F0 08 00 00 00 \n" +
                 "03 00 00 00 02 04 00 00 0F 00 03 F0 08 01 00 00 \n" +
@@ -76,7 +72,7 @@ public class TestEscherAggregate extends TestCase
 
         ObjRecord r2 = new ObjRecord();
 
-        List records = new ArrayList();
+        List<Record> records = new ArrayList<Record>();
         records.add( d1 );
         records.add( r1 );
         records.add( d2 );
@@ -92,8 +88,7 @@ public class TestEscherAggregate extends TestCase
 //        System.out.println( "aggregate = " + aggregate );
     }
 
-    public void testSerialize() throws Exception
-    {
+    public void testSerialize() {
 
         EscherContainerRecord container1 = new EscherContainerRecord();
         EscherContainerRecord spContainer1 = new EscherContainerRecord();
@@ -127,8 +122,8 @@ public class TestEscherAggregate extends TestCase
 
         EscherAggregate aggregate = new EscherAggregate(null);
         aggregate.addEscherRecord( container1 );
-        aggregate.assoicateShapeToObjRecord( d2, new ObjRecord() );
-        aggregate.assoicateShapeToObjRecord( d3, new ObjRecord() );
+        aggregate.associateShapeToObjRecord( d2, new ObjRecord() );
+        aggregate.associateShapeToObjRecord( d3, new ObjRecord() );
 
         byte[] data = new byte[112];
         int bytesWritten = aggregate.serialize( 0, data );
@@ -136,5 +131,4 @@ public class TestEscherAggregate extends TestCase
         assertEquals( "[EC, 00, 40, 00, 0F, 00, 00, 00, 58, 00, 00, 00, 0F, 00, 04, F0, 10, 00, 00, 00, 00, 00, 0A, F0, 08, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0F, 00, 04, F0, 18, 00, 00, 00, 00, 00, 0A, F0, 08, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 11, F0, 00, 00, 00, 00, 5D, 00, 00, 00, EC, 00, 20, 00, 0F, 00, 04, F0, 18, 00, 00, 00, 00, 00, 0A, F0, 08, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 11, F0, 00, 00, 00, 00, 5D, 00, 00, 00]",
                 HexDump.toHex( data ) );
     }
-
 }