From: Evgeniy Berlog Date: Fri, 13 Jul 2012 15:45:01 +0000 (+0000) Subject: moved HSSFObjectData into drawing layer X-Git-Tag: 3.10-beta1~161^2~14 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=47dd4545797ec8e0e789445931d3897a98cf384c;p=poi.git moved HSSFObjectData into drawing layer git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1361278 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java b/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java index 5b2a463f4c..efb19331b0 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java @@ -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 subRecordIter = _record.getSubRecords().iterator(); + Iterator 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"); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index fbe3f56b68..221dfc475a 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -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()); } } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index 4bf927b2a0..5d2c9bb619 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -18,18 +18,14 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.*; -import org.apache.poi.hssf.model.TextboxShape; -import org.apache.poi.hssf.record.CommonObjectDataSubRecord; -import org.apache.poi.hssf.record.EscherAggregate; -import org.apache.poi.hssf.record.NoteRecord; -import org.apache.poi.hssf.record.ObjRecord; -import org.apache.poi.hssf.record.Record; -import org.apache.poi.hssf.record.TextObjectRecord; +import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.usermodel.drawing.HSSFShapeType; +import org.apache.poi.poifs.filesystem.DirectoryNode; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -43,7 +39,7 @@ public class HSSFShapeFactory { private static final ReflectionConstructorShapeCreator shapeCreator = new ReflectionConstructorShapeCreator(shapeTypeToClass); static { - for (HSSFShapeType type: HSSFShapeType.values()){ + for (HSSFShapeType type : HSSFShapeType.values()) { shapeTypeToClass.put(type.getType(), type); } } @@ -56,60 +52,65 @@ public class HSSFShapeFactory { this.shapeTypeToClass = shapeTypeToClass; } - public HSSFShape createNewShape(Short type, EscherContainerRecord spContainer, ObjRecord objRecord){ - if (!shapeTypeToClass.containsKey(type)){ + public HSSFShape createNewShape(Short type, EscherContainerRecord spContainer, ObjRecord objRecord) { + if (!shapeTypeToClass.containsKey(type)) { return new HSSFUnknownShape(spContainer, objRecord); } Class clazz = shapeTypeToClass.get(type).getShape(); - if (null == clazz){ + if (null == clazz) { //System.out.println("No class attached to shape type: "+type); return new HSSFUnknownShape(spContainer, objRecord); } - try{ + try { Constructor constructor = clazz.getConstructor(new Class[]{EscherContainerRecord.class, ObjRecord.class}); return (HSSFShape) constructor.newInstance(spContainer, objRecord); } catch (NoSuchMethodException e) { - throw new IllegalStateException(clazz.getName() +" doesn't have required for shapes constructor"); + throw new IllegalStateException(clazz.getName() + " doesn't have required for shapes constructor"); } catch (Exception e) { throw new IllegalStateException("Couldn't create new instance of " + clazz.getName()); } } } - public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out){ - if(container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){ + public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out, DirectoryNode root) { + if (container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { HSSFShapeGroup group = new HSSFShapeGroup(container, null /* shape containers don't have a associated Obj record*/); List children = container.getChildContainers(); // skip the first child record, it is group descriptor - for(int i = 0; i < children.size(); i++) { + for (int i = 0; i < children.size(); i++) { EscherContainerRecord spContainer = children.get(i); - if(i == 0){ - EscherSpgrRecord spgr = (EscherSpgrRecord)spContainer.getChildById(EscherSpgrRecord.RECORD_ID); + if (i == 0) { + EscherSpgrRecord spgr = (EscherSpgrRecord) spContainer.getChildById(EscherSpgrRecord.RECORD_ID); } else { - createShapeTree(spContainer, agg, group); + createShapeTree(spContainer, agg, group, root); } } out.addShape(group); - } else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER){ + } else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER) { Map shapeToObj = agg.getShapeToObjMapping(); EscherSpRecord spRecord = null; ObjRecord objRecord = null; TextObjectRecord txtRecord = null; - for(EscherRecord record : container.getChildRecords()) { - switch(record.getRecordId()) { + for (EscherRecord record : container.getChildRecords()) { + switch (record.getRecordId()) { case EscherSpRecord.RECORD_ID: - spRecord = (EscherSpRecord)record; + spRecord = (EscherSpRecord) record; break; case EscherClientDataRecord.RECORD_ID: - objRecord = (ObjRecord)shapeToObj.get(record); + objRecord = (ObjRecord) shapeToObj.get(record); break; case EscherTextboxRecord.RECORD_ID: - txtRecord = (TextObjectRecord)shapeToObj.get(record); + txtRecord = (TextObjectRecord) shapeToObj.get(record); break; } } + if (isEmbeddedObject(objRecord)){ + HSSFObjectData objectData = new HSSFObjectData(container, objRecord, root); + out.addShape(objectData); + return; + } CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0); HSSFShape shape = null; switch (cmo.getObjectType()) { @@ -128,8 +129,8 @@ public class HSSFShapeFactory { case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING: EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID); EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); - if (null != property){ - shape = new HSSFPolygon(container, objRecord); + if (null != property) { + shape = new HSSFPolygon(container, objRecord); } else { shape = new HSSFSimpleShape(container, objRecord); } @@ -143,9 +144,20 @@ public class HSSFShapeFactory { default: shape = new HSSFSimpleShape(container, objRecord); } - if (null != shape){ + if (null != shape) { out.addShape(shape); } } } + + private static boolean isEmbeddedObject(ObjRecord obj) { + Iterator subRecordIter = obj.getSubRecords().iterator(); + while (subRecordIter.hasNext()) { + SubRecord sub = subRecordIter.next(); + if (sub instanceof EmbeddedObjectRefSubRecord) { + return true; + } + } + return false; + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index e24ccc2d91..332289e109 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -1706,7 +1706,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss List objects = new ArrayList(); 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 records, List objects) + private void getAllEmbeddedObjects(HSSFSheet sheet, List 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 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; + } } diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index 7d5bfaee6d..dd8882764f 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -198,7 +198,7 @@ public class TestDrawingShapes extends TestCase { assertEquals(1, drawing.getChildren().size()); HSSFPicture picture = (HSSFPicture) drawing.getChildren().get(0); - assertEquals(picture.getPictureIndex(), 1); + assertEquals(picture.getPictureIndex(), 2); assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT); assertEquals(picture.getFillColor(), 0x5DC943); assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT); 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 index 0000000000..840643b951 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java @@ -0,0 +1,24 @@ +package org.apache.poi.hssf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.hssf.HSSFTestDataSamples; + +import java.io.IOException; +import java.util.List; + +/** + * @author Evgeniy Berlog + * @date 13.07.12 + */ +public class TestEmbeddedObjects extends TestCase{ + + public void testReadExistingObject() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + List list = wb.getAllEmbeddedObjects(); + assertEquals(list.size(), 1); + HSSFObjectData obj = list.get(0); + assertNotNull(obj.getObjectData()); + assertNotNull(obj.getDirectory()); + assertNotNull(obj.getOLE2ClassName()); + } +} diff --git a/test-data/spreadsheet/drawings.xls b/test-data/spreadsheet/drawings.xls index eeac150c3f..45b9a95887 100644 Binary files a/test-data/spreadsheet/drawings.xls and b/test-data/spreadsheet/drawings.xls differ