]> source.dussan.org Git - poi.git/commitdiff
Bugzilla 53010, patch from June 3: improved support for Continue records in drawing...
authorYegor Kozlov <yegor@apache.org>
Mon, 4 Jun 2012 08:08:47 +0000 (08:08 +0000)
committerYegor Kozlov <yegor@apache.org>
Mon, 4 Jun 2012 08:08:47 +0000 (08:08 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1345858 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/model/InternalSheet.java
src/java/org/apache/poi/hssf/record/DrawingRecord.java
src/java/org/apache/poi/hssf/record/EscherAggregate.java
src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java
src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java
src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java [deleted file]
src/testcases/org/apache/poi/hssf/record/TestDrawingRecord.java
test-data/spreadsheet/DrawingAndComments.xls [new file with mode: 0755]
test-data/spreadsheet/DrawingContinue.xls [new file with mode: 0755]

index 75ea355e50b11408a520d4403b52c553891cffed..1e0af24530989d367460f7bda6accecdc4aec9a0 100644 (file)
@@ -1508,31 +1508,10 @@ public final class InternalSheet {
             return loc;
         }
         List<RecordBase> records = getRecords();
-        EscherAggregate r = EscherAggregate.createAggregate( records, loc, drawingManager );
-        int startloc = loc;
-        while ( loc + 1 < records.size()
-                && records.get( loc ) instanceof DrawingRecord
-                && (records.get( loc + 1 ) instanceof ObjRecord ||
-                    records.get( loc + 1 ) instanceof TextObjectRecord) )
-        {
-            loc += 2;
-            if (records.get( loc ) instanceof NoteRecord) loc ++;
-            while ( loc + 1 < records.size()
-                    && records.get( loc ) instanceof ContinueRecord
-                    && (records.get( loc + 1 ) instanceof ObjRecord ||
-                    records.get( loc + 1 ) instanceof TextObjectRecord) )
-            {
-                loc += 2;
-                if (records.get( loc ) instanceof NoteRecord) loc ++;
-            }
-        }
 
-        int endloc = loc-1;
-        for(int i = 0; i < (endloc - startloc + 1); i++)
-            records.remove(startloc);
-        records.add(startloc, r);
+        EscherAggregate.createAggregate( records, loc, drawingManager );
 
-        return startloc;
+        return loc;
     }
 
     /**
index 7b94e26c167e16844e5b7d20d7d95f589e8939ae..9e104de59e5e57f9880cc9046a3b935719f69922 100644 (file)
@@ -20,22 +20,21 @@ package org.apache.poi.hssf.record;
 import org.apache.poi.util.LittleEndianOutput;
 /**
  * DrawingRecord (0x00EC)<p/>
- *
  */
 public final class DrawingRecord extends StandardRecord {
     public static final short sid = 0x00EC;
 
-       private static final byte[] EMPTY_BYTE_ARRAY = { };
+    private static final byte[] EMPTY_BYTE_ARRAY = {};
 
     private byte[] recordData;
     private byte[] contd;
 
     public DrawingRecord() {
-       recordData = EMPTY_BYTE_ARRAY;
+        recordData = EMPTY_BYTE_ARRAY;
     }
 
     public DrawingRecord(RecordInputStream in) {
-      recordData = in.readRemainder();
+        recordData = in.readRemainder();
     }
 
     public void processContinueRecord(byte[] record) {
@@ -46,6 +45,7 @@ public final class DrawingRecord extends StandardRecord {
     public void serialize(LittleEndianOutput out) {
         out.write(recordData);
     }
+
     protected int getDataSize() {
         return recordData.length;
     }
@@ -55,12 +55,12 @@ public final class DrawingRecord extends StandardRecord {
     }
 
     public byte[] getData() {
-        if(contd != null) {
-            byte[] newBuffer = new byte[ recordData.length + contd.length ];
-            System.arraycopy( recordData, 0, newBuffer, 0, recordData.length );
-            System.arraycopy( contd, 0, newBuffer, recordData.length, contd.length);
-            return newBuffer;
-        }
+//        if (continueData.size() != 0) {
+//            byte[] newBuffer = new byte[recordData.length + continueData.size()];
+//            System.arraycopy(recordData, 0, newBuffer, 0, recordData.length);
+//            System.arraycopy(continueData.toByteArray(), 0, newBuffer, recordData.length, continueData.size());
+//            return newBuffer;
+//        }
         return recordData;
     }
 
@@ -69,21 +69,20 @@ public final class DrawingRecord extends StandardRecord {
     }
 
     public void setData(byte[] thedata) {
-       if (thedata == null) {
-               throw new IllegalArgumentException("data must not be null");
-       }
+        if (thedata == null) {
+            throw new IllegalArgumentException("data must not be null");
+        }
         recordData = thedata;
     }
 
     public Object clone() {
-       DrawingRecord rec = new DrawingRecord();
-       
-       rec.recordData = recordData.clone();
-       if (contd != null) {
-               // TODO - this code probably never executes
-               rec.contd = contd.clone();
-       }
-       
-       return rec;
+        DrawingRecord rec = new DrawingRecord();
+        rec.recordData = recordData.clone();
+        if (contd != null) {
+            // TODO - this code probably never executes
+            rec.contd = contd.clone();
+        }
+
+        return rec;
     }
-}
\ No newline at end of file
+}
index e2ca3dd475d75d12927c27c719dcb6c35f3adbcd..3bb7127356a5d7eefb1445afab1e3ad187369986 100644 (file)
 
 package org.apache.poi.hssf.record;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.*;
 
 import org.apache.poi.ddf.DefaultEscherRecordFactory;
 import org.apache.poi.ddf.EscherBoolProperty;
@@ -65,884 +63,912 @@ import org.apache.poi.util.POILogger;
  * combination of MSODRAWING -> OBJ -> MSODRAWING -> OBJ records
  * but the escher records are serialized _across_ the MSODRAWING
  * records.
- * <p>
+ * <p/>
  * It gets even worse when you start looking at TXO records.
- * <p>
+ * <p/>
  * So what we do with this class is aggregate lazily.  That is
  * we don't aggregate the MSODRAWING -> OBJ records unless we
  * need to modify them.
+ * <p/>
+ * At first document contains 4 types of records which belong to drawing layer.
+ * There are can be such sequence of record:
+ * <p/>
+ * DrawingRecord
+ * ContinueRecord
+ * ...
+ * ContinueRecord
+ * ObjRecord | TextObjectRecord
+ * .....
+ * ContinueRecord
+ * ...
+ * ContinueRecord
+ * ObjRecord | TextObjectRecord
+ * NoteRecord
+ * ...
+ * NoteRecord
+ * <p/>
+ * To work with shapes we have to read data from Drawing and Continue records into single array of bytes and
+ * build escher(office art) records tree from this array.
+ * Each shape in drawing layer matches corresponding ObjRecord
+ * Each textbox matches corresponding TextObjectRecord
  *
+ * ObjRecord contains information about shape. Thus each ObjRecord corresponds EscherContainerRecord(SPGR)
+ *
+ * EscherAggrefate contains also NoteRecords
+ * NoteRecords must be serial
  *
  * @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 {@link TextObjectRecord} or {@link ObjRecord} */
-       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();
-       }
-    
-    public String toXml(String tab){
+    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 final 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();
+    }
+
+    public String toXml(String tab) {
         StringBuilder builder = new StringBuilder();
         builder.append(tab).append("<").append(getRecordName()).append(">\n");
-        for ( Iterator iterator = getEscherRecords().iterator(); iterator.hasNext(); )
-        {
+        for (Iterator iterator = getEscherRecords().iterator(); iterator.hasNext(); ) {
             EscherRecord escherRecord = (EscherRecord) iterator.next();
-            builder.append( escherRecord.toXml(tab+"\t") );
+            builder.append(escherRecord.toXml(tab + "\t"));
         }
         builder.append(tab).append("</").append(getRecordName()).append(">\n");
         return builder.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 ) ).getRecordData().length;
-                       loc += 2;
-            while ( loc + 1 < records.size()
-                    && sid( records, loc ) == ContinueRecord.sid
-                    && isObjectRecord( records, loc + 1 ) )
-            {
-                dataSize += ( (ContinueRecord) records.get( loc ) ).getData().length;
-                loc += 2;
+    private static boolean isDrawingLayerRecord(final short sid) {
+        return sid == DrawingRecord.sid ||
+                sid == ContinueRecord.sid ||
+                sid == ObjRecord.sid ||
+                sid == TextObjectRecord.sid;
+    }
+
+    /**
+     * Collapses the drawing records into an aggregate.
+     * read Drawing and Continue records into single byte array, create Escher tree from byte array, create map <EscherRecord, Record>
+     */
+    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;
             }
-               }
-
-               // 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.getRecordData(), 0, buffer, offset, drawingRecord.getRecordData().length );
-                       offset += drawingRecord.getRecordData().length;
-                       loc += 2;
-            while ( loc + 1 < records.size()
-                    && sid( records, loc ) == ContinueRecord.sid
-                    && isObjectRecord( records, loc + 1 ) )
-            {
-                ContinueRecord continueRecord = (ContinueRecord) records.get( loc );
-                System.arraycopy( continueRecord.getData(), 0, buffer, offset, continueRecord.getData().length );
-                offset += continueRecord.getData().length;
-                loc += 2;
+        };
+
+        // Create one big buffer
+        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+        EscherAggregate agg = new EscherAggregate(drawingManager);
+        int loc = locFirstDrawingRecord;
+        while (loc + 1 < records.size()
+                && (isDrawingLayerRecord(sid(records, loc)))) {
+            try {
+                if (!(sid(records, loc) == DrawingRecord.sid || sid(records, loc) == ContinueRecord.sid)) {
+                    loc++;
+                    continue;
+                }
+                if (sid(records, loc) == DrawingRecord.sid) {
+                    buffer.write(((DrawingRecord) records.get(loc)).getRecordData());
+                } else {
+                    buffer.write(((ContinueRecord) records.get(loc)).getData());
+                }
+            } catch (IOException e) {
+                throw new RuntimeException("Couldn't get data from drawing/continue records", e);
+            }
+            loc++;
+        }
+
+        // Decode the shapes
+        //             agg.escherRecords = new ArrayList();
+        int pos = 0;
+        while (pos < buffer.size()) {
+            EscherRecord r = recordFactory.createRecord(buffer.toByteArray(), pos);
+            int bytesRead = r.fillFields(buffer.toByteArray(), pos, recordFactory);
+            agg.addEscherRecord(r);
+            pos += bytesRead;
+        }
+
+        // Associate the object records with the shapes
+        loc = locFirstDrawingRecord + 1;
+        int shapeIndex = 0;
+        while (loc < records.size()
+                && (isDrawingLayerRecord(sid(records, loc)))) {
+            if (!isObjectRecord(records, loc)) {
+                loc++;
+                continue;
+            }
+            Record objRecord = (Record) records.get(loc);
+            agg.shapeToObj.put(shapeRecords.get(shapeIndex++), objRecord);
+            loc++;
+        }
+
+        // any NoteRecords that follow the drawing block must be aggregated and and saved in the tailRec collection
+        // TODO remove this logic. 'tail' records should be inserted in the main record stream
+        while (loc < records.size()) {
+            if (sid(records, loc) == NoteRecord.sid) {
+                NoteRecord r = (NoteRecord) records.get(loc);
+                agg.tailRec.add(r);
+            } else {
+                break;
+            }
+            loc++;
+        }
+
+        int locLastDrawingRecord = loc;
+        // replace drawing block with the created EscherAggregate
+        records.subList(locFirstDrawingRecord, locLastDrawingRecord).clear();
+        records.add(locFirstDrawingRecord, agg);
+
+
+        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(Integer.valueOf(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;
+        int writtenEscherBytes = 0;
+        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();
+
+
+            byte[] drawingData = new byte[endOffset - startOffset + 1];
+            System.arraycopy(buffer, startOffset, drawingData, 0, drawingData.length);
+            int temp = 0;
+
+            //First record in drawing layer MUST be DrawingRecord
+            if (writtenEscherBytes + drawingData.length > RecordInputStream.MAX_RECORD_DATA_SIZE && i != 1) {
+                for (int j = 0; j < drawingData.length; j += RecordInputStream.MAX_RECORD_DATA_SIZE) {
+                    ContinueRecord drawing = new ContinueRecord(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length)));
+                    temp += drawing.serialize(pos + temp, data);
+                }
+            } else {
+                for (int j = 0; j < drawingData.length; j += RecordInputStream.MAX_RECORD_DATA_SIZE) {
+                    if (j == 0) {
+                        DrawingRecord drawing = new DrawingRecord();
+                        drawing.setData(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length)));
+                        temp += drawing.serialize(pos + temp, data);
+                    } else {
+                        ContinueRecord drawing = new ContinueRecord(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length)));
+                        temp += drawing.serialize(pos + temp, data);
+                    }
+                }
+
             }
-               }
-
-               // 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;
-            while ( loc + 1 < records.size()
-                    && sid( records, loc ) == ContinueRecord.sid
-                    && isObjectRecord( records, loc + 1 ) )
-            {
-                objRecord = (Record) records.get( loc + 1 );
-                agg.shapeToObj.put( shapeRecords.get( shapeIndex++ ), objRecord );
-                loc += 2;
+
+            pos += temp;
+            writtenEscherBytes += drawingData.length;
+
+            // Write the matching OBJ record
+            Record obj = 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();
+        // To determine size of aggregate record we have to know size of each DrawingRecord because if DrawingRecord
+        // is split into several continue records we have to add header size to total EscherAggregate size
+        int continueRecordsHeadersSize = 0;
+        // Determine buffer size
+        List<EscherRecord> records = getEscherRecords();
+        int rawEscherSize = getEscherRecordSize(records);
+        byte[] buffer = new byte[rawEscherSize];
+        final List<Integer> spEndingOffsets = new ArrayList<Integer>();
+        int pos = 0;
+        for (EscherRecord e : records) {
+            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(offset);
+                    }
+                }
+            });
+        }
+        spEndingOffsets.add(0, 0);
+
+        for (int i = 1; i < spEndingOffsets.size(); i++) {
+            if (spEndingOffsets.get(i) - spEndingOffsets.get(i - 1) <= RecordInputStream.MAX_RECORD_DATA_SIZE){
+                continue;
             }
-               }
-
-               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( Integer.valueOf( 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 = 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 = 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()
-                       );
-               }
-
-               convertRecordsToUserModelRecursive(tcc, patriarch, null);
-
-               // Now, clear any trace of what records make up
-               //  the patriarch
-               // Otherwise, everything will go horribly wrong
-               //  when we try to write out again....
+            continueRecordsHeadersSize += ((spEndingOffsets.get(i) - spEndingOffsets.get(i - 1)) / RecordInputStream.MAX_RECORD_DATA_SIZE)*4;
+        }
+
+        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 +continueRecordsHeadersSize;
+    }
+
+    /**
+     * 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 = 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()
+            );
+        }
+
+        convertRecordsToUserModelRecursive(tcc, patriarch, null);
+
+        // 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 static void convertRecordsToUserModelRecursive(List tcc, HSSFShapeContainer container, HSSFShape parent) {
-               // Now process the containers for each group
-               //  and objects
-               for(int i=1; i<tcc.size(); i++) {
-                       EscherContainerRecord shapeContainer = (EscherContainerRecord)tcc.get(i);
-
-                       // Could be a group, or a base object
-                       if (shapeContainer.getRecordId() == EscherContainerRecord.SPGR_CONTAINER)
-                       {
-                               // Group
-                               final int shapeChildren = shapeContainer.getChildRecords().size();
-                               if (shapeChildren > 0)
-                               {
-                                       HSSFShapeGroup group = new HSSFShapeGroup( parent, new HSSFClientAnchor() );
-                                       addToParentOrContainer(group, container, parent);
-
-                                       EscherContainerRecord groupContainer = (EscherContainerRecord) shapeContainer.getChild( 0 );
-                                       convertRecordsToUserModel( groupContainer, group );
-                                       
-                                       if (shapeChildren>1){
-                                               convertRecordsToUserModelRecursive(shapeContainer.getChildRecords(), container, group);
-                                       }
-                               } else
-                               {
-                                       log.log( POILogger.WARN,
-                                                       "Found drawing group without children." );
-                               }
-
-                       } else if (shapeContainer.getRecordId() == EscherContainerRecord.SP_CONTAINER)
-                       {
-                               EscherSpRecord spRecord = shapeContainer
-                                               .getChildById( EscherSpRecord.RECORD_ID );
-                               int type = spRecord.getShapeType();
-
-                               switch (type)
-                               {
-                               case ST_TEXTBOX:
-                                       HSSFTextbox box = new HSSFTextbox( parent,
-                                                       new HSSFClientAnchor() );
-                                       addToParentOrContainer(box, container, parent);
-
-                                       convertRecordsToUserModel( shapeContainer, box );
-                                       break;
-                               case ST_PICTUREFRAME:
-                                       // Duplicated from
-                                       // org.apache.poi.hslf.model.Picture.getPictureIndex()
-                                       EscherOptRecord opt = (EscherOptRecord) getEscherChild(
-                                                       shapeContainer, EscherOptRecord.RECORD_ID );
-                                       EscherSimpleProperty prop = (EscherSimpleProperty)opt.lookup(
-                                                       EscherProperties.BLIP__BLIPTODISPLAY );
-                                       if (prop == null)
-                                       {
-                                               log.log( POILogger.WARN,
-                                                               "Picture index for picture shape not found." );
-                                       } else
-                                       {
-                                               int pictureIndex = prop.getPropertyValue();
-
-                                               EscherClientAnchorRecord anchorRecord = (EscherClientAnchorRecord) getEscherChild(
-                                                               shapeContainer,
-                                                               EscherClientAnchorRecord.RECORD_ID );
-
-                                               EscherChildAnchorRecord childRecord = (EscherChildAnchorRecord) getEscherChild(
-                                                               shapeContainer,
-                                                               EscherChildAnchorRecord.RECORD_ID );
-
-                                               if (anchorRecord!=null && childRecord!=null){
-                                                       log.log( POILogger.WARN, "Picture with both CLIENT and CHILD anchor: "+ type );
-                                               }
-                                       
-                                               HSSFAnchor anchor;
-                                               if (anchorRecord!=null){
-                                                       anchor = toClientAnchor(anchorRecord);
-                                               }else{
-                                                       anchor = toChildAnchor(childRecord);
-                                               }
-
-                                               HSSFPicture picture = new HSSFPicture( parent, anchor );
-                                               picture.setPictureIndex( pictureIndex );
-
-                                               addToParentOrContainer(picture, container, parent);
-                                       }
-                                       break;
-                               default:
-                                       final HSSFSimpleShape shape = new HSSFSimpleShape( parent,
-                                                       new HSSFClientAnchor() );
-                                       addToParentOrContainer(shape, container, parent);
-                                       convertRecordsToUserModel( shapeContainer, shape);
-                                       
-                                       log.log( POILogger.WARN, "Unhandled shape type: "
-                                                       + type );
-                                       break;
-                               }
-                       } else
-                       {
-                               log.log( POILogger.WARN, "Unexpected record id of shape group." );
-                       }
-
-               }
-       }
+        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 static void convertRecordsToUserModelRecursive(List tcc, HSSFShapeContainer container, HSSFShape parent) {
+        // Now process the containers for each group
+        //  and objects
+        for (int i = 1; i < tcc.size(); i++) {
+            EscherContainerRecord shapeContainer = (EscherContainerRecord) tcc.get(i);
+
+            // Could be a group, or a base object
+            if (shapeContainer.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) {
+                // Group
+                final int shapeChildren = shapeContainer.getChildRecords().size();
+                if (shapeChildren > 0) {
+                    HSSFShapeGroup group = new HSSFShapeGroup(parent, new HSSFClientAnchor());
+                    addToParentOrContainer(group, container, parent);
+
+                    EscherContainerRecord groupContainer = (EscherContainerRecord) shapeContainer.getChild(0);
+                    convertRecordsToUserModel(groupContainer, group);
+
+                    if (shapeChildren > 1) {
+                        convertRecordsToUserModelRecursive(shapeContainer.getChildRecords(), container, group);
+                    }
+                } else {
+                    log.log(POILogger.WARN,
+                            "Found drawing group without children.");
+                }
+
+            } else if (shapeContainer.getRecordId() == EscherContainerRecord.SP_CONTAINER) {
+                EscherSpRecord spRecord = shapeContainer
+                        .getChildById(EscherSpRecord.RECORD_ID);
+                int type = spRecord.getShapeType();
+
+                switch (type) {
+                    case ST_TEXTBOX:
+                        HSSFTextbox box = new HSSFTextbox(parent,
+                                new HSSFClientAnchor());
+                        addToParentOrContainer(box, container, parent);
+
+                        convertRecordsToUserModel(shapeContainer, box);
+                        break;
+                    case ST_PICTUREFRAME:
+                        // Duplicated from
+                        // org.apache.poi.hslf.model.Picture.getPictureIndex()
+                        EscherOptRecord opt = (EscherOptRecord) getEscherChild(
+                                shapeContainer, EscherOptRecord.RECORD_ID);
+                        EscherSimpleProperty prop = (EscherSimpleProperty) opt.lookup(
+                                EscherProperties.BLIP__BLIPTODISPLAY);
+                        if (prop == null) {
+                            log.log(POILogger.WARN,
+                                    "Picture index for picture shape not found.");
+                        } else {
+                            int pictureIndex = prop.getPropertyValue();
+
+                            EscherClientAnchorRecord anchorRecord = (EscherClientAnchorRecord) getEscherChild(
+                                    shapeContainer,
+                                    EscherClientAnchorRecord.RECORD_ID);
+
+                            EscherChildAnchorRecord childRecord = (EscherChildAnchorRecord) getEscherChild(
+                                    shapeContainer,
+                                    EscherChildAnchorRecord.RECORD_ID);
+
+                            if (anchorRecord != null && childRecord != null) {
+                                log.log(POILogger.WARN, "Picture with both CLIENT and CHILD anchor: " + type);
+                            }
+
+                            HSSFAnchor anchor;
+                            if (anchorRecord != null) {
+                                anchor = toClientAnchor(anchorRecord);
+                            } else {
+                                anchor = toChildAnchor(childRecord);
+                            }
+
+                            HSSFPicture picture = new HSSFPicture(parent, anchor);
+                            picture.setPictureIndex(pictureIndex);
+
+                            addToParentOrContainer(picture, container, parent);
+                        }
+                        break;
+                    default:
+                        final HSSFSimpleShape shape = new HSSFSimpleShape(parent,
+                                new HSSFClientAnchor());
+                        addToParentOrContainer(shape, container, parent);
+                        convertRecordsToUserModel(shapeContainer, shape);
+
+                        log.log(POILogger.WARN, "Unhandled shape type: "
+                                + type);
+                        break;
+                }
+            } else {
+                log.log(POILogger.WARN, "Unexpected record id of shape group.");
+            }
+
+        }
+    }
 
     private static void addToParentOrContainer(HSSFShape shape, HSSFShapeContainer container, HSSFShape parent) {
 
-       if (parent instanceof HSSFShapeGroup)
-               ((HSSFShapeGroup) parent).addShape(shape);
-       else if (container instanceof HSSFPatriarch)
-               ((HSSFPatriarch) container).addShape(shape);
-       else
-               container.getChildren().add(shape);
-       }
+        if (parent instanceof HSSFShapeGroup)
+            ((HSSFShapeGroup) parent).addShape(shape);
+        else if (container instanceof HSSFPatriarch)
+            ((HSSFPatriarch) container).addShape(shape);
+        else
+            container.getChildren().add(shape);
+    }
 
-       private static HSSFClientAnchor toClientAnchor(EscherClientAnchorRecord anchorRecord){
+    private static HSSFClientAnchor toClientAnchor(EscherClientAnchorRecord anchorRecord) {
         HSSFClientAnchor anchor = new HSSFClientAnchor();
         anchor.setAnchorType(anchorRecord.getFlag());
-        anchor.setCol1( anchorRecord.getCol1() );
-        anchor.setCol2( anchorRecord.getCol2() );
-        anchor.setDx1( anchorRecord.getDx1() );
-        anchor.setDx2( anchorRecord.getDx2() );
-        anchor.setDy1( anchorRecord.getDy1() );
-        anchor.setDy2( anchorRecord.getDy2() );
-        anchor.setRow1( anchorRecord.getRow1() );
-        anchor.setRow2( anchorRecord.getRow2() );
+        anchor.setCol1(anchorRecord.getCol1());
+        anchor.setCol2(anchorRecord.getCol2());
+        anchor.setDx1(anchorRecord.getDx1());
+        anchor.setDx2(anchorRecord.getDx2());
+        anchor.setDy1(anchorRecord.getDy1());
+        anchor.setDy2(anchorRecord.getDy2());
+        anchor.setRow1(anchorRecord.getRow1());
+        anchor.setRow2(anchorRecord.getRow2());
         return anchor;
     }
 
-    private static HSSFChildAnchor toChildAnchor(EscherChildAnchorRecord anchorRecord){
+    private static HSSFChildAnchor toChildAnchor(EscherChildAnchorRecord anchorRecord) {
         HSSFChildAnchor anchor = new HSSFChildAnchor();
 //        anchor.setAnchorType(anchorRecord.getFlag());
 //        anchor.setCol1( anchorRecord.getCol1() );
 //        anchor.setCol2( anchorRecord.getCol2() );
-        anchor.setDx1( anchorRecord.getDx1() );
-        anchor.setDx2( anchorRecord.getDx2() );
-        anchor.setDy1( anchorRecord.getDy1() );
-        anchor.setDy2( anchorRecord.getDy2() );
+        anchor.setDx1(anchorRecord.getDx1());
+        anchor.setDx2(anchorRecord.getDx2());
+        anchor.setDy1(anchorRecord.getDy1());
+        anchor.setDy2(anchorRecord.getDy2());
 //        anchor.setRow1( anchorRecord.getRow1() );
 //        anchor.setRow2( anchorRecord.getRow2() );
         return anchor;
     }
 
-       private static 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
-                               final EscherSpRecord spr = (EscherSpRecord) r;
-                               if (model instanceof HSSFShape){
-                                       final HSSFShape s = (HSSFShape) model;
-                               }
-                       }
-                       else if(r instanceof EscherOptRecord) {
-                               // Use properties if needed
-                       }
-                       else {
-                               //System.err.println(r);
-                       }
-               }
-       }
-
-       public void clear()
-       {
-               clearEscherRecords();
-               shapeToObj.clear();
+    private static 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
+                final EscherSpRecord spr = (EscherSpRecord) r;
+                if (model instanceof HSSFShape) {
+                    final HSSFShape s = (HSSFShape) model;
+                }
+            } 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() );
-                       }
-               }
+    }
+
+    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() );
+    }
+
+    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() );
@@ -951,113 +977,108 @@ public final class EscherAggregate extends AbstractEscherHolderRecord {
 //             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( 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();
+        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(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();
-       }
-
-
-       // Duplicated from org.apache.poi.hslf.model.Shape
-
-       /**
-        * Helper method to return escher child by record ID
-        * 
-        * @return escher record or <code>null</code> if not found.
-        */
-       private static EscherRecord getEscherChild(EscherContainerRecord owner,
-                       int recordId)
-       {
-               for (Iterator iterator = owner.getChildRecords().iterator(); iterator
-                               .hasNext();)
-               {
-                       EscherRecord escherRecord = (EscherRecord) iterator.next();
-                       if (escherRecord.getRecordId() == recordId)
-                               return escherRecord;
-               }
-               return null;
-       }
+        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();
+    }
+
+
+    // Duplicated from org.apache.poi.hslf.model.Shape
+
+    /**
+     * Helper method to return escher child by record ID
+     *
+     * @return escher record or <code>null</code> if not found.
+     */
+    private static EscherRecord getEscherChild(EscherContainerRecord owner,
+                                               int recordId) {
+        for (Iterator iterator = owner.getChildRecords().iterator(); iterator
+                .hasNext(); ) {
+            EscherRecord escherRecord = (EscherRecord) iterator.next();
+            if (escherRecord.getRecordId() == recordId)
+                return escherRecord;
+        }
+        return null;
+    }
 
 }
index 344ad07ef3c4f7c9d6b6b308869590d206c731ac..aac88b80c978a7d18e338827d6866e8428125239 100644 (file)
@@ -338,14 +338,14 @@ public final class RecordFactoryInputStream {
                        }
                        if (_lastRecord instanceof DrawingGroupRecord) {
                                ((DrawingGroupRecord) _lastRecord).processContinueRecord(contRec.getData());
-                               return null;
-                       }
-                       if (_lastRecord instanceof DrawingRecord) {
-                               ((DrawingRecord) _lastRecord).processContinueRecord(contRec.getData());
-                               return null;
-                       }
-                       if (_lastRecord instanceof UnknownRecord) {
-                               //Gracefully handle records that we don't know about,
+                               return null;\r
+                       }\r
+                       if (_lastRecord instanceof DrawingRecord) {\r
+//                             ((DrawingRecord) _lastRecord).appendContinueRecord(contRec.getData());\r
+                               return contRec;\r
+                       }\r
+                       if (_lastRecord instanceof UnknownRecord) {\r
+                               //Gracefully handle records that we don't know about,\r
                                //that happen to be continued
                                return record;
                        }
index c5aa5855a9126d92cfd2d4e2e15e4eb39df9e6b8..a22ce4a0cc07c112ecf3480f99e3294f6f82468f 100644 (file)
 package org.apache.poi.hssf.model;\r
 \r
 import junit.framework.TestCase;\r
-import org.apache.poi.ddf.EscherClientDataRecord;\r
-import org.apache.poi.ddf.EscherContainerRecord;\r
 import org.apache.poi.ddf.EscherDggRecord;\r
-import org.apache.poi.ddf.EscherRecord;\r
-import org.apache.poi.ddf.EscherSpRecord;\r
 import org.apache.poi.hssf.HSSFTestDataSamples;\r
 import org.apache.poi.hssf.record.*;\r
 import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;\r
@@ -30,147 +26,199 @@ import org.apache.poi.hssf.usermodel.HSSFTestHelper;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;\r
 import org.apache.poi.util.HexRead;\r
 \r
-import java.io.ByteArrayInputStream;\r
-import java.util.ArrayList;\r
-import java.util.LinkedHashMap;\r
+import java.io.*;\r
+import java.util.Arrays;\r
 import java.util.List;\r
-import java.util.Map;\r
 \r
 /**\r
  * @author Yegor Kozlov\r
  * @author Evgeniy Berlog\r
  */\r
 public class TestDrawingAggregate extends TestCase {\r
+    private static byte[] toByteArray(List<RecordBase> records){\r
+            ByteArrayOutputStream out = new ByteArrayOutputStream();\r
+            for(RecordBase rb : records) {\r
+                    Record r = (Record)rb;\r
+                    try {\r
+                            out.write(r.serialize());\r
+                        } catch (IOException e){\r
+                            throw new RuntimeException(e);\r
+                        }\r
+                }\r
+            return out.toByteArray();\r
+        }\r
+\r
     /**\r
-     * Serialize escher aggregate, read back and assert that the drawing data is preserved.\r
-     *\r
-     * @param agg the aggregate to test\r
-     * @return verified aggregate (serialized and read back)\r
+     * test reading drawing aggregate from a test file from Bugzilla 45129\r
      */\r
-    public static EscherAggregate assertWriteAndReadBack(EscherAggregate agg) {\r
-        byte[] dgBytes = agg.serialize();\r
-\r
+    public void test45129() {\r
+        HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("45129.xls");\r
+        HSSFSheet sh = wb.getSheetAt(0);\r
 \r
-        List<Record> dgRecords = RecordFactory.createRecords(new ByteArrayInputStream(dgBytes));\r
+        InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb);\r
+        InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh);\r
 \r
-        DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord());\r
+        List<RecordBase> records = isheet.getRecords();\r
 \r
-        // create a dummy sheet consisting of our test data\r
-        InternalSheet sheet = InternalSheet.createSheet();\r
-        List<RecordBase> records = sheet.getRecords();\r
-        records.clear();\r
-        records.addAll(dgRecords);\r
-        records.add(EOFRecord.instance);\r
+        // the sheet's drawing is not aggregated\r
+        assertEquals("wrong size of sheet records stream", 394, records.size());\r
+        // the last record before the drawing block\r
+        assertTrue(\r
+                "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(),\r
+                records.get(18) instanceof RowRecordsAggregate);\r
 \r
+        // records to be aggregated\r
+        List<RecordBase> dgRecords = records.subList(19, 389);\r
+        // collect drawing records into a byte buffer.\r
+        byte[] dgBytes = toByteArray(dgRecords);\r
 \r
-        sheet.aggregateDrawingRecords(drawingManager, false);\r
-        assertEquals("drawing was not fully aggregated", 2, records.size());\r
-        assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate);\r
-        assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord);\r
-        EscherAggregate agg2 = (EscherAggregate) records.get(0);\r
+        for (RecordBase rb : dgRecords) {\r
+            Record r = (Record) rb;\r
+            short sid = r.getSid();\r
+            // we expect that drawing block consists of either\r
+            // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord\r
+            assertTrue(\r
+                    sid == DrawingRecord.sid ||\r
+                            sid == ContinueRecord.sid ||\r
+                            sid == ObjRecord.sid ||\r
+                            sid == TextObjectRecord.sid);\r
+        }\r
 \r
-        assertEquals(agg.getEscherRecords().size(), agg2.getEscherRecords().size());\r
+        // the first record after the drawing block\r
+        assertTrue(\r
+                "records.get(389) is expected to be Window2",\r
+                records.get(389) instanceof WindowTwoRecord);\r
 \r
-        // assert that both pre- and after- serialize aggregates have the same xml representation\r
-        for (int i = 0; i < agg.getEscherRecords().size(); i++) {\r
-            EscherRecord r1 = agg.getEscherRecords().get(i);\r
-            EscherRecord r2 = agg2.getEscherRecords().get(i);\r
+        // aggregate drawing records.\r
+        // The subrange [19, 388] is expected to be replaced with a EscherAggregate object\r
+        DrawingManager2 drawingManager = iworkbook.findDrawingGroup();\r
+        int loc = isheet.aggregateDrawingRecords(drawingManager, false);\r
+        EscherAggregate agg = (EscherAggregate) records.get(loc);\r
 \r
-            assertEquals(r1.toXml(), r2.toXml());\r
-        }\r
+        assertEquals("wrong size of the aggregated sheet records stream", 25, records.size());\r
+        assertTrue(\r
+                "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(),\r
+                records.get(18) instanceof RowRecordsAggregate);\r
+        assertTrue("records.get(19) is expected to be EscherAggregate but was " + records.get(19).getClass().getSimpleName(),\r
+                records.get(19) instanceof EscherAggregate);\r
+        assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(),\r
+                records.get(20) instanceof WindowTwoRecord);\r
 \r
-        return agg2;\r
+        byte[] dgBytesAfterSave = agg.serialize();\r
+        assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);\r
+        assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));\r
     }\r
 \r
     /**\r
-     * assert that mapping of Obj records to escher shape containers is the same in both aggregates\r
+     * Try to check file with such record sequence\r
+     * ...\r
+     * DrawingRecord\r
+     * ContinueRecord\r
+     * ObjRecord | TextObjRecord\r
+     * ...\r
      */\r
-    public static void assertObjectMappingSame(EscherAggregate agg1, EscherAggregate agg2) {\r
-\r
-        // map EscherClientDataRecord and EscherTextboxRecord to their parents\r
-        Map<EscherRecord, EscherContainerRecord> map1 = new LinkedHashMap<EscherRecord, EscherContainerRecord>();\r
-        for (EscherRecord r : agg1.getEscherRecords()) mapShapeContainers(r, map1);\r
-\r
-        Map<EscherRecord, EscherContainerRecord> map2 = new LinkedHashMap<EscherRecord, EscherContainerRecord>();\r
-        for (EscherRecord r : agg2.getEscherRecords()) mapShapeContainers(r, map2);\r
-\r
-        assertEquals("aggregates have different number of shapes", map1.size(), map2.size());\r
-\r
-        // for each EscherClientDataRecord get parent SP_CONTAINER and corresponding ObjRecord\r
-        // verify that ObjRecord to\r
-        List<EscherRecord> l1 = new ArrayList<EscherRecord>(map1.keySet());\r
-        List<EscherRecord> l2 = new ArrayList<EscherRecord>(map2.keySet());\r
-        for (int i = 0; i < l1.size(); i++) {\r
-            EscherRecord e1 = l1.get(i);\r
-            EscherRecord e2 = l2.get(i);\r
-            ObjRecord obj1 = (ObjRecord) HSSFRecordTestHelper.getShapeToObjForTest(agg1).get(e1);\r
-            ObjRecord obj2 = (ObjRecord) HSSFRecordTestHelper.getShapeToObjForTest(agg2).get(e2);\r
-\r
-            CommonObjectDataSubRecord cmo1 = (CommonObjectDataSubRecord) obj1.getSubRecords().get(0);\r
-            CommonObjectDataSubRecord cmo2 = (CommonObjectDataSubRecord) obj2.getSubRecords().get(0);\r
-\r
-            assertEquals(cmo1.getObjectId(), cmo2.getObjectId());\r
-            assertEquals(obj1.toString(), obj2.toString());\r
-\r
-            // test that obj parents have the same shapeId, that is, that shape is the same\r
-            EscherContainerRecord p1 = map1.get(e1);\r
-            EscherContainerRecord p2 = map2.get(e2);\r
-            EscherSpRecord sp1 = (EscherSpRecord) p1.getChildById(EscherSpRecord.RECORD_ID);\r
-            EscherSpRecord sp2 = (EscherSpRecord) p2.getChildById(EscherSpRecord.RECORD_ID);\r
-            assertEquals(sp1.getShapeId(), sp2.getShapeId());\r
-\r
-            assertEquals("wrong shape2obj mapping", sp1.getShapeId() % 1024, cmo1.getObjectId());\r
-            assertEquals(p1.toXml(), p2.toXml());\r
+    public void testSerializeDrawingBigger8k() {\r
+        HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("DrawingContinue.xls");\r
+        InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb);\r
+        HSSFSheet sh = wb.getSheetAt(0);\r
+        InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh);\r
+\r
+\r
+        List<RecordBase> records = isheet.getRecords();\r
+\r
+        // the sheet's drawing is not aggregated\r
+        assertEquals("wrong size of sheet records stream", 32, records.size());\r
+        // the last record before the drawing block\r
+        assertTrue(\r
+                "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(),\r
+                records.get(18) instanceof RowRecordsAggregate);\r
+\r
+        // records to be aggregated\r
+        List<RecordBase> dgRecords = records.subList(19, 26);\r
+        for (RecordBase rb : dgRecords) {\r
+            Record r = (Record) rb;\r
+            short sid = r.getSid();\r
+            // we expect that drawing block consists of either\r
+            // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord\r
+            assertTrue(\r
+                    sid == DrawingRecord.sid ||\r
+                            sid == ContinueRecord.sid ||\r
+                            sid == ObjRecord.sid ||\r
+                            sid == NoteRecord.sid ||\r
+                            sid == TextObjectRecord.sid);\r
         }\r
+        // collect drawing records into a byte buffer.\r
+        byte[] dgBytes = toByteArray(dgRecords);\r
+\r
+        // the first record after the drawing block\r
+        assertTrue(\r
+                "records.get(26) is expected to be Window2",\r
+                records.get(26) instanceof WindowTwoRecord);\r
+\r
+        // aggregate drawing records.\r
+        // The subrange [19, 38] is expected to be replaced with a EscherAggregate object\r
+        DrawingManager2 drawingManager = iworkbook.findDrawingGroup();\r
+        int loc = isheet.aggregateDrawingRecords(drawingManager, false);\r
+        EscherAggregate agg = (EscherAggregate) records.get(loc);\r
+\r
+        assertEquals("wrong size of the aggregated sheet records stream", 26, records.size());\r
+        assertTrue(\r
+                "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(),\r
+                records.get(18) instanceof RowRecordsAggregate);\r
+        assertTrue("records.get(19) is expected to be EscherAggregate but was " + records.get(19).getClass().getSimpleName(),\r
+                records.get(19) instanceof EscherAggregate);\r
+        assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(),\r
+                records.get(20) instanceof WindowTwoRecord);\r
+\r
+        byte[] dgBytesAfterSave = agg.serialize();\r
+        assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);\r
+        assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));\r
+\r
+\r
     }\r
 \r
-    /**\r
-     * recursively map EscherClientDataRecords  to their parent shape containers:\r
-     * <p/>\r
-     * EscherClientDataRecord1 --> EscherContainerRecord1\r
-     * EscherClientDataRecord2 --> EscherContainerRecord2\r
-     * ...\r
-     * <p/>\r
-     * TODO: YK: this method can be avoided if we have EscherRecord.getParent()\r
-     */\r
-    private static void mapShapeContainers(EscherRecord parent, Map<EscherRecord, EscherContainerRecord> map) {\r
-        if (parent.isContainerRecord()) {\r
-            if (parent.getRecordId() == EscherContainerRecord.SP_CONTAINER) {\r
-                // iterate over shape's children and search for EscherClientDataRecord\r
-                for (EscherRecord r : parent.getChildRecords()) {\r
-                    if (r.getRecordId() == EscherClientDataRecord.RECORD_ID) {\r
-                        map.put(r, (EscherContainerRecord) parent);\r
-                    }\r
-                }\r
-            } else {\r
-                for (EscherRecord ch : parent.getChildRecords()) {\r
-                    mapShapeContainers(ch, map);\r
-                }\r
+\r
+    public void testSerializeDrawingBigger8k_noAggregation() {\r
+        HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("DrawingContinue.xls");\r
+\r
+        InternalSheet isheet = HSSFTestHelper.getSheetForTest(wb.getSheetAt(0));\r
+        List<RecordBase> records = isheet.getRecords();\r
+\r
+        HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb);\r
+        InternalSheet isheet2 = HSSFTestHelper.getSheetForTest( wb2.getSheetAt(0));\r
+        List<RecordBase> records2 = isheet2.getRecords();\r
+\r
+        assertEquals(records.size(), records2.size());\r
+        for(int i = 0; i < records.size(); i++) {\r
+            RecordBase r1 = records.get(i);\r
+            RecordBase r2 = records2.get(i);\r
+            assertTrue(r1.getClass() == r2.getClass());\r
+            assertEquals(r1.getRecordSize(), r2.getRecordSize());\r
+            if(r1 instanceof Record ){\r
+                assertEquals(((Record)r1).getSid(), ((Record)r2).getSid());\r
+                assertTrue(Arrays.equals(((Record) r1).serialize(), ((Record) r2).serialize()));\r
             }\r
         }\r
+\r
     }\r
 \r
-    /**\r
-     * test reading drawing aggregate from a test file from Bugzilla 45129\r
-     */\r
-    public void test45129() {\r
-        HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("45129.xls");\r
+    public void testSerializeDrawingWithComments() throws IOException {\r
+        HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("DrawingAndComments.xls");\r
         HSSFSheet sh = wb.getSheetAt(0);\r
-\r
         InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb);\r
         InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh);\r
 \r
         List<RecordBase> records = isheet.getRecords();\r
 \r
         // the sheet's drawing is not aggregated\r
-        assertEquals("wrong size of sheet records stream", 394, records.size());\r
+        assertEquals("wrong size of sheet records stream", 46, records.size());\r
         // the last record before the drawing block\r
         assertTrue(\r
                 "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(),\r
                 records.get(18) instanceof RowRecordsAggregate);\r
 \r
         // records to be aggregated\r
-        List<RecordBase> dgRecords = records.subList(19, 388);\r
+        List<RecordBase> dgRecords = records.subList(19, 39);\r
         for (RecordBase rb : dgRecords) {\r
             Record r = (Record) rb;\r
             short sid = r.getSid();\r
@@ -180,21 +228,24 @@ public class TestDrawingAggregate extends TestCase {
                     sid == DrawingRecord.sid ||\r
                             sid == ContinueRecord.sid ||\r
                             sid == ObjRecord.sid ||\r
+                            sid == NoteRecord.sid ||\r
                             sid == TextObjectRecord.sid);\r
         }\r
+        // collect drawing records into a byte buffer.\r
+        byte[] dgBytes = toByteArray(dgRecords);\r
 \r
         // the first record after the drawing block\r
         assertTrue(\r
-                "records.get(389) is expected to be Window2",\r
-                records.get(389) instanceof WindowTwoRecord);\r
+                "records.get(39) is expected to be Window2",\r
+                records.get(39) instanceof WindowTwoRecord);\r
 \r
         // aggregate drawing records.\r
-        // The subrange [19, 388] is expected to be replaced with a EscherAggregate object\r
+        // The subrange [19, 38] is expected to be replaced with a EscherAggregate object\r
         DrawingManager2 drawingManager = iworkbook.findDrawingGroup();\r
         int loc = isheet.aggregateDrawingRecords(drawingManager, false);\r
         EscherAggregate agg = (EscherAggregate) records.get(loc);\r
 \r
-        assertEquals("wrong size of the aggregated sheet records stream", 25, records.size());\r
+        assertEquals("wrong size of the aggregated sheet records stream", 27, records.size());\r
         assertTrue(\r
                 "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(),\r
                 records.get(18) instanceof RowRecordsAggregate);\r
@@ -203,11 +254,12 @@ public class TestDrawingAggregate extends TestCase {
         assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(),\r
                 records.get(20) instanceof WindowTwoRecord);\r
 \r
-        EscherAggregate agg2 = assertWriteAndReadBack(agg);\r
-\r
-        assertObjectMappingSame(agg, agg2);\r
+        byte[] dgBytesAfterSave = agg.serialize();\r
+        assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);\r
+        assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));\r
     }\r
 \r
+\r
     public void testFileWithPictures() {\r
         HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ContinueRecordProblem.xls");\r
         HSSFSheet sh = wb.getSheetAt(0);\r
@@ -225,7 +277,7 @@ public class TestDrawingAggregate extends TestCase {
                 records.get(21) instanceof RowRecordsAggregate);\r
 \r
         // records to be aggregated\r
-        List<RecordBase> dgRecords = records.subList(22, 299);\r
+        List<RecordBase> dgRecords = records.subList(22, 300);\r
         for (RecordBase rb : dgRecords) {\r
             Record r = (Record) rb;\r
             short sid = r.getSid();\r
@@ -237,6 +289,8 @@ public class TestDrawingAggregate extends TestCase {
                             sid == ObjRecord.sid ||\r
                             sid == TextObjectRecord.sid);\r
         }\r
+        // collect drawing records into a byte buffer.\r
+        byte[] dgBytes = toByteArray(dgRecords);\r
 \r
         // the first record after the drawing block\r
         assertTrue(\r
@@ -244,7 +298,7 @@ public class TestDrawingAggregate extends TestCase {
                 records.get(300) instanceof WindowTwoRecord);\r
 \r
         // aggregate drawing records.\r
-        // The subrange [19, 388] is expected to be replaced with a EscherAggregate object\r
+        // The subrange [19, 299] is expected to be replaced with a EscherAggregate object\r
         DrawingManager2 drawingManager = iworkbook.findDrawingGroup();\r
         int loc = isheet.aggregateDrawingRecords(drawingManager, false);\r
         EscherAggregate agg = (EscherAggregate) records.get(loc);\r
@@ -258,9 +312,9 @@ public class TestDrawingAggregate extends TestCase {
         assertTrue("records.get(23) is expected to be Window2 but was " + records.get(23).getClass().getSimpleName(),\r
                 records.get(23) instanceof WindowTwoRecord);\r
 \r
-        EscherAggregate agg2 = assertWriteAndReadBack(agg);\r
-\r
-        assertObjectMappingSame(agg, agg2);\r
+        byte[] dgBytesAfterSave = agg.serialize();\r
+        assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);\r
+        assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));\r
     }\r
 \r
     public void testUnhandledContinue() {\r
@@ -972,10 +1026,9 @@ public class TestDrawingAggregate extends TestCase {
         assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord);\r
         EscherAggregate agg = (EscherAggregate) records.get(0);\r
 \r
-        // serialize, read back and assert that the drawing data is preserved\r
-        EscherAggregate agg2 = assertWriteAndReadBack(agg);\r
-\r
-        assertObjectMappingSame(agg, agg2);\r
+        byte[] dgBytesAfterSave = agg.serialize();\r
+        assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);\r
+        assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));\r
     }\r
 \r
     public void testUnhandledContinue2() {\r
@@ -1926,8 +1979,8 @@ public class TestDrawingAggregate extends TestCase {
 \r
         EscherAggregate agg = (EscherAggregate) records.get(0);\r
 \r
-        EscherAggregate agg2 = assertWriteAndReadBack(agg);\r
-\r
-        assertObjectMappingSame(agg, agg2);\r
+        byte[] dgBytesAfterSave = agg.serialize();\r
+        assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);\r
+        assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));\r
     }\r
 }\r
diff --git a/src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java b/src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java
deleted file mode 100644 (file)
index 4eed03d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- *    contributor license agreements.  See the NOTICE file distributed with\r
- *    this work for additional information regarding copyright ownership.\r
- *    The ASF licenses this file to You under the Apache License, Version 2.0\r
- *    (the "License"); you may not use this file except in compliance with\r
- *    the License.  You may obtain a copy of the License at\r
- *\r
- *        http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- *    Unless required by applicable law or agreed to in writing, software\r
- *    distributed under the License is distributed on an "AS IS" BASIS,\r
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- *    See the License for the specific language governing permissions and\r
- *    limitations under the License.\r
- */\r
-\r
-package org.apache.poi.hssf.record;\r
-\r
-import org.apache.poi.ddf.EscherRecord;\r
-\r
-import java.util.Map;\r
-\r
-/**\r
- * @author Evgeniy Berlog\r
- * date: 30.05.12\r
- */\r
-public class HSSFRecordTestHelper {\r
-\r
-    public static Map<EscherRecord, Record> getShapeToObjForTest(EscherAggregate agg){\r
-        return agg.shapeToObj;\r
-    }\r
-\r
-}\r
index f207a0046d55d085a880f896b2688fd277625ae6..38992c0bdf21fd06b9a1033dce5b9a3c861c8090 100644 (file)
@@ -49,17 +49,12 @@ public final class TestDrawingRecord extends TestCase {
         out.write(cn.serialize());
 
         List<Record> rec = RecordFactory.createRecords(new ByteArrayInputStream(out.toByteArray()));
-        assertEquals(1, rec.size());
+        assertEquals(2, rec.size());
         assertTrue(rec.get(0) instanceof DrawingRecord);
+        assertTrue(rec.get(1) instanceof ContinueRecord);
 
-        //DrawingRecord.getData() should return concatenated data1 and data2
-        byte[] tmp = new byte[data1.length + data2.length];
-        System.arraycopy(data1, 0, tmp, 0, data1.length);
-        System.arraycopy(data2, 0, tmp, data1.length, data2.length);
-
-        DrawingRecord dg2 = (DrawingRecord)rec.get(0);
-        assertEquals(data1.length + data2.length, dg2.getData().length);
-        assertTrue(Arrays.equals(tmp, dg2.getData()));
+        assertTrue(Arrays.equals(data1, ((DrawingRecord)rec.get(0)).getData()));
+        assertTrue(Arrays.equals(data2, ((ContinueRecord)rec.get(1)).getData()));
 
     }
 
diff --git a/test-data/spreadsheet/DrawingAndComments.xls b/test-data/spreadsheet/DrawingAndComments.xls
new file mode 100755 (executable)
index 0000000..8be6c9e
Binary files /dev/null and b/test-data/spreadsheet/DrawingAndComments.xls differ
diff --git a/test-data/spreadsheet/DrawingContinue.xls b/test-data/spreadsheet/DrawingContinue.xls
new file mode 100755 (executable)
index 0000000..131c18c
Binary files /dev/null and b/test-data/spreadsheet/DrawingContinue.xls differ