moved HSSFObjectData into drawing layer

git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1361278 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Evgeniy Berlog 2012-07-13 15:45:01 +00:00
parent 73b0c8390c
commit 57f0fe06b9
7 changed files with 110 additions and 66 deletions

View File

@ -21,6 +21,7 @@ package org.apache.poi.hssf.usermodel;
import java.io.IOException; import java.io.IOException;
import java.util.Iterator; import java.util.Iterator;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord; import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord;
import org.apache.poi.hssf.record.ObjRecord; import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.SubRecord; 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... * 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 * @author Daniel Noll
*/ */
public final class HSSFObjectData { public final class HSSFObjectData extends HSSFShape{
/**
* Underlying object record ultimately containing a reference to the object.
*/
private final ObjRecord _record;
/** /**
* Reference to the filesystem root, required for retrieving the object data. * Reference to the filesystem root, required for retrieving the object data.
*/ */
private final DirectoryEntry _root; private final DirectoryEntry _root;
/** public HSSFObjectData(EscherContainerRecord spContainer, ObjRecord objRecord, DirectoryEntry _root) {
* Constructs object data by wrapping a lower level object record. super(spContainer, objRecord);
* this._root = _root;
* @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;
} }
/** /**
@ -110,7 +101,7 @@ public final class HSSFObjectData {
* Exception if there wasn't one * Exception if there wasn't one
*/ */
protected EmbeddedObjectRefSubRecord findObjectRecord() { protected EmbeddedObjectRefSubRecord findObjectRecord() {
Iterator<SubRecord> subRecordIter = _record.getSubRecords().iterator(); Iterator<SubRecord> subRecordIter = getObjRecord().getSubRecords().iterator();
while (subRecordIter.hasNext()) { while (subRecordIter.hasNext()) {
Object subRecord = subRecordIter.next(); 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"); 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");
}
} }

View File

@ -387,7 +387,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
if (i == 0){ if (i == 0){
continue; continue;
} else { } else {
HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this); HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this, _sheet.getWorkbook().getRootDirectory());
} }
} }
} }

View File

@ -18,18 +18,14 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*; import org.apache.poi.ddf.*;
import org.apache.poi.hssf.model.TextboxShape; import org.apache.poi.hssf.record.*;
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.usermodel.drawing.HSSFShapeType; import org.apache.poi.hssf.usermodel.drawing.HSSFShapeType;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -43,7 +39,7 @@ public class HSSFShapeFactory {
private static final ReflectionConstructorShapeCreator shapeCreator = new ReflectionConstructorShapeCreator(shapeTypeToClass); private static final ReflectionConstructorShapeCreator shapeCreator = new ReflectionConstructorShapeCreator(shapeTypeToClass);
static { static {
for (HSSFShapeType type: HSSFShapeType.values()){ for (HSSFShapeType type : HSSFShapeType.values()) {
shapeTypeToClass.put(type.getType(), type); shapeTypeToClass.put(type.getType(), type);
} }
} }
@ -56,60 +52,65 @@ public class HSSFShapeFactory {
this.shapeTypeToClass = shapeTypeToClass; this.shapeTypeToClass = shapeTypeToClass;
} }
public HSSFShape createNewShape(Short type, EscherContainerRecord spContainer, ObjRecord objRecord){ public HSSFShape createNewShape(Short type, EscherContainerRecord spContainer, ObjRecord objRecord) {
if (!shapeTypeToClass.containsKey(type)){ if (!shapeTypeToClass.containsKey(type)) {
return new HSSFUnknownShape(spContainer, objRecord); return new HSSFUnknownShape(spContainer, objRecord);
} }
Class clazz = shapeTypeToClass.get(type).getShape(); Class clazz = shapeTypeToClass.get(type).getShape();
if (null == clazz){ if (null == clazz) {
//System.out.println("No class attached to shape type: "+type); //System.out.println("No class attached to shape type: "+type);
return new HSSFUnknownShape(spContainer, objRecord); return new HSSFUnknownShape(spContainer, objRecord);
} }
try{ try {
Constructor constructor = clazz.getConstructor(new Class[]{EscherContainerRecord.class, ObjRecord.class}); Constructor constructor = clazz.getConstructor(new Class[]{EscherContainerRecord.class, ObjRecord.class});
return (HSSFShape) constructor.newInstance(spContainer, objRecord); return (HSSFShape) constructor.newInstance(spContainer, objRecord);
} catch (NoSuchMethodException e) { } 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) { } catch (Exception e) {
throw new IllegalStateException("Couldn't create new instance of " + clazz.getName()); throw new IllegalStateException("Couldn't create new instance of " + clazz.getName());
} }
} }
} }
public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out){ public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out, DirectoryNode root) {
if(container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){ if (container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) {
HSSFShapeGroup group = new HSSFShapeGroup(container, HSSFShapeGroup group = new HSSFShapeGroup(container,
null /* shape containers don't have a associated Obj record*/); null /* shape containers don't have a associated Obj record*/);
List<EscherContainerRecord> children = container.getChildContainers(); List<EscherContainerRecord> children = container.getChildContainers();
// skip the first child record, it is group descriptor // 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); EscherContainerRecord spContainer = children.get(i);
if(i == 0){ if (i == 0) {
EscherSpgrRecord spgr = (EscherSpgrRecord)spContainer.getChildById(EscherSpgrRecord.RECORD_ID); EscherSpgrRecord spgr = (EscherSpgrRecord) spContainer.getChildById(EscherSpgrRecord.RECORD_ID);
} else { } else {
createShapeTree(spContainer, agg, group); createShapeTree(spContainer, agg, group, root);
} }
} }
out.addShape(group); out.addShape(group);
} else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER){ } else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER) {
Map<EscherRecord, Record> shapeToObj = agg.getShapeToObjMapping(); Map<EscherRecord, Record> shapeToObj = agg.getShapeToObjMapping();
EscherSpRecord spRecord = null; EscherSpRecord spRecord = null;
ObjRecord objRecord = null; ObjRecord objRecord = null;
TextObjectRecord txtRecord = null; TextObjectRecord txtRecord = null;
for(EscherRecord record : container.getChildRecords()) { for (EscherRecord record : container.getChildRecords()) {
switch(record.getRecordId()) { switch (record.getRecordId()) {
case EscherSpRecord.RECORD_ID: case EscherSpRecord.RECORD_ID:
spRecord = (EscherSpRecord)record; spRecord = (EscherSpRecord) record;
break; break;
case EscherClientDataRecord.RECORD_ID: case EscherClientDataRecord.RECORD_ID:
objRecord = (ObjRecord)shapeToObj.get(record); objRecord = (ObjRecord) shapeToObj.get(record);
break; break;
case EscherTextboxRecord.RECORD_ID: case EscherTextboxRecord.RECORD_ID:
txtRecord = (TextObjectRecord)shapeToObj.get(record); txtRecord = (TextObjectRecord) shapeToObj.get(record);
break; break;
} }
} }
if (isEmbeddedObject(objRecord)){
HSSFObjectData objectData = new HSSFObjectData(container, objRecord, root);
out.addShape(objectData);
return;
}
CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0); CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0);
HSSFShape shape = null; HSSFShape shape = null;
switch (cmo.getObjectType()) { switch (cmo.getObjectType()) {
@ -128,7 +129,7 @@ public class HSSFShapeFactory {
case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING: case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING:
EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID); EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID);
EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES);
if (null != property){ if (null != property) {
shape = new HSSFPolygon(container, objRecord); shape = new HSSFPolygon(container, objRecord);
} else { } else {
shape = new HSSFSimpleShape(container, objRecord); shape = new HSSFSimpleShape(container, objRecord);
@ -143,9 +144,20 @@ public class HSSFShapeFactory {
default: default:
shape = new HSSFSimpleShape(container, objRecord); shape = new HSSFSimpleShape(container, objRecord);
} }
if (null != shape){ if (null != shape) {
out.addShape(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;
}
} }

View File

@ -1706,7 +1706,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
List<HSSFObjectData> objects = new ArrayList<HSSFObjectData>(); List<HSSFObjectData> objects = new ArrayList<HSSFObjectData>();
for (int i = 0; i < getNumberOfSheets(); i++) for (int i = 0; i < getNumberOfSheets(); i++)
{ {
getAllEmbeddedObjects(getSheetAt(i).getSheet().getRecords(), objects); getAllEmbeddedObjects(getSheetAt(i), objects);
} }
return objects; return objects;
} }
@ -1714,25 +1714,18 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
/** /**
* Gets all embedded OLE2 objects from the Workbook. * 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. * @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) { HSSFPatriarch patriarch = sheet.getDrawingPatriarch();
if (obj instanceof ObjRecord) if (null == patriarch){
{ return;
// 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));
}
} }
for (HSSFShape shape: patriarch.getChildren()){
if (shape instanceof HSSFObjectData){
objects.add((HSSFObjectData) shape);
} }
} }
} }
@ -1808,4 +1801,8 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
public boolean changeExternalReference(String oldUrl, String newUrl) { public boolean changeExternalReference(String oldUrl, String newUrl) {
return workbook.changeExternalReference(oldUrl, newUrl); return workbook.changeExternalReference(oldUrl, newUrl);
} }
public DirectoryNode getRootDirectory(){
return directory;
}
} }

View File

@ -198,7 +198,7 @@ public class TestDrawingShapes extends TestCase {
assertEquals(1, drawing.getChildren().size()); assertEquals(1, drawing.getChildren().size());
HSSFPicture picture = (HSSFPicture) drawing.getChildren().get(0); HSSFPicture picture = (HSSFPicture) drawing.getChildren().get(0);
assertEquals(picture.getPictureIndex(), 1); assertEquals(picture.getPictureIndex(), 2);
assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT); assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT);
assertEquals(picture.getFillColor(), 0x5DC943); assertEquals(picture.getFillColor(), 0x5DC943);
assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT); assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT);

View File

@ -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());
}
}

Binary file not shown.