blob: c7dce3053568108b7439b6edfeb9f9b9dc98c893 [file] [log] [blame]
/*
* 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.EscherProperty;
import org.apache.poi.ddf.EscherPropertyTypes;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherRecordTypes;
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
if (children.size() > 1) {
children.subList(1, children.size()).forEach(c -> createShapeTree(c, 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 (EscherRecordTypes.forTypeID(record.getRecordId())) {
case CLIENT_DATA:
objRecord = (ObjRecord) shapeToObj.get(record);
break;
case CLIENT_TEXTBOX:
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(EscherPropertyTypes.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;
}
}