git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1361278 13f79535-47bb-0310-9956-ffa450edef68tags/3.10-beta1
@@ -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"); | |||
} | |||
} |
@@ -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()); | |||
} | |||
} | |||
} |
@@ -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<EscherContainerRecord> 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<EscherRecord, Record> 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<SubRecord> subRecordIter = obj.getSubRecords().iterator(); | |||
while (subRecordIter.hasNext()) { | |||
SubRecord sub = subRecordIter.next(); | |||
if (sub instanceof EmbeddedObjectRefSubRecord) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); |
@@ -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<HSSFObjectData> list = wb.getAllEmbeddedObjects(); | |||
assertEquals(list.size(), 1); | |||
HSSFObjectData obj = list.get(0); | |||
assertNotNull(obj.getObjectData()); | |||
assertNotNull(obj.getDirectory()); | |||
assertNotNull(obj.getOLE2ClassName()); | |||
} | |||
} |