001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.ddf;
019:
020: import org.apache.poi.hssf.record.RecordFormatException;
021:
022: import java.lang.reflect.Constructor;
023: import java.util.HashMap;
024: import java.util.Map;
025:
026: /**
027: * Generates escher records when provided the byte array containing those records.
028: *
029: * @author Glen Stampoultzis
030: * @author Nick Burch (nick at torchbox . com)
031: *
032: * @see EscherRecordFactory
033: */
034: public class DefaultEscherRecordFactory implements EscherRecordFactory {
035: private static Class[] escherRecordClasses = {
036: EscherBSERecord.class, EscherOptRecord.class,
037: EscherClientAnchorRecord.class, EscherDgRecord.class,
038: EscherSpgrRecord.class, EscherSpRecord.class,
039: EscherClientDataRecord.class, EscherDggRecord.class,
040: EscherSplitMenuColorsRecord.class,
041: EscherChildAnchorRecord.class, EscherTextboxRecord.class };
042: private static Map recordsMap = recordsToMap(escherRecordClasses);
043:
044: /**
045: * Creates an instance of the escher record factory
046: */
047: public DefaultEscherRecordFactory() {
048: }
049:
050: /**
051: * Generates an escher record including the any children contained under that record.
052: * An exception is thrown if the record could not be generated.
053: *
054: * @param data The byte array containing the records
055: * @param offset The starting offset into the byte array
056: * @return The generated escher record
057: */
058: public EscherRecord createRecord(byte[] data, int offset) {
059: EscherRecord.EscherRecordHeader header = EscherRecord.EscherRecordHeader
060: .readHeader(data, offset);
061:
062: // Options of 0x000F means container record
063: // However, EscherTextboxRecord are containers of records for the
064: // host application, not of other Escher records, so treat them
065: // differently
066: if ((header.getOptions() & (short) 0x000F) == (short) 0x000F
067: && header.getRecordId() != EscherTextboxRecord.RECORD_ID) {
068: EscherContainerRecord r = new EscherContainerRecord();
069: r.setRecordId(header.getRecordId());
070: r.setOptions(header.getOptions());
071: return r;
072: } else if (header.getRecordId() >= EscherBlipRecord.RECORD_ID_START
073: && header.getRecordId() <= EscherBlipRecord.RECORD_ID_END) {
074: EscherBlipRecord r;
075: if (header.getRecordId() == EscherBitmapBlip.RECORD_ID_DIB
076: || header.getRecordId() == EscherBitmapBlip.RECORD_ID_JPEG
077: || header.getRecordId() == EscherBitmapBlip.RECORD_ID_PNG) {
078: r = new EscherBitmapBlip();
079: } else if (header.getRecordId() == EscherMetafileBlip.RECORD_ID_EMF
080: || header.getRecordId() == EscherMetafileBlip.RECORD_ID_WMF
081: || header.getRecordId() == EscherMetafileBlip.RECORD_ID_PICT) {
082: r = new EscherMetafileBlip();
083: } else {
084: r = new EscherBlipRecord();
085: }
086: r.setRecordId(header.getRecordId());
087: r.setOptions(header.getOptions());
088: return r;
089: } else {
090: Constructor recordConstructor = (Constructor) recordsMap
091: .get(new Short(header.getRecordId()));
092: EscherRecord escherRecord = null;
093: if (recordConstructor != null) {
094: try {
095: escherRecord = (EscherRecord) recordConstructor
096: .newInstance(new Object[] {});
097: escherRecord.setRecordId(header.getRecordId());
098: escherRecord.setOptions(header.getOptions());
099: } catch (Exception e) {
100: escherRecord = null;
101: }
102: }
103: return escherRecord == null ? new UnknownEscherRecord()
104: : escherRecord;
105: }
106: }
107:
108: /**
109: * Converts from a list of classes into a map that contains the record id as the key and
110: * the Constructor in the value part of the map. It does this by using reflection to look up
111: * the RECORD_ID field then using reflection again to find a reference to the constructor.
112: *
113: * @param records The records to convert
114: * @return The map containing the id/constructor pairs.
115: */
116: private static Map recordsToMap(Class[] records) {
117: Map result = new HashMap();
118: Constructor constructor;
119:
120: for (int i = 0; i < records.length; i++) {
121: Class record = null;
122: short sid = 0;
123:
124: record = records[i];
125: try {
126: sid = record.getField("RECORD_ID").getShort(null);
127: constructor = record.getConstructor(new Class[] {});
128: } catch (Exception illegalArgumentException) {
129: throw new RecordFormatException(
130: "Unable to determine record types");
131: }
132: result.put(new Short(sid), constructor);
133: }
134: return result;
135: }
136:
137: }
|