diff options
author | Yegor Kozlov <yegor@apache.org> | 2012-06-08 17:47:37 +0000 |
---|---|---|
committer | Yegor Kozlov <yegor@apache.org> | 2012-06-08 17:47:37 +0000 |
commit | 03fe413245879f2daef2be39e29c4e0e3c7ede63 (patch) | |
tree | ed3bbad434a4f64d39f3595bbc459aa4142c979c | |
parent | de28fe9aff1aa6cd00689310643acd3b6b428abc (diff) | |
download | poi-03fe413245879f2daef2be39e29c4e0e3c7ede63.tar.gz poi-03fe413245879f2daef2be39e29c4e0e3c7ede63.zip |
initial support for reading shapes, see patch from June 8 in Bugzilla 53372
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1348168 13f79535-47bb-0310-9956-ffa450edef68
15 files changed, 476 insertions, 42 deletions
diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index 3bb7127356..1d48ff751f 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -43,16 +43,7 @@ import org.apache.poi.hssf.model.CommentShape; import org.apache.poi.hssf.model.ConvertAnchor; import org.apache.poi.hssf.model.DrawingManager2; import org.apache.poi.hssf.model.TextboxShape; -import org.apache.poi.hssf.usermodel.HSSFAnchor; -import org.apache.poi.hssf.usermodel.HSSFChildAnchor; -import org.apache.poi.hssf.usermodel.HSSFClientAnchor; -import org.apache.poi.hssf.usermodel.HSSFPatriarch; -import org.apache.poi.hssf.usermodel.HSSFPicture; -import org.apache.poi.hssf.usermodel.HSSFShape; -import org.apache.poi.hssf.usermodel.HSSFShapeContainer; -import org.apache.poi.hssf.usermodel.HSSFShapeGroup; -import org.apache.poi.hssf.usermodel.HSSFSimpleShape; -import org.apache.poi.hssf.usermodel.HSSFTextbox; +import org.apache.poi.hssf.usermodel.*; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -322,7 +313,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { /** * list of "tail" records that need to be serialized after all drawing group records */ - private List tailRec = new ArrayList(); + private List<Record> tailRec = new ArrayList<Record>(); public EscherAggregate(DrawingManager2 drawingManager) { this.drawingManager = drawingManager; @@ -413,7 +404,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { } // Decode the shapes - // agg.escherRecords = new ArrayList(); + // agg.escherRecords = new ArrayList(); int pos = 0; while (pos < buffer.size()) { EscherRecord r = recordFactory.createRecord(buffer.toByteArray(), pos); @@ -486,7 +477,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { public void afterRecordSerialize(int offset, short recordId, int size, EscherRecord record) { if (recordId == EscherClientDataRecord.RECORD_ID || recordId == EscherTextboxRecord.RECORD_ID) { - spEndingOffsets.add(Integer.valueOf(offset)); + spEndingOffsets.add(offset); shapes.add(record); } } @@ -501,12 +492,17 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { pos = offset; int writtenEscherBytes = 0; for (int i = 1; i < shapes.size(); i++) { - int endOffset = ((Integer) spEndingOffsets.get(i)).intValue() - 1; + int endOffset; + if (i == shapes.size()-1){ + endOffset = buffer.length - 1; + } else { + endOffset = (Integer) spEndingOffsets.get(i) - 1; + } int startOffset; if (i == 1) startOffset = 0; else - startOffset = ((Integer) spEndingOffsets.get(i - 1)).intValue(); + startOffset = (Integer) spEndingOffsets.get(i - 1); byte[] drawingData = new byte[endOffset - startOffset + 1]; @@ -790,7 +786,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { container.getChildren().add(shape); } - private static HSSFClientAnchor toClientAnchor(EscherClientAnchorRecord anchorRecord) { + public static HSSFClientAnchor toClientAnchor(EscherClientAnchorRecord anchorRecord) { HSSFClientAnchor anchor = new HSSFClientAnchor(); anchor.setAnchorType(anchorRecord.getFlag()); anchor.setCol1(anchorRecord.getCol1()); @@ -804,7 +800,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { return anchor; } - private static HSSFChildAnchor toChildAnchor(EscherChildAnchorRecord anchorRecord) { + public static HSSFChildAnchor toChildAnchor(EscherChildAnchorRecord anchorRecord) { HSSFChildAnchor anchor = new HSSFChildAnchor(); // anchor.setAnchorType(anchorRecord.getFlag()); // anchor.setCol1( anchorRecord.getCol1() ); @@ -1081,4 +1077,24 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { return null; } + /** + * Returns the mapping of {@link EscherClientDataRecord} and {@link EscherTextboxRecord} + * to their {@link TextObjectRecord} or {@link ObjRecord} . + * + * We need to access it outside of EscherAggregate when building shapes + * + * @return + */ + public Map<EscherRecord, Record> getShapeToObjMapping(){ + return Collections.unmodifiableMap(shapeToObj); + } + + /** + * + * @return tails records. We need to access them when building shapes. + * Every HSSFComment shape has a link to a NoteRecord from the tailRec collection. + */ + public List<Record> getTailRecords(){ + return Collections.unmodifiableList(tailRec); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java index 513ac619f4..ccd0e620cf 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java @@ -18,7 +18,16 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherChildAnchorRecord; + public final class HSSFChildAnchor extends HSSFAnchor { + + private EscherChildAnchorRecord escherChildAnchorRecord; + + public HSSFChildAnchor(EscherChildAnchorRecord escherChildAnchorRecord) { + this.escherChildAnchorRecord = escherChildAnchorRecord; + } + public HSSFChildAnchor() { } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java index cffb00cd55..a040144c27 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java @@ -17,6 +17,7 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherClientAnchorRecord; import org.apache.poi.ss.usermodel.ClientAnchor; @@ -33,6 +34,13 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { int row2; int anchorType; + private EscherClientAnchorRecord escherClientAnchorRecord; + + public HSSFClientAnchor(EscherClientAnchorRecord escherClientAnchorRecord) { + this.escherClientAnchorRecord = escherClientAnchorRecord; + //TODO set properties or read properties from EscherRecord ? + } + /** * Creates a new client anchor and defaults all the anchor positions to 0. */ diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index 672f82cc73..71549bbf31 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -22,9 +22,11 @@ import java.util.Iterator; import java.util.List; import org.apache.poi.ddf.EscherComplexProperty; +import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherOptRecord; import org.apache.poi.ddf.EscherProperty; import org.apache.poi.ddf.EscherBSERecord; +import org.apache.poi.ddf.EscherSpgrRecord; import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.ss.usermodel.Chart; import org.apache.poi.util.StringUtil; @@ -314,4 +316,23 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { throw new RuntimeException("NotImplemented"); } + + void buildShapeTree(){ + EscherContainerRecord dgContainer = _boundAggregate.getEscherContainer(); + EscherContainerRecord spgrConrainer = dgContainer.getChildContainers().get(0); + List<EscherContainerRecord> spgrChildren = spgrConrainer.getChildContainers(); + + for(int i = 0; i < spgrChildren.size(); i++){ + EscherContainerRecord spContainer = spgrChildren.get(i); + if (i == 0){ + EscherSpgrRecord spgr = (EscherSpgrRecord)spContainer.getChildById(EscherSpgrRecord.RECORD_ID); + setCoordinates( + spgr.getRectX1(), spgr.getRectY1(), + spgr.getRectX2(), spgr.getRectY2() + ); + } else { + HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this); + } + } + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java b/src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java new file mode 100644 index 0000000000..0a0468c144 --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java @@ -0,0 +1,15 @@ +package org.apache.poi.hssf.usermodel;
+
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.hssf.record.ObjRecord;
+
+/**
+ * @author Evgeniy Berlog
+ * @date 08.06.12
+ */
+public class HSSFRectangle extends HSSFShape{
+
+ public HSSFRectangle(EscherContainerRecord spContainer, ObjRecord objRecord) {
+ super(spContainer, objRecord);
+ }
+}
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index 3c586340fe..7ffdfdb9ba 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -17,6 +17,9 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.hssf.record.ObjRecord; + /** * An abstract shape. * @@ -40,7 +43,7 @@ public abstract class HSSFShape { public static final int LINESTYLE_NONE = -1; // TODO - make all these fields private - final HSSFShape parent; + HSSFShape parent; HSSFAnchor anchor; HSSFPatriarch _patriarch; private int _lineStyleColor = 0x08000040; @@ -49,15 +52,30 @@ public abstract class HSSFShape { private int _lineStyle = LINESTYLE_SOLID; private boolean _noFill = false; + private EscherContainerRecord spContainer; + private ObjRecord objRecord; + + public HSSFShape(EscherContainerRecord spContainer, ObjRecord objRecord){ + this.spContainer = spContainer; + this.objRecord = objRecord; + } /** * Create a new shape with the specified parent and anchor. */ - HSSFShape( HSSFShape parent, HSSFAnchor anchor ) + public HSSFShape( HSSFShape parent, HSSFAnchor anchor ) { this.parent = parent; this.anchor = anchor; } + public EscherContainerRecord getSpContainer() { + return spContainer; + } + + public ObjRecord getObjRecord() { + return objRecord; + } + /** * Gets the parent shape. */ diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java index 99e6a5de6a..181b3d17a9 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java @@ -31,4 +31,15 @@ public interface HSSFShapeContainer */ List getChildren(); + /** + * add shape to the list of child records + * @param shape + */ + public void addShape(HSSFShape shape); + + /** + * set coordinates of this group relative to the parent + */ + void setCoordinates( int x1, int y1, int x2, int y2 ); + } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java new file mode 100644 index 0000000000..fc88a2a16d --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -0,0 +1,157 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.poi.hssf.usermodel;
+
+import org.apache.poi.ddf.EscherClientDataRecord;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.ddf.EscherSpRecord;
+import org.apache.poi.ddf.EscherSpgrRecord;
+import org.apache.poi.ddf.EscherTextboxRecord;
+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.usermodel.drawing.HSSFShapeType;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author evgeniy
+ * date: 05.06.12
+ */
+public class HSSFShapeFactory {
+
+ private static final Map<Short, Class> shapeTypeToClass = new HashMap<Short, Class>(HSSFShapeType.values().length);
+ private static final ReflectionConstructorShapeCreator shapeCreator = new ReflectionConstructorShapeCreator(shapeTypeToClass);
+
+ static {
+ for (HSSFShapeType type: HSSFShapeType.values()){
+ shapeTypeToClass.put(type.getType(), type.getShape());
+ }
+ }
+
+ private static class ReflectionConstructorShapeCreator {
+
+ private final Map<Short, Class> shapeTypeToClass;
+
+ private ReflectionConstructorShapeCreator(Map<Short, Class> shapeTypeToClass) {
+ this.shapeTypeToClass = shapeTypeToClass;
+ }
+
+ public HSSFShape createNewShape(Short type, EscherContainerRecord spContainer, ObjRecord objRecord){
+ if (!shapeTypeToClass.containsKey(type)){
+ return new HSSFUnknownShape(spContainer, objRecord);
+ }
+ Class clazz = shapeTypeToClass.get(type);
+ if (null == clazz){
+ System.out.println("No class attached to shape type: "+type);
+ return new HSSFUnknownShape(spContainer, objRecord);
+ }
+ 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");
+ } catch (Exception e) {
+ throw new IllegalStateException("Couldn't create new instance of " + clazz.getName());
+ }
+ }
+ }
+
+ public static HSSFShape createShape(EscherRecord container, ObjRecord objRecord){
+ if (0 == container.getChildRecords().size()){
+ throw new IllegalArgumentException("Couldn't create shape from empty escher container");
+ }
+ if (container.getChild(0) instanceof EscherSpgrRecord){
+ return new HSSFShapeGroup((EscherContainerRecord) container, objRecord);
+ }
+
+ //TODO implement cases for all shapes
+ return new HSSFUnknownShape(container, objRecord);
+ }
+
+ public static HSSFShapeGroup createShapeGroup(){
+ return null;
+ }
+
+ public static HSSFShapeGroup createSimpleShape(EscherRecord container, ObjRecord objRecord){
+ return null;
+ }
+
+ public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out){
+ 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++) {
+ EscherContainerRecord spContainer = children.get(i);
+ if(i == 0){
+ EscherSpgrRecord spgr = (EscherSpgrRecord)spContainer.getChildById(EscherSpgrRecord.RECORD_ID);
+ group.setCoordinates(
+ spgr.getRectX1(), spgr.getRectY1(),
+ spgr.getRectX2(), spgr.getRectY2()
+ );
+ } else {
+ createShapeTree(spContainer, agg, group);
+ }
+ }
+ out.addShape(group);
+ } 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()) {
+ case EscherSpRecord.RECORD_ID:
+ spRecord = (EscherSpRecord)record;
+ break;
+ case EscherClientDataRecord.RECORD_ID:
+ objRecord = (ObjRecord)shapeToObj.get(record);
+ break;
+ case EscherTextboxRecord.RECORD_ID:
+ txtRecord = (TextObjectRecord)shapeToObj.get(record);
+ break;
+ }
+ }
+ if (null != objRecord){
+ HSSFShape shape = shapeCreator.createNewShape(spRecord.getShapeType(), container, objRecord);
+ out.addShape(shape);
+ }
+ if (null != txtRecord){
+ //TODO resolve textbox
+// TextboxShape shape = new TextboxShape(container, txtRecord);
+// out.a
+ }
+//
+// //TODO decide what shape to create based on ObjRecord / EscherSpRecord
+// HSSFShape shape = new HSSFUnknownShape(container, objRecord);
+// out.addShape(shape);
+ }
+ }
+}
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index 905dad3fc2..7cab3e493d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -17,6 +17,15 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherChildAnchorRecord; +import org.apache.poi.ddf.EscherClientAnchorRecord; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.ddf.EscherSpgrRecord; +import org.apache.poi.hssf.model.TextboxShape; +import org.apache.poi.hssf.record.EscherAggregate; +import org.apache.poi.hssf.record.ObjRecord; + import java.util.ArrayList; import java.util.List; import java.util.Iterator; @@ -37,6 +46,32 @@ public class HSSFShapeGroup int x2 = 1023; int y2 = 255; + public HSSFShapeGroup(EscherContainerRecord spgrContainer, ObjRecord objRecord) { + super(spgrContainer, objRecord); + + // read internal and external coordinates from spgrContainer + EscherContainerRecord spContainer = spgrContainer.getChildContainers().get(0); + for(EscherRecord ch : spContainer.getChildRecords()){ + switch(ch.getRecordId()) { + case EscherSpgrRecord.RECORD_ID: + EscherSpgrRecord spgr = (EscherSpgrRecord)ch; + setCoordinates( + spgr.getRectX1(), spgr.getRectY1(), + spgr.getRectX2(), spgr.getRectY2() + ); + break; + case EscherClientAnchorRecord.RECORD_ID: + this.anchor = EscherAggregate.toClientAnchor((EscherClientAnchorRecord)ch); + // TODO anchor = new HSSFClientAnchor((EscherChildAnchorRecord)ch); + break; + case EscherChildAnchorRecord.RECORD_ID: + this.anchor = EscherAggregate.toChildAnchor((EscherChildAnchorRecord)ch); + // TODO anchor = new HSSFChildAnchor((EscherClientAnchorRecord)ch); + break; + } + } + + } public HSSFShapeGroup( HSSFShape parent, HSSFAnchor anchor ) { @@ -61,6 +96,11 @@ public class HSSFShapeGroup shapes.add(shape); } + public void addTextBox(TextboxShape textboxShape){ +// HSSFTextbox shape = new HSSFTextbox(this, textboxShape.geanchor); +// shapes.add(textboxShape); + } + /** * Create a new simple shape under this group. * @param anchor the position of the shape. diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index fe332eb83e..da7a404b28 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -1738,12 +1738,16 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { if(agg == null) return null; _patriarch = new HSSFPatriarch(this, agg); - agg.setPatriarch(_patriarch); + _patriarch.buildShapeTree(); + + //HSSFShapeFactory.createShapeTree(); + //agg.setPatriarch(_patriarch); + //EscherAggregate.createShapeTree(EscherAggregate.getMainSpgrContainer(agg), agg.getPatriarch(), agg); // Have it process the records into high level objects // as best it can do (this step may eat anything // that isn't supported, you were warned...) - agg.convertRecordsToUserModel(); +// agg.convertRecordsToUserModel(); // Return what we could cope with return _patriarch; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java new file mode 100644 index 0000000000..d4cac9be9a --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java @@ -0,0 +1,33 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.poi.hssf.usermodel;
+
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.hssf.record.ObjRecord;
+
+/**
+ * @author Evgeniy Berlog
+ * date: 05.06.12
+ */
+public class HSSFUnknownShape extends HSSFShape {
+
+ public HSSFUnknownShape(EscherRecord spContainer, ObjRecord objRecord) {
+ super((EscherContainerRecord) spContainer, objRecord);
+ }
+}
diff --git a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java new file mode 100644 index 0000000000..2818687921 --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java @@ -0,0 +1,29 @@ +package org.apache.poi.hssf.usermodel.drawing;
+
+import org.apache.poi.hssf.usermodel.HSSFRectangle;
+
+/**
+ * @author Evgeniy Berlog
+ * date: 08.06.12
+ */
+public enum HSSFShapeType {
+ NOT_PRIMITIVE(0x0, null),
+ RECTANGLE(0x1, HSSFRectangle.class),
+ ROUND_RECTANGLE(0x2, null);
+
+ private Short type;
+ private Class shape;
+
+ HSSFShapeType(Integer type, Class shape) {
+ this.type = type.shortValue();
+ this.shape = shape;
+ }
+
+ public Short getType() {
+ return type;
+ }
+
+ public Class getShape() {
+ return shape;
+ }
+}
diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java index a22ce4a0cc..0608c0eb18 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -17,13 +17,13 @@ package org.apache.poi.hssf.model;
import junit.framework.TestCase;
+import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherDggRecord;
+import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFTestHelper;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.util.HexRead;
import java.io.*;
@@ -35,18 +35,84 @@ import java.util.List; * @author Evgeniy Berlog
*/
public class TestDrawingAggregate extends TestCase {
- private static byte[] toByteArray(List<RecordBase> records){
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- for(RecordBase rb : records) {
- Record r = (Record)rb;
- try {
- out.write(r.serialize());
- } catch (IOException e){
- throw new RuntimeException(e);
- }
- }
- return out.toByteArray();
+
+ private int spgrCount = 0;
+ private int spCount = 0;
+ private int shapeCount = 0;
+ private int shGroupCount = 0;
+
+ /*
+ * EscherAggregate must have for each SpgrContainer HSSFShapeGroup and for each SpContainer HSSFShape
+ */
+ private void checkEscherAndShapesCount(EscherAggregate agg, HSSFSheet sheet) {
+ /*
+ HSSFPatriarch patriarch = HSSFTestHelper.createTestPatriarch(sheet, agg);
+ agg.setPatriarch(patriarch);
+ EscherAggregate.createShapeTree(EscherAggregate.getMainSpgrContainer(agg), agg.getPatriarch(), agg);
+ EscherContainerRecord mainContainer = EscherAggregate.getMainSpgrContainer(agg);
+ calculateShapesCount(agg.getPatriarch());
+ calculateEscherContainersCount(mainContainer);
+
+ assertEquals(spgrCount, shGroupCount);
+ assertEquals(spCount - spgrCount - 1, shapeCount);
+ */
+ }
+
+ private void calculateEscherContainersCount(EscherContainerRecord spgr) {
+ for (EscherRecord record : spgr.getChildRecords()) {
+ if (EscherContainerRecord.SP_CONTAINER == record.getRecordId()) {
+ spCount++;
+ continue;
+ }
+ if (EscherContainerRecord.SPGR_CONTAINER == record.getRecordId()) {
+ spgrCount++;
+ calculateEscherContainersCount((EscherContainerRecord) record);
+ }
+ }
+ }
+
+ private void calculateShapesCount(HSSFShapeContainer group) {
+ for (HSSFShape shape : (List<HSSFShape>) group.getChildren()) {
+ if (shape instanceof HSSFShapeGroup) {
+ shGroupCount++;
+ calculateShapesCount((HSSFShapeGroup) shape);
+ } else {
+ shapeCount++;
+ }
+ }
+ }
+
+
+ private static byte[] toByteArray(List<RecordBase> records) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ for (RecordBase rb : records) {
+ Record r = (Record) rb;
+ try {
+ out.write(r.serialize());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
+ return out.toByteArray();
+ }
+
+ public void testSolverContainerMustBeSavedDuringSerialization(){
+ HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SolverContainerAfterSPGR.xls");
+ HSSFSheet sh = wb.getSheetAt(0);
+ InternalSheet ish = HSSFTestHelper.getSheetForTest(sh);
+ sh.getDrawingPatriarch();
+ EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid);
+ assertEquals(agg.getEscherRecords().get(0).getChildRecords().size(), 3);
+ assertEquals(agg.getEscherRecords().get(0).getChild(2).getRecordId(), EscherContainerRecord.SOLVER_CONTAINER);
+ wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
+ sh = wb.getSheetAt(0);
+ sh.getDrawingPatriarch();
+ ish = HSSFTestHelper.getSheetForTest(sh);
+ agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid);
+ assertEquals(agg.getEscherRecords().get(0).getChildRecords().size(), 3);
+ assertEquals(agg.getEscherRecords().get(0).getChild(2).getRecordId(), EscherContainerRecord.SOLVER_CONTAINER);
+
+ }
/**
* test reading drawing aggregate from a test file from Bugzilla 45129
@@ -107,6 +173,7 @@ public class TestDrawingAggregate extends TestCase { byte[] dgBytesAfterSave = agg.serialize();
assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);
assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
+ checkEscherAndShapesCount(agg, sh);
}
/**
@@ -174,7 +241,7 @@ public class TestDrawingAggregate extends TestCase { assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);
assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
-
+ checkEscherAndShapesCount(agg, sh);
}
@@ -185,21 +252,20 @@ public class TestDrawingAggregate extends TestCase { List<RecordBase> records = isheet.getRecords();
HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb);
- InternalSheet isheet2 = HSSFTestHelper.getSheetForTest( wb2.getSheetAt(0));
+ InternalSheet isheet2 = HSSFTestHelper.getSheetForTest(wb2.getSheetAt(0));
List<RecordBase> records2 = isheet2.getRecords();
assertEquals(records.size(), records2.size());
- for(int i = 0; i < records.size(); i++) {
+ for (int i = 0; i < records.size(); i++) {
RecordBase r1 = records.get(i);
RecordBase r2 = records2.get(i);
assertTrue(r1.getClass() == r2.getClass());
assertEquals(r1.getRecordSize(), r2.getRecordSize());
- if(r1 instanceof Record ){
- assertEquals(((Record)r1).getSid(), ((Record)r2).getSid());
+ if (r1 instanceof Record) {
+ assertEquals(((Record) r1).getSid(), ((Record) r2).getSid());
assertTrue(Arrays.equals(((Record) r1).serialize(), ((Record) r2).serialize()));
}
}
-
}
public void testSerializeDrawingWithComments() throws IOException {
@@ -257,6 +323,7 @@ public class TestDrawingAggregate extends TestCase { byte[] dgBytesAfterSave = agg.serialize();
assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);
assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
+ checkEscherAndShapesCount(agg, sh);
}
@@ -314,7 +381,8 @@ public class TestDrawingAggregate extends TestCase { byte[] dgBytesAfterSave = agg.serialize();
assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);
- assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
+ assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
+ checkEscherAndShapesCount(agg, sh);
}
public void testUnhandledContinue() {
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java index 7c5a88bd45..0b79eae50e 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java @@ -18,6 +18,7 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.hssf.model.InternalSheet; import org.apache.poi.hssf.model.InternalWorkbook; +import org.apache.poi.hssf.record.EscherAggregate; /** * Helper class for HSSF tests that aren't within the @@ -34,4 +35,8 @@ public class HSSFTestHelper { public static InternalSheet getSheetForTest(HSSFSheet sheet) { return sheet.getSheet(); } + + public static HSSFPatriarch createTestPatriarch(HSSFSheet sheet, EscherAggregate agg){ + return new HSSFPatriarch(sheet, agg); + } } diff --git a/test-data/spreadsheet/SolverContainerAfterSPGR.xls b/test-data/spreadsheet/SolverContainerAfterSPGR.xls Binary files differnew file mode 100755 index 0000000000..57a1b17048 --- /dev/null +++ b/test-data/spreadsheet/SolverContainerAfterSPGR.xls |