]> source.dussan.org Git - poi.git/commitdiff
more tests and fixes, see patch from May 30 in Bugzilla 53010
authorYegor Kozlov <yegor@apache.org>
Thu, 31 May 2012 09:47:17 +0000 (09:47 +0000)
committerYegor Kozlov <yegor@apache.org>
Thu, 31 May 2012 09:47:17 +0000 (09:47 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1344621 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/ddf/EscherArrayProperty.java
src/java/org/apache/poi/hssf/record/DrawingRecord.java
src/java/org/apache/poi/hssf/record/EscherAggregate.java
src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java
src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java [new file with mode: 0644]

index 6faec52321170b8a56683289b1338cde443915bb..01e2f5c36504ad37246861e2bc23f9359a4cdc45 100644 (file)
@@ -62,6 +62,9 @@ public final class EscherArrayProperty extends EscherComplexProperty {
     }
 
     public int getNumberOfElementsInArray() {
+        if (emptyComplexPart){
+            return 0;
+        }
         return LittleEndian.getUShort(_complexData, 0);
     }
 
index 9ba18aee03c69294dbff785e22198fd7a9aad8d1..7b94e26c167e16844e5b7d20d7d95f589e8939ae 100644 (file)
@@ -64,6 +64,10 @@ public final class DrawingRecord extends StandardRecord {
         return recordData;
     }
 
+    public byte[] getRecordData(){
+        return recordData;
+    }
+
     public void setData(byte[] thedata) {
        if (thedata == null) {
                throw new IllegalArgumentException("data must not be null");
index 0ac0d04729c146b6993afaffac691cd51df06c19..e2ca3dd475d75d12927c27c719dcb6c35f3adbcd 100644 (file)
@@ -288,7 +288,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord {
        protected HSSFPatriarch patriarch;
 
        /** Maps shape container objects to their {@link TextObjectRecord} or {@link ObjRecord} */
-       private Map<EscherRecord, Record> shapeToObj = new HashMap<EscherRecord, Record>();
+       Map<EscherRecord, Record> shapeToObj = new HashMap<EscherRecord, Record>();
        private DrawingManager2 drawingManager;
        private short drawingGroupId;
 
@@ -371,7 +371,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord {
                                && sid( records, loc ) == DrawingRecord.sid
                                && isObjectRecord( records, loc + 1 ) )
                {
-                       dataSize += ( (DrawingRecord) records.get( loc ) ).getData().length;
+                       dataSize += ( (DrawingRecord) records.get( loc ) ).getRecordData().length;
                        loc += 2;
             while ( loc + 1 < records.size()
                     && sid( records, loc ) == ContinueRecord.sid
@@ -391,8 +391,8 @@ public final class EscherAggregate extends AbstractEscherHolderRecord {
                                && isObjectRecord( records, loc + 1 ) )
                {
                        DrawingRecord drawingRecord = (DrawingRecord) records.get( loc );
-                       System.arraycopy( drawingRecord.getData(), 0, buffer, offset, drawingRecord.getData().length );
-                       offset += drawingRecord.getData().length;
+                       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
index 43fe4b482ccab075939ed8e48231162e3c649e64..c5aa5855a9126d92cfd2d4e2e15e4eb39df9e6b8 100644 (file)
@@ -1,18 +1,29 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
 package org.apache.poi.hssf.model;\r
 \r
 import junit.framework.TestCase;\r
+import org.apache.poi.ddf.EscherClientDataRecord;\r
+import org.apache.poi.ddf.EscherContainerRecord;\r
 import org.apache.poi.ddf.EscherDggRecord;\r
+import org.apache.poi.ddf.EscherRecord;\r
+import org.apache.poi.ddf.EscherSpRecord;\r
 import org.apache.poi.hssf.HSSFTestDataSamples;\r
-import org.apache.poi.hssf.record.ContinueRecord;\r
-import org.apache.poi.hssf.record.DrawingRecord;\r
-import org.apache.poi.hssf.record.EOFRecord;\r
-import org.apache.poi.hssf.record.EscherAggregate;\r
-import org.apache.poi.hssf.record.ObjRecord;\r
-import org.apache.poi.hssf.record.Record;\r
-import org.apache.poi.hssf.record.RecordBase;\r
-import org.apache.poi.hssf.record.RecordFactory;\r
-import org.apache.poi.hssf.record.TextObjectRecord;\r
-import org.apache.poi.hssf.record.WindowTwoRecord;\r
+import org.apache.poi.hssf.record.*;\r
 import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;\r
 import org.apache.poi.hssf.usermodel.HSSFSheet;\r
 import org.apache.poi.hssf.usermodel.HSSFTestHelper;\r
@@ -20,13 +31,125 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 import org.apache.poi.util.HexRead;\r
 \r
 import java.io.ByteArrayInputStream;\r
+import java.util.ArrayList;\r
+import java.util.LinkedHashMap;\r
 import java.util.List;\r
+import java.util.Map;\r
 \r
 /**\r
  * @author Yegor Kozlov\r
  * @author Evgeniy Berlog\r
  */\r
 public class TestDrawingAggregate extends TestCase {\r
+    /**\r
+     * Serialize escher aggregate, read back and assert that the drawing data is preserved.\r
+     *\r
+     * @param agg the aggregate to test\r
+     * @return verified aggregate (serialized and read back)\r
+     */\r
+    public static EscherAggregate assertWriteAndReadBack(EscherAggregate agg) {\r
+        byte[] dgBytes = agg.serialize();\r
+\r
+\r
+        List<Record> dgRecords = RecordFactory.createRecords(new ByteArrayInputStream(dgBytes));\r
+\r
+        DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord());\r
+\r
+        // create a dummy sheet consisting of our test data\r
+        InternalSheet sheet = InternalSheet.createSheet();\r
+        List<RecordBase> records = sheet.getRecords();\r
+        records.clear();\r
+        records.addAll(dgRecords);\r
+        records.add(EOFRecord.instance);\r
+\r
+\r
+        sheet.aggregateDrawingRecords(drawingManager, false);\r
+        assertEquals("drawing was not fully aggregated", 2, records.size());\r
+        assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate);\r
+        assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord);\r
+        EscherAggregate agg2 = (EscherAggregate) records.get(0);\r
+\r
+        assertEquals(agg.getEscherRecords().size(), agg2.getEscherRecords().size());\r
+\r
+        // assert that both pre- and after- serialize aggregates have the same xml representation\r
+        for (int i = 0; i < agg.getEscherRecords().size(); i++) {\r
+            EscherRecord r1 = agg.getEscherRecords().get(i);\r
+            EscherRecord r2 = agg2.getEscherRecords().get(i);\r
+\r
+            assertEquals(r1.toXml(), r2.toXml());\r
+        }\r
+\r
+        return agg2;\r
+    }\r
+\r
+    /**\r
+     * assert that mapping of Obj records to escher shape containers is the same in both aggregates\r
+     */\r
+    public static void assertObjectMappingSame(EscherAggregate agg1, EscherAggregate agg2) {\r
+\r
+        // map EscherClientDataRecord and EscherTextboxRecord to their parents\r
+        Map<EscherRecord, EscherContainerRecord> map1 = new LinkedHashMap<EscherRecord, EscherContainerRecord>();\r
+        for (EscherRecord r : agg1.getEscherRecords()) mapShapeContainers(r, map1);\r
+\r
+        Map<EscherRecord, EscherContainerRecord> map2 = new LinkedHashMap<EscherRecord, EscherContainerRecord>();\r
+        for (EscherRecord r : agg2.getEscherRecords()) mapShapeContainers(r, map2);\r
+\r
+        assertEquals("aggregates have different number of shapes", map1.size(), map2.size());\r
+\r
+        // for each EscherClientDataRecord get parent SP_CONTAINER and corresponding ObjRecord\r
+        // verify that ObjRecord to\r
+        List<EscherRecord> l1 = new ArrayList<EscherRecord>(map1.keySet());\r
+        List<EscherRecord> l2 = new ArrayList<EscherRecord>(map2.keySet());\r
+        for (int i = 0; i < l1.size(); i++) {\r
+            EscherRecord e1 = l1.get(i);\r
+            EscherRecord e2 = l2.get(i);\r
+            ObjRecord obj1 = (ObjRecord) HSSFRecordTestHelper.getShapeToObjForTest(agg1).get(e1);\r
+            ObjRecord obj2 = (ObjRecord) HSSFRecordTestHelper.getShapeToObjForTest(agg2).get(e2);\r
+\r
+            CommonObjectDataSubRecord cmo1 = (CommonObjectDataSubRecord) obj1.getSubRecords().get(0);\r
+            CommonObjectDataSubRecord cmo2 = (CommonObjectDataSubRecord) obj2.getSubRecords().get(0);\r
+\r
+            assertEquals(cmo1.getObjectId(), cmo2.getObjectId());\r
+            assertEquals(obj1.toString(), obj2.toString());\r
+\r
+            // test that obj parents have the same shapeId, that is, that shape is the same\r
+            EscherContainerRecord p1 = map1.get(e1);\r
+            EscherContainerRecord p2 = map2.get(e2);\r
+            EscherSpRecord sp1 = (EscherSpRecord) p1.getChildById(EscherSpRecord.RECORD_ID);\r
+            EscherSpRecord sp2 = (EscherSpRecord) p2.getChildById(EscherSpRecord.RECORD_ID);\r
+            assertEquals(sp1.getShapeId(), sp2.getShapeId());\r
+\r
+            assertEquals("wrong shape2obj mapping", sp1.getShapeId() % 1024, cmo1.getObjectId());\r
+            assertEquals(p1.toXml(), p2.toXml());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * recursively map EscherClientDataRecords  to their parent shape containers:\r
+     * <p/>\r
+     * EscherClientDataRecord1 --> EscherContainerRecord1\r
+     * EscherClientDataRecord2 --> EscherContainerRecord2\r
+     * ...\r
+     * <p/>\r
+     * TODO: YK: this method can be avoided if we have EscherRecord.getParent()\r
+     */\r
+    private static void mapShapeContainers(EscherRecord parent, Map<EscherRecord, EscherContainerRecord> map) {\r
+        if (parent.isContainerRecord()) {\r
+            if (parent.getRecordId() == EscherContainerRecord.SP_CONTAINER) {\r
+                // iterate over shape's children and search for EscherClientDataRecord\r
+                for (EscherRecord r : parent.getChildRecords()) {\r
+                    if (r.getRecordId() == EscherClientDataRecord.RECORD_ID) {\r
+                        map.put(r, (EscherContainerRecord) parent);\r
+                    }\r
+                }\r
+            } else {\r
+                for (EscherRecord ch : parent.getChildRecords()) {\r
+                    mapShapeContainers(ch, map);\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
     /**\r
      * test reading drawing aggregate from a test file from Bugzilla 45129\r
      */\r
@@ -69,7 +192,7 @@ public class TestDrawingAggregate extends TestCase {
         // The subrange [19, 388] is expected to be replaced with a EscherAggregate object\r
         DrawingManager2 drawingManager = iworkbook.findDrawingGroup();\r
         int loc = isheet.aggregateDrawingRecords(drawingManager, false);\r
-        EscherAggregate ag = (EscherAggregate) records.get(loc);\r
+        EscherAggregate agg = (EscherAggregate) records.get(loc);\r
 \r
         assertEquals("wrong size of the aggregated sheet records stream", 25, records.size());\r
         assertTrue(\r
@@ -80,8 +203,9 @@ public class TestDrawingAggregate extends TestCase {
         assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(),\r
                 records.get(20) instanceof WindowTwoRecord);\r
 \r
-        // TODO figure out why serialization fails\r
-        // byte[] bytes = ag.serialize();\r
+        EscherAggregate agg2 = assertWriteAndReadBack(agg);\r
+\r
+        assertObjectMappingSame(agg, agg2);\r
     }\r
 \r
     public void testFileWithPictures() {\r
@@ -93,10 +217,6 @@ public class TestDrawingAggregate extends TestCase {
 \r
         List<RecordBase> records = isheet.getRecords();\r
 \r
-        for (RecordBase recordBase : records) {\r
-            System.out.println(recordBase.toString());\r
-        }\r
-\r
         // the sheet's drawing is not aggregated\r
         assertEquals("wrong size of sheet records stream", 315, records.size());\r
         // the last record before the drawing block\r
@@ -127,7 +247,7 @@ public class TestDrawingAggregate extends TestCase {
         // The subrange [19, 388] is expected to be replaced with a EscherAggregate object\r
         DrawingManager2 drawingManager = iworkbook.findDrawingGroup();\r
         int loc = isheet.aggregateDrawingRecords(drawingManager, false);\r
-        EscherAggregate ag = (EscherAggregate) records.get(loc);\r
+        EscherAggregate agg = (EscherAggregate) records.get(loc);\r
 \r
         assertEquals("wrong size of the aggregated sheet records stream", 38, records.size());\r
         assertTrue(\r
@@ -137,6 +257,10 @@ public class TestDrawingAggregate extends TestCase {
                 records.get(22) instanceof EscherAggregate);\r
         assertTrue("records.get(23) is expected to be Window2 but was " + records.get(23).getClass().getSimpleName(),\r
                 records.get(23) instanceof WindowTwoRecord);\r
+\r
+        EscherAggregate agg2 = assertWriteAndReadBack(agg);\r
+\r
+        assertObjectMappingSame(agg, agg2);\r
     }\r
 \r
     public void testUnhandledContinue() {\r
@@ -848,8 +972,10 @@ public class TestDrawingAggregate extends TestCase {
         assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord);\r
         EscherAggregate agg = (EscherAggregate) records.get(0);\r
 \r
-        // TODO figure out why serialization fails\r
-//        byte[] writtenBytes = agg.serialize();\r
+        // serialize, read back and assert that the drawing data is preserved\r
+        EscherAggregate agg2 = assertWriteAndReadBack(agg);\r
+\r
+        assertObjectMappingSame(agg, agg2);\r
     }\r
 \r
     public void testUnhandledContinue2() {\r
@@ -1793,10 +1919,15 @@ public class TestDrawingAggregate extends TestCase {
         records.addAll(dgRecords);\r
         records.add(EOFRecord.instance);\r
 \r
-\r
         sheet.aggregateDrawingRecords(drawingManager, false);\r
         assertEquals("drawing was not fully aggregated", 2, records.size());\r
         assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate);\r
         assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord);\r
+\r
+        EscherAggregate agg = (EscherAggregate) records.get(0);\r
+\r
+        EscherAggregate agg2 = assertWriteAndReadBack(agg);\r
+\r
+        assertObjectMappingSame(agg, agg2);\r
     }\r
 }\r
diff --git a/src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java b/src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java
new file mode 100644 (file)
index 0000000..4eed03d
--- /dev/null
@@ -0,0 +1,34 @@
+/*\r
+ * Licensed to the Apache Software Foundation (ASF) under one or more\r
+ *    contributor license agreements.  See the NOTICE file distributed with\r
+ *    this work for additional information regarding copyright ownership.\r
+ *    The ASF licenses this file to You under the Apache License, Version 2.0\r
+ *    (the "License"); you may not use this file except in compliance with\r
+ *    the License.  You may obtain a copy of the License at\r
+ *\r
+ *        http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ *    Unless required by applicable law or agreed to in writing, software\r
+ *    distributed under the License is distributed on an "AS IS" BASIS,\r
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *    See the License for the specific language governing permissions and\r
+ *    limitations under the License.\r
+ */\r
+\r
+package org.apache.poi.hssf.record;\r
+\r
+import org.apache.poi.ddf.EscherRecord;\r
+\r
+import java.util.Map;\r
+\r
+/**\r
+ * @author Evgeniy Berlog\r
+ * date: 30.05.12\r
+ */\r
+public class HSSFRecordTestHelper {\r
+\r
+    public static Map<EscherRecord, Record> getShapeToObjForTest(EscherAggregate agg){\r
+        return agg.shapeToObj;\r
+    }\r
+\r
+}\r