/* * 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 java.util.List; import java.util.Map; import org.apache.poi.ddf.EscherClientDataRecord; import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherOptRecord; import org.apache.poi.ddf.EscherProperties; import org.apache.poi.ddf.EscherProperty; import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.EscherTextboxRecord; import org.apache.poi.hssf.record.CommonObjectDataSubRecord; import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord; import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.record.ObjRecord; import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.SubRecord; import org.apache.poi.hssf.record.TextObjectRecord; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.util.RecordFormatException; /** * Factory class for producing Excel Shapes from Escher records */ public class HSSFShapeFactory { /** * build shape tree from escher container * @param container root escher container from which escher records must be taken * @param agg - EscherAggregate * @param out - shape container to which shapes must be added * @param root - node to create HSSFObjectData shapes */ public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out, DirectoryNode root) { if (container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { ObjRecord obj = null; EscherClientDataRecord clientData = ((EscherContainerRecord) container.getChild(0)).getChildById(EscherClientDataRecord.RECORD_ID); if (null != clientData) { obj = (ObjRecord) agg.getShapeToObjMapping().get(clientData); } HSSFShapeGroup group = new HSSFShapeGroup(container, obj); 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) { createShapeTree(spContainer, agg, group, root); } } out.addShape(group); } else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER) { Map<EscherRecord, Record> shapeToObj = agg.getShapeToObjMapping(); ObjRecord objRecord = null; TextObjectRecord txtRecord = null; for (EscherRecord record : container) { switch (record.getRecordId()) { case EscherClientDataRecord.RECORD_ID: objRecord = (ObjRecord) shapeToObj.get(record); break; case EscherTextboxRecord.RECORD_ID: txtRecord = (TextObjectRecord) shapeToObj.get(record); break; default: break; } } if (objRecord == null) { throw new RecordFormatException("EscherClientDataRecord can't be found."); } if (isEmbeddedObject(objRecord)) { HSSFObjectData objectData = new HSSFObjectData(container, objRecord, root); out.addShape(objectData); return; } CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0); final HSSFShape shape; switch (cmo.getObjectType()) { case CommonObjectDataSubRecord.OBJECT_TYPE_PICTURE: shape = new HSSFPicture(container, objRecord); break; case CommonObjectDataSubRecord.OBJECT_TYPE_RECTANGLE: shape = new HSSFSimpleShape(container, objRecord, txtRecord); break; case CommonObjectDataSubRecord.OBJECT_TYPE_LINE: shape = new HSSFSimpleShape(container, objRecord); break; case CommonObjectDataSubRecord.OBJECT_TYPE_COMBO_BOX: shape = new HSSFCombobox(container, objRecord); break; case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING: EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID); if(optRecord == null) { shape = new HSSFSimpleShape(container, objRecord, txtRecord); } else { EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); if (null != property) { shape = new HSSFPolygon(container, objRecord, txtRecord); } else { shape = new HSSFSimpleShape(container, objRecord, txtRecord); } } break; case CommonObjectDataSubRecord.OBJECT_TYPE_TEXT: shape = new HSSFTextbox(container, objRecord, txtRecord); break; case CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT: shape = new HSSFComment(container, objRecord, txtRecord, agg.getNoteRecordByObj(objRecord)); break; default: shape = new HSSFSimpleShape(container, objRecord, txtRecord); } out.addShape(shape); } } private static boolean isEmbeddedObject(ObjRecord obj) { for (SubRecord sub : obj.getSubRecords()) { if (sub instanceof EmbeddedObjectRefSubRecord) { return true; } } return false; } }