]> source.dussan.org Git - poi.git/commitdiff
moved HSSFObjectData into drawing layer
authorEvgeniy Berlog <berlog@apache.org>
Fri, 13 Jul 2012 15:45:01 +0000 (15:45 +0000)
committerEvgeniy Berlog <berlog@apache.org>
Fri, 13 Jul 2012 15:45:01 +0000 (15:45 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1361278 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java
src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java
src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java
src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java
src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java [new file with mode: 0644]
test-data/spreadsheet/drawings.xls

index 5b2a463f4c30eeaee85b29bb64c8c6cdd5698bb6..efb19331b06437292f34dc589259cc071255719b 100644 (file)
@@ -21,6 +21,7 @@ package org.apache.poi.hssf.usermodel;
 import java.io.IOException;
 import java.util.Iterator;
 
+import org.apache.poi.ddf.EscherContainerRecord;
 import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord;
 import org.apache.poi.hssf.record.ObjRecord;
 import org.apache.poi.hssf.record.SubRecord;
@@ -31,29 +32,19 @@ import org.apache.poi.util.HexDump;
 /**
  * Represents binary object (i.e. OLE) data stored in the file.  Eg. A GIF, JPEG etc...
  *
+ * Right now, 13, july, 2012 can not be created from scratch
+ *
  * @author Daniel Noll
  */
-public final class HSSFObjectData {
-    /**
-     * Underlying object record ultimately containing a reference to the object.
-     */
-    private final ObjRecord _record;
-
+public final class HSSFObjectData extends HSSFShape{
     /**
      * Reference to the filesystem root, required for retrieving the object data.
      */
     private final DirectoryEntry _root;
 
-    /**
-     * Constructs object data by wrapping a lower level object record.
-     *
-     * @param record the low-level object record.
-     * @param root the root of the filesystem, required for retrieving the object data.
-     */
-    public HSSFObjectData(ObjRecord record, DirectoryEntry root)
-    {
-        _record = record;
-        _root = root;
+    public HSSFObjectData(EscherContainerRecord spContainer, ObjRecord objRecord, DirectoryEntry _root) {
+        super(spContainer, objRecord);
+        this._root = _root;
     }
 
     /**
@@ -110,7 +101,7 @@ public final class HSSFObjectData {
      *  Exception if there wasn't one
      */
     protected EmbeddedObjectRefSubRecord findObjectRecord() {
-        Iterator<SubRecord> subRecordIter = _record.getSubRecords().iterator();
+        Iterator<SubRecord> subRecordIter = getObjRecord().getSubRecords().iterator();
 
         while (subRecordIter.hasNext()) {
             Object subRecord = subRecordIter.next();
@@ -121,4 +112,24 @@ public final class HSSFObjectData {
 
         throw new IllegalStateException("Object data does not contain a reference to an embedded object OLE2 directory");
     }
+
+    @Override
+    protected EscherContainerRecord createSpContainer() {
+        throw new IllegalStateException("HSSFObjectData cannot be created from scratch");
+    }
+
+    @Override
+    protected ObjRecord createObjRecord() {
+        throw new IllegalStateException("HSSFObjectData cannot be created from scratch");
+    }
+
+    @Override
+    protected void afterRemove(HSSFPatriarch patriarch) {
+        throw new IllegalStateException("HSSFObjectData cannot be created from scratch");
+    }
+
+    @Override
+    void afterInsert(HSSFPatriarch patriarch) {
+        throw new IllegalStateException("HSSFObjectData cannot be created from scratch");
+    }
 }
index fbe3f56b681897bbce1bfe18423818025cfec55b..221dfc475a6d5bba3c7bc02e4cbde6401c0c2680 100644 (file)
@@ -387,7 +387,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
             if (i == 0){
                 continue;
             } else {
-                HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this);
+                HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this, _sheet.getWorkbook().getRootDirectory());
             }
         }
     }
index 4bf927b2a0ff40ae242f30193f1f85bacc9bfb1d..5d2c9bb61962e013ff9bbe23103cbb2e16f4bf6c 100644 (file)
 package org.apache.poi.hssf.usermodel;\r
 \r
 import org.apache.poi.ddf.*;\r
-import org.apache.poi.hssf.model.TextboxShape;\r
-import org.apache.poi.hssf.record.CommonObjectDataSubRecord;\r
-import org.apache.poi.hssf.record.EscherAggregate;\r
-import org.apache.poi.hssf.record.NoteRecord;\r
-import org.apache.poi.hssf.record.ObjRecord;\r
-import org.apache.poi.hssf.record.Record;\r
-import org.apache.poi.hssf.record.TextObjectRecord;\r
+import org.apache.poi.hssf.record.*;\r
 import org.apache.poi.hssf.usermodel.drawing.HSSFShapeType;\r
+import org.apache.poi.poifs.filesystem.DirectoryNode;\r
 \r
 import java.lang.reflect.Constructor;\r
 import java.lang.reflect.InvocationTargetException;\r
 import java.util.HashMap;\r
+import java.util.Iterator;\r
 import java.util.List;\r
 import java.util.Map;\r
 \r
@@ -43,7 +39,7 @@ public class HSSFShapeFactory {
     private static final ReflectionConstructorShapeCreator shapeCreator = new ReflectionConstructorShapeCreator(shapeTypeToClass);\r
 \r
     static {\r
-        for (HSSFShapeType type: HSSFShapeType.values()){\r
+        for (HSSFShapeType type : HSSFShapeType.values()) {\r
             shapeTypeToClass.put(type.getType(), type);\r
         }\r
     }\r
@@ -56,60 +52,65 @@ public class HSSFShapeFactory {
             this.shapeTypeToClass = shapeTypeToClass;\r
         }\r
 \r
-        public HSSFShape createNewShape(Short type, EscherContainerRecord spContainer, ObjRecord objRecord){\r
-            if (!shapeTypeToClass.containsKey(type)){\r
+        public HSSFShape createNewShape(Short type, EscherContainerRecord spContainer, ObjRecord objRecord) {\r
+            if (!shapeTypeToClass.containsKey(type)) {\r
                 return new HSSFUnknownShape(spContainer, objRecord);\r
             }\r
             Class clazz = shapeTypeToClass.get(type).getShape();\r
-            if (null == clazz){\r
+            if (null == clazz) {\r
                 //System.out.println("No class attached to shape type: "+type);\r
                 return new HSSFUnknownShape(spContainer, objRecord);\r
             }\r
-            try{\r
+            try {\r
                 Constructor constructor = clazz.getConstructor(new Class[]{EscherContainerRecord.class, ObjRecord.class});\r
                 return (HSSFShape) constructor.newInstance(spContainer, objRecord);\r
             } catch (NoSuchMethodException e) {\r
-                throw new IllegalStateException(clazz.getName() +" doesn't have required for shapes constructor");\r
+                throw new IllegalStateException(clazz.getName() + " doesn't have required for shapes constructor");\r
             } catch (Exception e) {\r
                 throw new IllegalStateException("Couldn't create new instance of " + clazz.getName());\r
             }\r
         }\r
     }\r
 \r
-    public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out){\r
-        if(container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){\r
+    public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out, DirectoryNode root) {\r
+        if (container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) {\r
             HSSFShapeGroup group = new HSSFShapeGroup(container,\r
                     null /* shape containers don't have a associated Obj record*/);\r
             List<EscherContainerRecord> children = container.getChildContainers();\r
             // skip the first child record, it is group descriptor\r
-            for(int i = 0; i < children.size(); i++) {\r
+            for (int i = 0; i < children.size(); i++) {\r
                 EscherContainerRecord spContainer = children.get(i);\r
-                if(i == 0){\r
-                    EscherSpgrRecord spgr = (EscherSpgrRecord)spContainer.getChildById(EscherSpgrRecord.RECORD_ID);\r
+                if (i == 0) {\r
+                    EscherSpgrRecord spgr = (EscherSpgrRecord) spContainer.getChildById(EscherSpgrRecord.RECORD_ID);\r
                 } else {\r
-                    createShapeTree(spContainer, agg, group);\r
+                    createShapeTree(spContainer, agg, group, root);\r
                 }\r
             }\r
             out.addShape(group);\r
-        } else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER){\r
+        } else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER) {\r
             Map<EscherRecord, Record> shapeToObj = agg.getShapeToObjMapping();\r
             EscherSpRecord spRecord = null;\r
             ObjRecord objRecord = null;\r
             TextObjectRecord txtRecord = null;\r
 \r
-            for(EscherRecord record : container.getChildRecords()) {\r
-                switch(record.getRecordId()) {\r
+            for (EscherRecord record : container.getChildRecords()) {\r
+                switch (record.getRecordId()) {\r
                     case EscherSpRecord.RECORD_ID:\r
-                        spRecord = (EscherSpRecord)record;\r
+                        spRecord = (EscherSpRecord) record;\r
                         break;\r
                     case EscherClientDataRecord.RECORD_ID:\r
-                        objRecord = (ObjRecord)shapeToObj.get(record);\r
+                        objRecord = (ObjRecord) shapeToObj.get(record);\r
                         break;\r
                     case EscherTextboxRecord.RECORD_ID:\r
-                        txtRecord = (TextObjectRecord)shapeToObj.get(record);\r
+                        txtRecord = (TextObjectRecord) shapeToObj.get(record);\r
                         break;\r
                 }\r
             }\r
+            if (isEmbeddedObject(objRecord)){\r
+                HSSFObjectData objectData = new HSSFObjectData(container, objRecord, root);\r
+                out.addShape(objectData);\r
+                return;\r
+            }\r
             CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0);\r
             HSSFShape shape = null;\r
             switch (cmo.getObjectType()) {\r
@@ -128,8 +129,8 @@ public class HSSFShapeFactory {
                 case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING:\r
                     EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID);\r
                     EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES);\r
-                    if (null != property){\r
-                        shape = new HSSFPolygon(container, objRecord);    \r
+                    if (null != property) {\r
+                        shape = new HSSFPolygon(container, objRecord);\r
                     } else {\r
                         shape = new HSSFSimpleShape(container, objRecord);\r
                     }\r
@@ -143,9 +144,20 @@ public class HSSFShapeFactory {
                 default:\r
                     shape = new HSSFSimpleShape(container, objRecord);\r
             }\r
-            if (null != shape){\r
+            if (null != shape) {\r
                 out.addShape(shape);\r
             }\r
         }\r
     }\r
+\r
+    private static boolean isEmbeddedObject(ObjRecord obj) {\r
+        Iterator<SubRecord> subRecordIter = obj.getSubRecords().iterator();\r
+        while (subRecordIter.hasNext()) {\r
+            SubRecord sub = subRecordIter.next();\r
+            if (sub instanceof EmbeddedObjectRefSubRecord) {\r
+                return true;\r
+            }\r
+        }\r
+        return false;\r
+    }\r
 }\r
index e24ccc2d91f267e89149b8118788cc5a07b15e57..332289e109685b18960df624e24c547ffbdc50c6 100644 (file)
@@ -1706,7 +1706,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
         List<HSSFObjectData> objects = new ArrayList<HSSFObjectData>();
         for (int i = 0; i < getNumberOfSheets(); i++)
         {
-            getAllEmbeddedObjects(getSheetAt(i).getSheet().getRecords(), objects);
+            getAllEmbeddedObjects(getSheetAt(i), objects);
         }
         return objects;
     }
@@ -1714,27 +1714,20 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
     /**
      * Gets all embedded OLE2 objects from the Workbook.
      *
-     * @param records the list of records to search.
+     * @param sheet embedded object attached to
      * @param objects the list of embedded objects to populate.
      */
-    private void getAllEmbeddedObjects(List<RecordBase> records, List<HSSFObjectData> objects)
+    private void getAllEmbeddedObjects(HSSFSheet sheet, List<HSSFObjectData> objects)
     {
-       for (RecordBase obj : records) {
-          if (obj instanceof ObjRecord)
-          {
-             // TODO: More convenient way of determining if there is stored binary.
-             // TODO: Link to the data stored in the other stream.
-             Iterator<SubRecord> subRecordIter = ((ObjRecord) obj).getSubRecords().iterator();
-             while (subRecordIter.hasNext())
-             {
-                SubRecord sub = subRecordIter.next();
-                if (sub instanceof EmbeddedObjectRefSubRecord)
-                {
-                   objects.add(new HSSFObjectData((ObjRecord) obj, directory));
-                }
-             }
-          }
-       }
+        HSSFPatriarch patriarch = sheet.getDrawingPatriarch();
+        if (null == patriarch){
+            return;
+        }
+        for (HSSFShape shape: patriarch.getChildren()){
+            if (shape instanceof HSSFObjectData){
+                objects.add((HSSFObjectData) shape);
+            }
+        }
     }
 
     public HSSFCreationHelper getCreationHelper() {
@@ -1808,4 +1801,8 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
     public boolean changeExternalReference(String oldUrl, String newUrl) {
        return workbook.changeExternalReference(oldUrl, newUrl);
     }
+
+    public DirectoryNode getRootDirectory(){
+        return directory;
+    }
 }
index 7d5bfaee6d1bc2da8e7f0639288027685dbcc32d..dd8882764f345954426e0243c4cd7f803115bfe5 100644 (file)
@@ -198,7 +198,7 @@ public class TestDrawingShapes extends TestCase {
         assertEquals(1, drawing.getChildren().size());\r
         HSSFPicture picture = (HSSFPicture) drawing.getChildren().get(0);\r
 \r
-        assertEquals(picture.getPictureIndex(), 1);\r
+        assertEquals(picture.getPictureIndex(), 2);\r
         assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT);\r
         assertEquals(picture.getFillColor(), 0x5DC943);\r
         assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT);\r
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java b/src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java
new file mode 100644 (file)
index 0000000..840643b
--- /dev/null
@@ -0,0 +1,24 @@
+package org.apache.poi.hssf.usermodel;\r
+\r
+import junit.framework.TestCase;\r
+import org.apache.poi.hssf.HSSFTestDataSamples;\r
+\r
+import java.io.IOException;\r
+import java.util.List;\r
+\r
+/**\r
+ * @author Evgeniy Berlog\r
+ * @date 13.07.12\r
+ */\r
+public class TestEmbeddedObjects extends TestCase{\r
+    \r
+    public void testReadExistingObject() throws IOException {\r
+        HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");\r
+        List<HSSFObjectData> list = wb.getAllEmbeddedObjects();\r
+        assertEquals(list.size(), 1);\r
+        HSSFObjectData obj = list.get(0);\r
+        assertNotNull(obj.getObjectData());\r
+        assertNotNull(obj.getDirectory());\r
+        assertNotNull(obj.getOLE2ClassName());\r
+    }\r
+}\r
index eeac150c3f4bf3c2329e3cecf5c56b706220d337..45b9a958870d9362f8ade14e7b93e6b5d7159207 100644 (file)
Binary files a/test-data/spreadsheet/drawings.xls and b/test-data/spreadsheet/drawings.xls differ