--- src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java (revision 1345088) +++ src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java (revision ) @@ -17,11 +17,7 @@ package org.apache.poi.hssf.model; import junit.framework.TestCase; -import org.apache.poi.ddf.EscherClientDataRecord; -import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherDggRecord; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate; @@ -30,147 +26,172 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.util.HexRead; -import java.io.ByteArrayInputStream; -import java.util.ArrayList; -import java.util.LinkedHashMap; +import java.io.*; +import java.util.Arrays; import java.util.List; -import java.util.Map; /** * @author Yegor Kozlov * @author Evgeniy Berlog */ public class TestDrawingAggregate extends TestCase { + private static byte[] toByteArray(List records){ + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for(RecordBase rb : records) { + Record r = (Record)rb; + try { + out.write(r.serialize()); + } catch (IOException e){ + throw new RuntimeException(e); + } + } + return out.toByteArray(); + } + /** - * Serialize escher aggregate, read back and assert that the drawing data is preserved. - * - * @param agg the aggregate to test - * @return verified aggregate (serialized and read back) + * test reading drawing aggregate from a test file from Bugzilla 45129 */ - public static EscherAggregate assertWriteAndReadBack(EscherAggregate agg) { - byte[] dgBytes = agg.serialize(); + public void test45129() { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("45129.xls"); + HSSFSheet sh = wb.getSheetAt(0); + InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); + InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); - List dgRecords = RecordFactory.createRecords(new ByteArrayInputStream(dgBytes)); + List records = isheet.getRecords(); - DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord()); + // the sheet's drawing is not aggregated + assertEquals("wrong size of sheet records stream", 394, records.size()); + // the last record before the drawing block + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); - // create a dummy sheet consisting of our test data - InternalSheet sheet = InternalSheet.createSheet(); - List records = sheet.getRecords(); - records.clear(); - records.addAll(dgRecords); - records.add(EOFRecord.instance); + // records to be aggregated + List dgRecords = records.subList(19, 389); + // collect drawing records into a byte buffer. + byte[] dgBytes = toByteArray(dgRecords); + for (RecordBase rb : dgRecords) { + Record r = (Record) rb; + short sid = r.getSid(); + // we expect that drawing block consists of either + // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord + assertTrue( + sid == DrawingRecord.sid || + sid == ContinueRecord.sid || + sid == ObjRecord.sid || + sid == TextObjectRecord.sid); + } - sheet.aggregateDrawingRecords(drawingManager, false); - assertEquals("drawing was not fully aggregated", 2, records.size()); - assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate); - assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord); - EscherAggregate agg2 = (EscherAggregate) records.get(0); + // the first record after the drawing block + assertTrue( + "records.get(389) is expected to be Window2", + records.get(389) instanceof WindowTwoRecord); - assertEquals(agg.getEscherRecords().size(), agg2.getEscherRecords().size()); + // aggregate drawing records. + // The subrange [19, 388] is expected to be replaced with a EscherAggregate object + DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); + int loc = isheet.aggregateDrawingRecords(drawingManager, false); + EscherAggregate agg = (EscherAggregate) records.get(loc); - // assert that both pre- and after- serialize aggregates have the same xml representation - for (int i = 0; i < agg.getEscherRecords().size(); i++) { - EscherRecord r1 = agg.getEscherRecords().get(i); - EscherRecord r2 = agg2.getEscherRecords().get(i); + assertEquals("wrong size of the aggregated sheet records stream", 25, records.size()); + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); + assertTrue("records.get(19) is expected to be EscherAggregate but was " + records.get(19).getClass().getSimpleName(), + records.get(19) instanceof EscherAggregate); + assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(), + records.get(20) instanceof WindowTwoRecord); - assertEquals(r1.toXml(), r2.toXml()); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - } + } - return agg2; - } - /** - * assert that mapping of Obj records to escher shape containers is the same in both aggregates + * Try to check file with such record sequence + * ... + * DrawingRecord + * ContinueRecord + * ObjRecord | TextObjRecord + * ... */ - public static void assertObjectMappingSame(EscherAggregate agg1, EscherAggregate agg2) { + public void testSerializeDrawingBigger8k() { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("DrawingContinue.xls"); + InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); + HSSFSheet sh = wb.getSheetAt(0); + InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); - // map EscherClientDataRecord and EscherTextboxRecord to their parents - Map map1 = new LinkedHashMap(); - for (EscherRecord r : agg1.getEscherRecords()) mapShapeContainers(r, map1); + List records = isheet.getRecords(); - Map map2 = new LinkedHashMap(); - for (EscherRecord r : agg2.getEscherRecords()) mapShapeContainers(r, map2); + // the sheet's drawing is not aggregated + assertEquals("wrong size of sheet records stream", 32, records.size()); + // the last record before the drawing block + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); - assertEquals("aggregates have different number of shapes", map1.size(), map2.size()); + // records to be aggregated + List dgRecords = records.subList(19, 26); + for (RecordBase rb : dgRecords) { + Record r = (Record) rb; + short sid = r.getSid(); + // we expect that drawing block consists of either + // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord + assertTrue( + sid == DrawingRecord.sid || + sid == ContinueRecord.sid || + sid == ObjRecord.sid || + sid == NoteRecord.sid || + sid == TextObjectRecord.sid); + } + // collect drawing records into a byte buffer. + byte[] dgBytes = toByteArray(dgRecords); - // for each EscherClientDataRecord get parent SP_CONTAINER and corresponding ObjRecord - // verify that ObjRecord to - List l1 = new ArrayList(map1.keySet()); - List l2 = new ArrayList(map2.keySet()); - for (int i = 0; i < l1.size(); i++) { - EscherRecord e1 = l1.get(i); - EscherRecord e2 = l2.get(i); - ObjRecord obj1 = (ObjRecord) HSSFRecordTestHelper.getShapeToObjForTest(agg1).get(e1); - ObjRecord obj2 = (ObjRecord) HSSFRecordTestHelper.getShapeToObjForTest(agg2).get(e2); + // the first record after the drawing block + assertTrue( + "records.get(26) is expected to be Window2", + records.get(26) instanceof WindowTwoRecord); - CommonObjectDataSubRecord cmo1 = (CommonObjectDataSubRecord) obj1.getSubRecords().get(0); - CommonObjectDataSubRecord cmo2 = (CommonObjectDataSubRecord) obj2.getSubRecords().get(0); + // aggregate drawing records. + // The subrange [19, 38] is expected to be replaced with a EscherAggregate object + DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); + int loc = isheet.aggregateDrawingRecords(drawingManager, false); + EscherAggregate agg = (EscherAggregate) records.get(loc); - assertEquals(cmo1.getObjectId(), cmo2.getObjectId()); - assertEquals(obj1.toString(), obj2.toString()); + assertEquals("wrong size of the aggregated sheet records stream", 26, records.size()); + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); + assertTrue("records.get(19) is expected to be EscherAggregate but was " + records.get(19).getClass().getSimpleName(), + records.get(19) instanceof EscherAggregate); + assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(), + records.get(20) instanceof WindowTwoRecord); - // test that obj parents have the same shapeId, that is, that shape is the same - EscherContainerRecord p1 = map1.get(e1); - EscherContainerRecord p2 = map2.get(e2); - EscherSpRecord sp1 = (EscherSpRecord) p1.getChildById(EscherSpRecord.RECORD_ID); - EscherSpRecord sp2 = (EscherSpRecord) p2.getChildById(EscherSpRecord.RECORD_ID); - assertEquals(sp1.getShapeId(), sp2.getShapeId()); - - assertEquals("wrong shape2obj mapping", sp1.getShapeId() % 1024, cmo1.getObjectId()); - assertEquals(p1.toXml(), p2.toXml()); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - } + } - } - /** - * recursively map EscherClientDataRecords to their parent shape containers: - *

- * EscherClientDataRecord1 --> EscherContainerRecord1 - * EscherClientDataRecord2 --> EscherContainerRecord2 - * ... - *

- * TODO: YK: this method can be avoided if we have EscherRecord.getParent() - */ - private static void mapShapeContainers(EscherRecord parent, Map map) { - if (parent.isContainerRecord()) { - if (parent.getRecordId() == EscherContainerRecord.SP_CONTAINER) { - // iterate over shape's children and search for EscherClientDataRecord - for (EscherRecord r : parent.getChildRecords()) { - if (r.getRecordId() == EscherClientDataRecord.RECORD_ID) { - map.put(r, (EscherContainerRecord) parent); - } - } - } else { - for (EscherRecord ch : parent.getChildRecords()) { - mapShapeContainers(ch, map); - } - } - } - } - /** - * test reading drawing aggregate from a test file from Bugzilla 45129 - */ - public void test45129() { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("45129.xls"); + public void testSerializeDrawingWithComments() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("DrawingAndComments.xls"); HSSFSheet sh = wb.getSheetAt(0); - InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); List records = isheet.getRecords(); // the sheet's drawing is not aggregated - assertEquals("wrong size of sheet records stream", 394, records.size()); + assertEquals("wrong size of sheet records stream", 46, records.size()); // the last record before the drawing block assertTrue( "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), records.get(18) instanceof RowRecordsAggregate); // records to be aggregated - List dgRecords = records.subList(19, 388); + List dgRecords = records.subList(19, 39); for (RecordBase rb : dgRecords) { Record r = (Record) rb; short sid = r.getSid(); @@ -180,21 +201,24 @@ sid == DrawingRecord.sid || sid == ContinueRecord.sid || sid == ObjRecord.sid || + sid == NoteRecord.sid || sid == TextObjectRecord.sid); } + // collect drawing records into a byte buffer. + byte[] dgBytes = toByteArray(dgRecords); // the first record after the drawing block assertTrue( - "records.get(389) is expected to be Window2", - records.get(389) instanceof WindowTwoRecord); + "records.get(39) is expected to be Window2", + records.get(39) instanceof WindowTwoRecord); // aggregate drawing records. - // The subrange [19, 388] is expected to be replaced with a EscherAggregate object + // The subrange [19, 38] is expected to be replaced with a EscherAggregate object DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); int loc = isheet.aggregateDrawingRecords(drawingManager, false); EscherAggregate agg = (EscherAggregate) records.get(loc); - assertEquals("wrong size of the aggregated sheet records stream", 25, records.size()); + assertEquals("wrong size of the aggregated sheet records stream", 27, records.size()); assertTrue( "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), records.get(18) instanceof RowRecordsAggregate); @@ -203,11 +227,12 @@ assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(), records.get(20) instanceof WindowTwoRecord); - EscherAggregate agg2 = assertWriteAndReadBack(agg); - - assertObjectMappingSame(agg, agg2); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); } + public void testFileWithPictures() { HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ContinueRecordProblem.xls"); HSSFSheet sh = wb.getSheetAt(0); @@ -225,7 +250,7 @@ records.get(21) instanceof RowRecordsAggregate); // records to be aggregated - List dgRecords = records.subList(22, 299); + List dgRecords = records.subList(22, 300); for (RecordBase rb : dgRecords) { Record r = (Record) rb; short sid = r.getSid(); @@ -237,6 +262,8 @@ sid == ObjRecord.sid || sid == TextObjectRecord.sid); } + // collect drawing records into a byte buffer. + byte[] dgBytes = toByteArray(dgRecords); // the first record after the drawing block assertTrue( @@ -244,7 +271,7 @@ records.get(300) instanceof WindowTwoRecord); // aggregate drawing records. - // The subrange [19, 388] is expected to be replaced with a EscherAggregate object + // The subrange [19, 299] is expected to be replaced with a EscherAggregate object DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); int loc = isheet.aggregateDrawingRecords(drawingManager, false); EscherAggregate agg = (EscherAggregate) records.get(loc); @@ -258,9 +285,9 @@ assertTrue("records.get(23) is expected to be Window2 but was " + records.get(23).getClass().getSimpleName(), records.get(23) instanceof WindowTwoRecord); - EscherAggregate agg2 = assertWriteAndReadBack(agg); - - assertObjectMappingSame(agg, agg2); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); } public void testUnhandledContinue() { @@ -972,10 +999,9 @@ assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord); EscherAggregate agg = (EscherAggregate) records.get(0); - // serialize, read back and assert that the drawing data is preserved - EscherAggregate agg2 = assertWriteAndReadBack(agg); - - assertObjectMappingSame(agg, agg2); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); } public void testUnhandledContinue2() { @@ -1926,8 +1952,8 @@ EscherAggregate agg = (EscherAggregate) records.get(0); - EscherAggregate agg2 = assertWriteAndReadBack(agg); - - assertObjectMappingSame(agg, agg2); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); } } --- src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java (revision 1345088) +++ src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java (revision ) @@ -341,8 +341,8 @@ return null; } if (_lastRecord instanceof DrawingRecord) { - ((DrawingRecord) _lastRecord).processContinueRecord(contRec.getData()); - return null; +// ((DrawingRecord) _lastRecord).appendContinueRecord(contRec.getData()); + return contRec; } if (_lastRecord instanceof UnknownRecord) { //Gracefully handle records that we don't know about, --- src/java/org/apache/poi/hssf/model/InternalSheet.java (revision 1345088) +++ src/java/org/apache/poi/hssf/model/InternalSheet.java (revision ) @@ -1508,31 +1508,10 @@ return loc; } List 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; } /** --- src/java/org/apache/poi/hssf/record/EscherAggregate.java (revision 1345088) +++ src/java/org/apache/poi/hssf/record/EscherAggregate.java (revision ) @@ -17,11 +17,9 @@ 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 @@ * combination of MSODRAWING -> OBJ -> MSODRAWING -> OBJ records * but the escher records are serialized _across_ the MSODRAWING * records. - *

+ *

* It gets even worse when you start looking at TXO records. - *

+ *

* 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. + *

+ * At first document contains 4 types of records which belong to drawing layer. + * There are can be such sequence of record: + *

+ * DrawingRecord + * ContinueRecord + * ... + * ContinueRecord + * ObjRecord | TextObjectRecord + * ..... + * ContinueRecord + * ... + * ContinueRecord + * ObjRecord | TextObjectRecord + * NoteRecord + * ... + * NoteRecord + *

+ * 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 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; + 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; + protected HSSFPatriarch patriarch; - /** Maps shape container objects to their {@link TextObjectRecord} or {@link ObjRecord} */ - Map shapeToObj = new HashMap(); + /** + * Maps shape container objects to their {@link TextObjectRecord} or {@link ObjRecord} + */ + private final Map shapeToObj = new HashMap(); - private DrawingManager2 drawingManager; - private short drawingGroupId; + 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(); + /** + * list of "tail" records that need to be serialized after all drawing group records + */ + private List tailRec = new ArrayList(); - public EscherAggregate( DrawingManager2 drawingManager ) - { + public EscherAggregate(DrawingManager2 drawingManager) { - this.drawingManager = drawingManager; - } + this.drawingManager = drawingManager; + } - /** + /** - * @return Returns the current sid. + * @return Returns the current sid. - */ + */ - public short getSid() - { + public short getSid() { - return sid; - } + return sid; + } - /** - * Calculates the string representation of this record. This is - * simply a dump of all the records. - */ + /** + * Calculates the string representation of this record. This is + * simply a dump of all the records. + */ - public String toString() - { + public String toString() { - String nl = System.getProperty( "line.separtor" ); + String nl = System.getProperty("line.separtor"); - StringBuffer result = new StringBuffer(); + StringBuffer result = new StringBuffer(); - result.append( '[' ).append( getRecordName() ).append( ']' + nl ); + result.append('[').append(getRecordName()).append(']' + nl); - for ( Iterator iterator = getEscherRecords().iterator(); iterator.hasNext(); ) - { + for (Iterator iterator = getEscherRecords().iterator(); iterator.hasNext(); ) { - EscherRecord escherRecord = (EscherRecord) iterator.next(); + EscherRecord escherRecord = (EscherRecord) iterator.next(); - result.append( escherRecord.toString() ); + result.append(escherRecord.toString()); - } + } - result.append( "[/" ).append( getRecordName() ).append( ']' + nl ); + result.append("[/").append(getRecordName()).append(']' + nl); - return result.toString(); - } - + return result.toString(); + } + - public String toXml(String tab){ + 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("\n"); return builder.toString(); } + 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. + /** + * Collapses the drawing records into an aggregate. + * read Drawing and Continue records into single byte array, create Escher tree from byte array, create map - */ + */ - public static EscherAggregate createAggregate( List records, int locFirstDrawingRecord, DrawingManager2 drawingManager ) - { + public static EscherAggregate createAggregate(List records, int locFirstDrawingRecord, DrawingManager2 drawingManager) { - // Keep track of any shape records created so we can match them back to the object id's. - // Textbox objects are also treated as shape objects. - final List shapeRecords = new ArrayList(); + // Keep track of any shape records created so we can match them back to the object id's. + // Textbox objects are also treated as shape objects. + final List shapeRecords = new ArrayList(); - EscherRecordFactory recordFactory = new DefaultEscherRecordFactory() - { - public EscherRecord createRecord( byte[] data, int offset ) - { + EscherRecordFactory recordFactory = new DefaultEscherRecordFactory() { + public EscherRecord createRecord(byte[] data, int offset) { - EscherRecord r = super.createRecord( data, offset ); + EscherRecord r = super.createRecord(data, offset); - if ( r.getRecordId() == EscherClientDataRecord.RECORD_ID || r.getRecordId() == EscherTextboxRecord.RECORD_ID ) - { + if (r.getRecordId() == EscherClientDataRecord.RECORD_ID || r.getRecordId() == EscherTextboxRecord.RECORD_ID) { - shapeRecords.add( r ); + shapeRecords.add(r); - } - return r; - } - }; + } + return r; + } + }; - // Calculate the size of the buffer + // Create one big buffer + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + - EscherAggregate agg = new EscherAggregate(drawingManager); - int loc = locFirstDrawingRecord; + EscherAggregate agg = new EscherAggregate(drawingManager); + int loc = locFirstDrawingRecord; - int dataSize = 0; - while ( loc + 1 < records.size() + 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; + && (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()); - } + } - - // 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; + } 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; + // 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 ); + while (pos < buffer.size()) { + EscherRecord r = recordFactory.createRecord(buffer.toByteArray(), pos); + int bytesRead = r.fillFields(buffer.toByteArray(), pos, recordFactory); - agg.addEscherRecord( r ); + agg.addEscherRecord(r); - pos += bytesRead; - } + pos += bytesRead; + } - // Associate the object records with the shapes + // Associate the object records with the shapes - loc = locFirstDrawingRecord; + loc = locFirstDrawingRecord + 1; - int shapeIndex = 0; + int shapeIndex = 0; - agg.shapeToObj = new HashMap(); - while ( loc + 1 < records.size() - && sid( records, loc ) == DrawingRecord.sid - && isObjectRecord( records, loc + 1 ) ) - { - Record objRecord = (Record) records.get( loc + 1 ); + 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 ); + 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; + 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++; + } - return agg; + 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. - * + /** + * 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 offset The offset into the start of the array. - * @param data The byte array to serialize to. + * @param data The byte array to serialize to. - * @return The number of bytes serialized. + * @return The number of bytes serialized. - */ + */ - public int serialize( int offset, byte[] data ) - { + public int serialize(int offset, byte[] data) { - convertUserModelToRecords(); + convertUserModelToRecords(); - // Determine buffer size - List records = getEscherRecords(); + // Determine buffer size + List records = getEscherRecords(); - int size = getEscherRecordSize( records ); + int size = getEscherRecordSize(records); - byte[] buffer = new byte[size]; + 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; + // 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(); ) - { + for (Iterator iterator = records.iterator(); iterator.hasNext(); ) { - EscherRecord e = (EscherRecord) iterator.next(); + EscherRecord e = (EscherRecord) iterator.next(); - pos += e.serialize( pos, buffer, new EscherSerializationListener() - { - public void beforeRecordSerialize( int offset, short recordId, EscherRecord record ) - { + 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 ) - { + 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 ) ); + spEndingOffsets.add(Integer.valueOf(offset)); - shapes.add( record ); + shapes.add(record); - } - } + } + } - } ); + }); - } - // todo: fix this + } + // todo: fix this - shapes.add( 0, null ); + shapes.add(0, null); - spEndingOffsets.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; + // 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 writtenEscherBytes = 0; + for (int i = 1; i < shapes.size(); i++) { - int endOffset = ( (Integer) spEndingOffsets.get( i ) ).intValue() - 1; + int endOffset = ((Integer) spEndingOffsets.get(i)).intValue() - 1; - int startOffset; + int startOffset; - if ( i == 1 ) + if (i == 1) - startOffset = 0; - else + startOffset = 0; + else - startOffset = ( (Integer) spEndingOffsets.get( i - 1 ) ).intValue(); + 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]; + byte[] drawingData = new byte[endOffset - startOffset + 1]; - System.arraycopy( buffer, startOffset, drawingData, 0, drawingData.length ); + System.arraycopy(buffer, startOffset, drawingData, 0, drawingData.length); - drawing.setData( drawingData ); - int temp = drawing.serialize( pos, data ); + 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); + } + } + + } + - pos += temp; + pos += temp; + writtenEscherBytes += drawingData.length; - // Write the matching OBJ record + // Write the matching OBJ record - Record obj = shapeToObj.get( shapes.get( i ) ); + Record obj = shapeToObj.get(shapes.get(i)); - temp = obj.serialize( pos, data ); + temp = obj.serialize(pos, data); - pos += temp; + pos += temp; - } + } - // write records that need to be serialized after all drawing group records + // write records that need to be serialized after all drawing group records - for ( int i = 0; i < tailRec.size(); i++ ) - { + for (int i = 0; i < tailRec.size(); i++) { - Record rec = (Record)tailRec.get(i); + Record rec = (Record) tailRec.get(i); - pos += rec.serialize( pos, data ); + pos += rec.serialize(pos, data); - } + } - int bytesWritten = pos - offset; + int bytesWritten = pos - offset; - if ( bytesWritten != getRecordSize() ) + if (bytesWritten != getRecordSize()) - throw new RecordFormatException( bytesWritten + " bytes written but getRecordSize() reports " + getRecordSize() ); + throw new RecordFormatException(bytesWritten + " bytes written but getRecordSize() reports " + getRecordSize()); - return bytesWritten; - } + return bytesWritten; + } - /** - * How many bytes do the raw escher records contain. + /** + * How many bytes do the raw escher records contain. + * - * @param records List of escher records + * @param records List of escher records - * @return the number of bytes + * @return the number of bytes - */ + */ - private int getEscherRecordSize( List records ) - { + private int getEscherRecordSize(List records) { - int size = 0; + int size = 0; - for ( Iterator iterator = records.iterator(); iterator.hasNext(); ) + for (Iterator iterator = records.iterator(); iterator.hasNext(); ) - size += ( (EscherRecord) iterator.next() ).getRecordSize(); + size += ((EscherRecord) iterator.next()).getRecordSize(); - return size; - } + return size; + } - public int getRecordSize() { - // TODO - convert this to RecordAggregate - convertUserModelToRecords(); + public int getRecordSize() { + // TODO - convert this to RecordAggregate + convertUserModelToRecords(); - List records = getEscherRecords(); + // 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 records = getEscherRecords(); - int rawEscherSize = getEscherRecordSize( records ); + int rawEscherSize = getEscherRecordSize(records); + byte[] buffer = new byte[rawEscherSize]; + final List spEndingOffsets = new ArrayList(); + 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; + } + continueRecordsHeadersSize += ((spEndingOffsets.get(i) - spEndingOffsets.get(i - 1)) / RecordInputStream.MAX_RECORD_DATA_SIZE)*4; + } + - int drawingRecordSize = rawEscherSize + ( shapeToObj.size() ) * 4; + int drawingRecordSize = rawEscherSize + (shapeToObj.size()) * 4; - int objRecordSize = 0; + int objRecordSize = 0; - for ( Iterator iterator = shapeToObj.values().iterator(); iterator.hasNext(); ) - { + for (Iterator iterator = shapeToObj.values().iterator(); iterator.hasNext(); ) { - Record r = (Record) iterator.next(); - objRecordSize += r.getRecordSize(); - } - int tailRecordSize = 0; + Record r = (Record) iterator.next(); + objRecordSize += r.getRecordSize(); + } + int tailRecordSize = 0; - for ( Iterator iterator = tailRec.iterator(); iterator.hasNext(); ) - { + for (Iterator iterator = tailRec.iterator(); iterator.hasNext(); ) { - Record r = (Record) iterator.next(); - tailRecordSize += r.getRecordSize(); - } + Record r = (Record) iterator.next(); + tailRecordSize += r.getRecordSize(); + } - return drawingRecordSize + objRecordSize + tailRecordSize; + return drawingRecordSize + objRecordSize + tailRecordSize +continueRecordsHeadersSize; - } + } - /** - * Associates an escher record to an OBJ record or a TXO record. - */ + /** + * Associates an escher record to an OBJ record or a TXO record. + */ - Object associateShapeToObjRecord( EscherRecord r, ObjRecord objRecord ) - { + Object associateShapeToObjRecord(EscherRecord r, ObjRecord objRecord) { - return shapeToObj.put( r, objRecord ); + return shapeToObj.put(r, objRecord); - } + } - public HSSFPatriarch getPatriarch() - { + public HSSFPatriarch getPatriarch() { - return patriarch; - } + return patriarch; + } - public void setPatriarch( HSSFPatriarch patriarch ) - { + public void setPatriarch(HSSFPatriarch patriarch) { - this.patriarch = patriarch; - } + this.patriarch = patriarch; + } - /** - * Converts the Records into UserModel + /** + * Converts the Records into UserModel - * objects on the bound HSSFPatriarch + * objects on the bound HSSFPatriarch - */ - public void convertRecordsToUserModel() { + */ + public void convertRecordsToUserModel() { - if(patriarch == null) { + if (patriarch == null) { - throw new IllegalStateException("Must call setPatriarch() first"); - } + 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(); + // 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) { + if (topContainer == null) { - return; - } - topContainer = topContainer.getChildContainers().get(0); + return; + } + topContainer = topContainer.getChildContainers().get(0); - List tcc = topContainer.getChildContainers(); + List tcc = topContainer.getChildContainers(); - if(tcc.size() == 0) { + 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!"); - } + 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 = + // 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); + (EscherContainerRecord) tcc.get(0); - EscherSpgrRecord spgr = null; + EscherSpgrRecord spgr = null; - for(Iterator it = patriachContainer.getChildIterator(); it.hasNext();) { + for (Iterator it = patriachContainer.getChildIterator(); it.hasNext(); ) { - EscherRecord r = it.next(); + EscherRecord r = it.next(); - if(r instanceof EscherSpgrRecord) { + if (r instanceof EscherSpgrRecord) { - spgr = (EscherSpgrRecord)r; + spgr = (EscherSpgrRecord) r; - break; - } - } + break; + } + } - if(spgr != null) { + if (spgr != null) { - patriarch.setCoordinates( - spgr.getRectX1(), spgr.getRectY1(), - spgr.getRectX2(), spgr.getRectY2() - ); - } + patriarch.setCoordinates( + spgr.getRectX1(), spgr.getRectY1(), + spgr.getRectX2(), spgr.getRectY2() + ); + } - convertRecordsToUserModelRecursive(tcc, patriarch, null); + 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.... + // 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]); + drawingManager.getDgg().setFileIdClusters(new EscherDggRecord.FileIdCluster[0]); - // TODO: Support converting our records - // back into shapes - // log.log(POILogger.WARN, "Not processing objects into Patriarch!"); - } + // 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 + private static void convertRecordsToUserModelRecursive(List tcc, HSSFShapeContainer container, HSSFShape parent) { + // Now process the containers for each group + // and objects - for(int i=1; i 0) - { + if (shapeChildren > 0) { - HSSFShapeGroup group = new HSSFShapeGroup( parent, new HSSFClientAnchor() ); + HSSFShapeGroup group = new HSSFShapeGroup(parent, new HSSFClientAnchor()); - addToParentOrContainer(group, container, parent); + addToParentOrContainer(group, container, parent); - EscherContainerRecord groupContainer = (EscherContainerRecord) shapeContainer.getChild( 0 ); + EscherContainerRecord groupContainer = (EscherContainerRecord) shapeContainer.getChild(0); - convertRecordsToUserModel( groupContainer, group ); + convertRecordsToUserModel(groupContainer, group); - + - if (shapeChildren>1){ + if (shapeChildren > 1) { - convertRecordsToUserModelRecursive(shapeContainer.getChildRecords(), container, group); - } + convertRecordsToUserModelRecursive(shapeContainer.getChildRecords(), container, group); + } - } else - { + } else { - log.log( POILogger.WARN, + log.log(POILogger.WARN, - "Found drawing group without children." ); + "Found drawing group without children."); - } + } - } else if (shapeContainer.getRecordId() == EscherContainerRecord.SP_CONTAINER) - { + } else if (shapeContainer.getRecordId() == EscherContainerRecord.SP_CONTAINER) { - EscherSpRecord spRecord = shapeContainer + EscherSpRecord spRecord = shapeContainer - .getChildById( EscherSpRecord.RECORD_ID ); + .getChildById(EscherSpRecord.RECORD_ID); - int type = spRecord.getShapeType(); + int type = spRecord.getShapeType(); - switch (type) - { + switch (type) { - case ST_TEXTBOX: + case ST_TEXTBOX: - HSSFTextbox box = new HSSFTextbox( parent, + HSSFTextbox box = new HSSFTextbox(parent, - new HSSFClientAnchor() ); + new HSSFClientAnchor()); - addToParentOrContainer(box, container, parent); + addToParentOrContainer(box, container, parent); - convertRecordsToUserModel( shapeContainer, box ); + convertRecordsToUserModel(shapeContainer, box); - break; - case ST_PICTUREFRAME: - // Duplicated from - // org.apache.poi.hslf.model.Picture.getPictureIndex() - EscherOptRecord opt = (EscherOptRecord) getEscherChild( + break; + case ST_PICTUREFRAME: + // Duplicated from + // org.apache.poi.hslf.model.Picture.getPictureIndex() + EscherOptRecord opt = (EscherOptRecord) getEscherChild( - shapeContainer, EscherOptRecord.RECORD_ID ); + shapeContainer, EscherOptRecord.RECORD_ID); - EscherSimpleProperty prop = (EscherSimpleProperty)opt.lookup( + EscherSimpleProperty prop = (EscherSimpleProperty) opt.lookup( - EscherProperties.BLIP__BLIPTODISPLAY ); + EscherProperties.BLIP__BLIPTODISPLAY); - if (prop == null) - { + if (prop == null) { - log.log( POILogger.WARN, + log.log(POILogger.WARN, - "Picture index for picture shape not found." ); + "Picture index for picture shape not found."); - } else - { + } else { - int pictureIndex = prop.getPropertyValue(); + int pictureIndex = prop.getPropertyValue(); - EscherClientAnchorRecord anchorRecord = (EscherClientAnchorRecord) getEscherChild( - shapeContainer, + EscherClientAnchorRecord anchorRecord = (EscherClientAnchorRecord) getEscherChild( + shapeContainer, - EscherClientAnchorRecord.RECORD_ID ); + EscherClientAnchorRecord.RECORD_ID); - EscherChildAnchorRecord childRecord = (EscherChildAnchorRecord) getEscherChild( - shapeContainer, + EscherChildAnchorRecord childRecord = (EscherChildAnchorRecord) getEscherChild( + shapeContainer, - EscherChildAnchorRecord.RECORD_ID ); + EscherChildAnchorRecord.RECORD_ID); - if (anchorRecord!=null && childRecord!=null){ + if (anchorRecord != null && childRecord != null) { - log.log( POILogger.WARN, "Picture with both CLIENT and CHILD anchor: "+ type ); + log.log(POILogger.WARN, "Picture with both CLIENT and CHILD anchor: " + type); - } - - HSSFAnchor anchor; + } + + HSSFAnchor anchor; - if (anchorRecord!=null){ + if (anchorRecord != null) { - anchor = toClientAnchor(anchorRecord); + anchor = toClientAnchor(anchorRecord); - }else{ + } else { - anchor = toChildAnchor(childRecord); - } + anchor = toChildAnchor(childRecord); + } - HSSFPicture picture = new HSSFPicture( parent, anchor ); + HSSFPicture picture = new HSSFPicture(parent, anchor); - picture.setPictureIndex( pictureIndex ); + picture.setPictureIndex(pictureIndex); - addToParentOrContainer(picture, container, parent); - } - break; - default: + addToParentOrContainer(picture, container, parent); + } + break; + default: - final HSSFSimpleShape shape = new HSSFSimpleShape( parent, + final HSSFSimpleShape shape = new HSSFSimpleShape(parent, - new HSSFClientAnchor() ); + new HSSFClientAnchor()); - addToParentOrContainer(shape, container, parent); + addToParentOrContainer(shape, container, parent); - convertRecordsToUserModel( shapeContainer, shape); + convertRecordsToUserModel(shapeContainer, shape); - + - log.log( POILogger.WARN, "Unhandled shape type: " + log.log(POILogger.WARN, "Unhandled shape type: " - + type ); + + type); - break; - } + break; + } - } else - { + } else { - log.log( POILogger.WARN, "Unexpected record id of shape group." ); + 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.setCol1(anchorRecord.getCol1()); - anchor.setCol2( anchorRecord.getCol2() ); + anchor.setCol2(anchorRecord.getCol2()); - anchor.setDx1( anchorRecord.getDx1() ); + anchor.setDx1(anchorRecord.getDx1()); - anchor.setDx2( anchorRecord.getDx2() ); + anchor.setDx2(anchorRecord.getDx2()); - anchor.setDy1( anchorRecord.getDy1() ); + anchor.setDy1(anchorRecord.getDy1()); - anchor.setDy2( anchorRecord.getDy2() ); + anchor.setDy2(anchorRecord.getDy2()); - anchor.setRow1( anchorRecord.getRow1() ); + anchor.setRow1(anchorRecord.getRow1()); - anchor.setRow2( anchorRecord.getRow2() ); + 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.setDx1(anchorRecord.getDx1()); - anchor.setDx2( anchorRecord.getDx2() ); + anchor.setDx2(anchorRecord.getDx2()); - anchor.setDy1( anchorRecord.getDy1() ); + anchor.setDy1(anchorRecord.getDy1()); - anchor.setDy2( anchorRecord.getDy2() ); + anchor.setDy2(anchorRecord.getDy2()); // anchor.setRow1( anchorRecord.getRow1() ); // anchor.setRow2( anchorRecord.getRow2() ); return anchor; } - private static void convertRecordsToUserModel(EscherContainerRecord shapeContainer, Object model) { + private static void convertRecordsToUserModel(EscherContainerRecord shapeContainer, Object model) { - for(Iterator it = shapeContainer.getChildIterator(); it.hasNext();) { + for (Iterator it = shapeContainer.getChildIterator(); it.hasNext(); ) { - EscherRecord r = it.next(); + EscherRecord r = it.next(); - if(r instanceof EscherSpgrRecord) { + if (r instanceof EscherSpgrRecord) { - // This may be overriden by a later EscherClientAnchorRecord + // This may be overriden by a later EscherClientAnchorRecord - EscherSpgrRecord spgr = (EscherSpgrRecord)r; + EscherSpgrRecord spgr = (EscherSpgrRecord) r; - if(model instanceof HSSFShapeGroup) { + if (model instanceof HSSFShapeGroup) { - HSSFShapeGroup g = (HSSFShapeGroup)model; + 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"); - } + 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) { + } else if (r instanceof EscherClientAnchorRecord) { - EscherClientAnchorRecord car = (EscherClientAnchorRecord)r; + EscherClientAnchorRecord car = (EscherClientAnchorRecord) r; - if(model instanceof HSSFShape) { + if (model instanceof HSSFShape) { - HSSFShape g = (HSSFShape)model; + 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"); - } + 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) { + } else if (r instanceof EscherTextboxRecord) { - EscherTextboxRecord tbr = (EscherTextboxRecord)r; + EscherTextboxRecord tbr = (EscherTextboxRecord) r; - // Also need to find the TextObjectRecord too - // TODO + // Also need to find the TextObjectRecord too + // TODO - } - else if(r instanceof EscherSpRecord) { + } else if (r instanceof EscherSpRecord) { - // Use flags if needed - final EscherSpRecord spr = (EscherSpRecord) r; + // Use flags if needed + final EscherSpRecord spr = (EscherSpRecord) r; - if (model instanceof HSSFShape){ + if (model instanceof HSSFShape) { - final HSSFShape s = (HSSFShape) model; - } + final HSSFShape s = (HSSFShape) model; + } - } - else if(r instanceof EscherOptRecord) { + } else if (r instanceof EscherOptRecord) { - // Use properties if needed + // Use properties if needed - } - else { + } else { - //System.err.println(r); - } - } - } + //System.err.println(r); + } + } + } - public void clear() - { + public void clear() { - clearEscherRecords(); - shapeToObj.clear(); + clearEscherRecords(); + shapeToObj.clear(); // lastShapeId = 1024; - } + } - protected String getRecordName() - { + protected String getRecordName() { - return "ESCHERAGGREGATE"; - } + return "ESCHERAGGREGATE"; + } - // =============== Private methods ======================== + // =============== Private methods ======================== - private static boolean isObjectRecord( List records, int loc ) - { + private static boolean isObjectRecord(List records, int loc) { - return sid( records, loc ) == ObjRecord.sid || sid( records, loc ) == TextObjectRecord.sid; + return sid(records, loc) == ObjRecord.sid || sid(records, loc) == TextObjectRecord.sid; - } + } - private void convertUserModelToRecords() - { - if ( patriarch != null ) - { + private void convertUserModelToRecords() { + if (patriarch != null) { - shapeToObj.clear(); - tailRec.clear(); - clearEscherRecords(); + shapeToObj.clear(); + tailRec.clear(); + clearEscherRecords(); - if ( patriarch.getChildren().size() != 0 ) - { + if (patriarch.getChildren().size() != 0) { - convertPatriarch( patriarch ); + convertPatriarch(patriarch); - EscherContainerRecord dgContainer = (EscherContainerRecord) getEscherRecord( 0 ); + EscherContainerRecord dgContainer = (EscherContainerRecord) getEscherRecord(0); - EscherContainerRecord spgrContainer = null; - Iterator iter = dgContainer.getChildIterator(); - while (iter.hasNext()) { - EscherRecord child = iter.next(); - if (child.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { - spgrContainer = (EscherContainerRecord) child; - } - } + EscherContainerRecord spgrContainer = null; + Iterator iter = dgContainer.getChildIterator(); + while (iter.hasNext()) { + EscherRecord child = iter.next(); + if (child.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { + spgrContainer = (EscherContainerRecord) child; + } + } - convertShapes( patriarch, spgrContainer, shapeToObj ); + convertShapes(patriarch, spgrContainer, shapeToObj); - patriarch = null; - } - } - } + patriarch = null; + } + } + } - private void convertShapes( HSSFShapeContainer parent, EscherContainerRecord escherParent, Map shapeToObj ) - { + private void convertShapes(HSSFShapeContainer parent, EscherContainerRecord escherParent, Map shapeToObj) { - if ( escherParent == null ) throw new IllegalArgumentException( "Parent record required" ); + if (escherParent == null) throw new IllegalArgumentException("Parent record required"); - List shapes = parent.getChildren(); + List shapes = parent.getChildren(); - for ( Iterator iterator = shapes.iterator(); iterator.hasNext(); ) - { + for (Iterator iterator = shapes.iterator(); iterator.hasNext(); ) { - HSSFShape shape = (HSSFShape) iterator.next(); + HSSFShape shape = (HSSFShape) iterator.next(); - if ( shape instanceof HSSFShapeGroup ) - { + if (shape instanceof HSSFShapeGroup) { - convertGroup( (HSSFShapeGroup) shape, escherParent, shapeToObj ); + convertGroup((HSSFShapeGroup) shape, escherParent, shapeToObj); - } - else - { + } else { - AbstractShape shapeModel = AbstractShape.createShape( - shape, + AbstractShape shapeModel = AbstractShape.createShape( + shape, - drawingManager.allocateShapeId(drawingGroupId) ); + drawingManager.allocateShapeId(drawingGroupId)); - shapeToObj.put( findClientData( shapeModel.getSpContainer() ), shapeModel.getObjRecord() ); + shapeToObj.put(findClientData(shapeModel.getSpContainer()), shapeModel.getObjRecord()); - if ( shapeModel instanceof TextboxShape ) - { + if (shapeModel instanceof TextboxShape) { - EscherRecord escherTextbox = ( (TextboxShape) shapeModel ).getEscherTextbox(); + EscherRecord escherTextbox = ((TextboxShape) shapeModel).getEscherTextbox(); - shapeToObj.put( escherTextbox, ( (TextboxShape) shapeModel ).getTextObjectRecord() ); + shapeToObj.put(escherTextbox, ((TextboxShape) shapeModel).getTextObjectRecord()); - // escherParent.addChildRecord(escherTextbox); + // escherParent.addChildRecord(escherTextbox); - if ( shapeModel instanceof CommentShape ){ + if (shapeModel instanceof CommentShape) { - CommentShape comment = (CommentShape)shapeModel; + CommentShape comment = (CommentShape) shapeModel; - tailRec.add(comment.getNoteRecord()); - } + tailRec.add(comment.getNoteRecord()); + } - } + } - escherParent.addChildRecord( shapeModel.getSpContainer() ); + escherParent.addChildRecord(shapeModel.getSpContainer()); - } - } + } + } // drawingManager.newCluster( (short)1 ); // drawingManager.newCluster( (short)2 ); - } + } - private void convertGroup( HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj ) - { + 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(); + 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.setRecordId(EscherContainerRecord.SPGR_CONTAINER); - spgrContainer.setOptions( (short) 0x000F ); + spgrContainer.setOptions((short) 0x000F); - spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); + spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); - spContainer.setOptions( (short) 0x000F ); + spContainer.setOptions((short) 0x000F); - spgr.setRecordId( EscherSpgrRecord.RECORD_ID ); + spgr.setRecordId(EscherSpgrRecord.RECORD_ID); - spgr.setOptions( (short) 0x0001 ); + spgr.setOptions((short) 0x0001); - spgr.setRectX1( shape.getX1() ); + spgr.setRectX1(shape.getX1()); - spgr.setRectY1( shape.getY1() ); + spgr.setRectY1(shape.getY1()); - spgr.setRectX2( shape.getX2() ); + spgr.setRectX2(shape.getX2()); - spgr.setRectY2( shape.getY2() ); + spgr.setRectY2(shape.getY2()); - sp.setRecordId( EscherSpRecord.RECORD_ID ); + sp.setRecordId(EscherSpRecord.RECORD_ID); - sp.setOptions( (short) 0x0002 ); + sp.setOptions((short) 0x0002); - int shapeId = drawingManager.allocateShapeId(drawingGroupId); + int shapeId = drawingManager.allocateShapeId(drawingGroupId); - sp.setShapeId( shapeId ); + sp.setShapeId(shapeId); - if (shape.getAnchor() instanceof HSSFClientAnchor) + if (shape.getAnchor() instanceof HSSFClientAnchor) - sp.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR ); + sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR); - else + else - sp.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD ); + sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD); - opt.setRecordId( EscherOptRecord.RECORD_ID ); + opt.setRecordId(EscherOptRecord.RECORD_ID); - opt.setOptions( (short) 0x0023 ); + opt.setOptions((short) 0x0023); - opt.addEscherProperty( new EscherBoolProperty( EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004 ) ); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004)); - opt.addEscherProperty( new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x00080000 ) ); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00080000)); - anchor = ConvertAnchor.createAnchor( shape.getAnchor() ); + 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 @@ // 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.setRecordId(EscherClientDataRecord.RECORD_ID); - clientData.setOptions( (short) 0x0000 ); + clientData.setOptions((short) 0x0000); - spgrContainer.addChildRecord( spContainer ); + spgrContainer.addChildRecord(spContainer); - spContainer.addChildRecord( spgr ); + spContainer.addChildRecord(spgr); - spContainer.addChildRecord( sp ); + spContainer.addChildRecord(sp); - spContainer.addChildRecord( opt ); + spContainer.addChildRecord(opt); - spContainer.addChildRecord( anchor ); + spContainer.addChildRecord(anchor); - spContainer.addChildRecord( clientData ); + spContainer.addChildRecord(clientData); - ObjRecord obj = new ObjRecord(); - CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord(); + ObjRecord obj = new ObjRecord(); + CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord(); - cmo.setObjectType( CommonObjectDataSubRecord.OBJECT_TYPE_GROUP ); + cmo.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_GROUP); - cmo.setObjectId( shapeId ); + cmo.setObjectId(shapeId); - cmo.setLocked( true ); + cmo.setLocked(true); - cmo.setPrintable( true ); + cmo.setPrintable(true); - cmo.setAutofill( true ); + cmo.setAutofill(true); - cmo.setAutoline( true ); + cmo.setAutoline(true); - GroupMarkerSubRecord gmo = new GroupMarkerSubRecord(); - EndSubRecord end = new EndSubRecord(); + GroupMarkerSubRecord gmo = new GroupMarkerSubRecord(); + EndSubRecord end = new EndSubRecord(); - obj.addSubRecord( cmo ); + obj.addSubRecord(cmo); - obj.addSubRecord( gmo ); + obj.addSubRecord(gmo); - obj.addSubRecord( end ); + obj.addSubRecord(end); - shapeToObj.put( clientData, obj ); + shapeToObj.put(clientData, obj); - escherParent.addChildRecord( spgrContainer ); + escherParent.addChildRecord(spgrContainer); - convertShapes( shape, spgrContainer, shapeToObj ); + convertShapes(shape, spgrContainer, shapeToObj); - } + } - private EscherRecord findClientData( EscherContainerRecord spContainer ) - { + private EscherRecord findClientData(EscherContainerRecord spContainer) { - for (Iterator iterator = spContainer.getChildIterator(); iterator.hasNext();) { + for (Iterator iterator = spContainer.getChildIterator(); iterator.hasNext(); ) { - EscherRecord r = iterator.next(); - if (r.getRecordId() == EscherClientDataRecord.RECORD_ID) { - return r; - } - } + EscherRecord r = iterator.next(); + if (r.getRecordId() == EscherClientDataRecord.RECORD_ID) { + return r; + } + } - throw new IllegalArgumentException( "Can not find client data record" ); + throw new IllegalArgumentException("Can not find client data record"); - } + } - private void convertPatriarch( HSSFPatriarch patriarch ) - { + 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(); + 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.setRecordId(EscherContainerRecord.DG_CONTAINER); - dgContainer.setOptions( (short) 0x000F ); + dgContainer.setOptions((short) 0x000F); - dg = drawingManager.createDgRecord(); - drawingGroupId = dg.getDrawingGroupId(); + 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.setRecordId(EscherContainerRecord.SPGR_CONTAINER); - spgrContainer.setOptions( (short) 0x000F ); + spgrContainer.setOptions((short) 0x000F); - spContainer1.setRecordId( EscherContainerRecord.SP_CONTAINER ); + spContainer1.setRecordId(EscherContainerRecord.SP_CONTAINER); - spContainer1.setOptions( (short) 0x000F ); + spContainer1.setOptions((short) 0x000F); - spgr.setRecordId( EscherSpgrRecord.RECORD_ID ); + spgr.setRecordId(EscherSpgrRecord.RECORD_ID); - spgr.setOptions( (short) 0x0001 ); // version + spgr.setOptions((short) 0x0001); // version - spgr.setRectX1( patriarch.getX1() ); + spgr.setRectX1(patriarch.getX1()); - spgr.setRectY1( patriarch.getY1() ); + spgr.setRectY1(patriarch.getY1()); - spgr.setRectX2( patriarch.getX2() ); + spgr.setRectX2(patriarch.getX2()); - spgr.setRectY2( patriarch.getY2() ); + spgr.setRectY2(patriarch.getY2()); - sp1.setRecordId( EscherSpRecord.RECORD_ID ); + sp1.setRecordId(EscherSpRecord.RECORD_ID); - sp1.setOptions( (short) 0x0002 ); + sp1.setOptions((short) 0x0002); - sp1.setShapeId( drawingManager.allocateShapeId(dg.getDrawingGroupId()) ); + sp1.setShapeId(drawingManager.allocateShapeId(dg.getDrawingGroupId())); - sp1.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_PATRIARCH ); + sp1.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_PATRIARCH); - dgContainer.addChildRecord( dg ); + dgContainer.addChildRecord(dg); - dgContainer.addChildRecord( spgrContainer ); + dgContainer.addChildRecord(spgrContainer); - spgrContainer.addChildRecord( spContainer1 ); + spgrContainer.addChildRecord(spContainer1); - spContainer1.addChildRecord( spgr ); + spContainer1.addChildRecord(spgr); - spContainer1.addChildRecord( sp1 ); + spContainer1.addChildRecord(sp1); - addEscherRecord( dgContainer ); + addEscherRecord(dgContainer); - } + } - private static short sid( List records, int loc ) - { + private static short sid(List records, int loc) { - return ( (Record) records.get( loc ) ).getSid(); + return ((Record) records.get(loc)).getSid(); - } + } - // Duplicated from org.apache.poi.hslf.model.Shape + // Duplicated from org.apache.poi.hslf.model.Shape - /** - * Helper method to return escher child by record ID - * - * @return escher record or null if not found. - */ - private static EscherRecord getEscherChild(EscherContainerRecord owner, + /** + * Helper method to return escher child by record ID + * + * @return escher record or null if not found. + */ + private static EscherRecord getEscherChild(EscherContainerRecord owner, - int recordId) - { + int recordId) { - for (Iterator iterator = owner.getChildRecords().iterator(); iterator + for (Iterator iterator = owner.getChildRecords().iterator(); iterator - .hasNext();) - { + .hasNext(); ) { - EscherRecord escherRecord = (EscherRecord) iterator.next(); - if (escherRecord.getRecordId() == recordId) - return escherRecord; - } - return null; - } + EscherRecord escherRecord = (EscherRecord) iterator.next(); + if (escherRecord.getRecordId() == recordId) + return escherRecord; + } + return null; + } } --- src/java/org/apache/poi/hssf/record/DrawingRecord.java (revision 1345088) +++ src/java/org/apache/poi/hssf/record/DrawingRecord.java (revision ) @@ -20,22 +20,21 @@ import org.apache.poi.util.LittleEndianOutput; /** * DrawingRecord (0x00EC)

- * */ 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 void serialize(LittleEndianOutput out) { out.write(recordData); } + protected int getDataSize() { return recordData.length; } @@ -55,12 +55,12 @@ } 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 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(); + DrawingRecord rec = new DrawingRecord(); - - rec.recordData = recordData.clone(); - if (contd != null) { - // TODO - this code probably never executes - rec.contd = contd.clone(); - } - - return rec; + rec.recordData = recordData.clone(); + if (contd != null) { + // TODO - this code probably never executes + rec.contd = contd.clone(); + } + + return rec; } } --- src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java (revision 1345088) +++ src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java (revision 1345088) @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.poi.hssf.record; - -import org.apache.poi.ddf.EscherRecord; - -import java.util.Map; - -/** - * @author Evgeniy Berlog - * date: 30.05.12 - */ -public class HSSFRecordTestHelper { - - public static Map getShapeToObjForTest(EscherAggregate agg){ - return agg.shapeToObj; - } - -}