2004-04-09 09:05:39 -04:00
|
|
|
/* ====================================================================
|
2006-12-22 14:18:16 -05:00
|
|
|
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
|
2004-04-09 09:05:39 -04:00
|
|
|
|
|
|
|
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.
|
|
|
|
==================================================================== */
|
2004-04-09 07:45:38 -04:00
|
|
|
|
2009-05-19 15:21:12 -04:00
|
|
|
package org.apache.poi.ddf;
|
2004-04-09 07:45:38 -04:00
|
|
|
|
|
|
|
import java.lang.reflect.Constructor;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates escher records when provided the byte array containing those records.
|
|
|
|
*
|
|
|
|
* @author Glen Stampoultzis
|
2005-05-05 09:06:06 -04:00
|
|
|
* @author Nick Burch (nick at torchbox . com)
|
|
|
|
*
|
2004-04-09 07:45:38 -04:00
|
|
|
* @see EscherRecordFactory
|
|
|
|
*/
|
2009-05-19 15:21:12 -04:00
|
|
|
public class DefaultEscherRecordFactory implements EscherRecordFactory {
|
|
|
|
private static Class<?>[] escherRecordClasses = {
|
2004-04-09 07:45:38 -04:00
|
|
|
EscherBSERecord.class, EscherOptRecord.class, EscherClientAnchorRecord.class, EscherDgRecord.class,
|
|
|
|
EscherSpgrRecord.class, EscherSpRecord.class, EscherClientDataRecord.class, EscherDggRecord.class,
|
|
|
|
EscherSplitMenuColorsRecord.class, EscherChildAnchorRecord.class, EscherTextboxRecord.class
|
|
|
|
};
|
2009-05-19 15:21:12 -04:00
|
|
|
private static Map<Short, Constructor<? extends EscherRecord>> recordsMap = recordsToMap( escherRecordClasses );
|
2004-04-09 07:45:38 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates an instance of the escher record factory
|
|
|
|
*/
|
2009-05-19 15:21:12 -04:00
|
|
|
public DefaultEscherRecordFactory() {
|
|
|
|
// no instance initialisation
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates an escher record including the any children contained under that record.
|
|
|
|
* An exception is thrown if the record could not be generated.
|
|
|
|
*
|
|
|
|
* @param data The byte array containing the records
|
|
|
|
* @param offset The starting offset into the byte array
|
|
|
|
* @return The generated escher record
|
|
|
|
*/
|
2009-05-19 15:21:12 -04:00
|
|
|
public EscherRecord createRecord(byte[] data, int offset) {
|
2004-04-09 07:45:38 -04:00
|
|
|
EscherRecord.EscherRecordHeader header = EscherRecord.EscherRecordHeader.readHeader( data, offset );
|
2005-05-05 09:06:06 -04:00
|
|
|
|
2009-05-19 15:21:12 -04:00
|
|
|
// Options of 0x000F means container record
|
|
|
|
// However, EscherTextboxRecord are containers of records for the
|
|
|
|
// host application, not of other Escher records, so treat them
|
|
|
|
// differently
|
2005-05-05 09:06:06 -04:00
|
|
|
if ( ( header.getOptions() & (short) 0x000F ) == (short) 0x000F
|
|
|
|
&& header.getRecordId() != EscherTextboxRecord.RECORD_ID ) {
|
2004-04-09 07:45:38 -04:00
|
|
|
EscherContainerRecord r = new EscherContainerRecord();
|
|
|
|
r.setRecordId( header.getRecordId() );
|
|
|
|
r.setOptions( header.getOptions() );
|
|
|
|
return r;
|
|
|
|
}
|
2009-05-19 15:21:12 -04:00
|
|
|
|
|
|
|
if (header.getRecordId() >= EscherBlipRecord.RECORD_ID_START
|
|
|
|
&& header.getRecordId() <= EscherBlipRecord.RECORD_ID_END) {
|
2005-05-01 07:26:18 -04:00
|
|
|
EscherBlipRecord r;
|
|
|
|
if (header.getRecordId() == EscherBitmapBlip.RECORD_ID_DIB ||
|
|
|
|
header.getRecordId() == EscherBitmapBlip.RECORD_ID_JPEG ||
|
|
|
|
header.getRecordId() == EscherBitmapBlip.RECORD_ID_PNG)
|
|
|
|
{
|
|
|
|
r = new EscherBitmapBlip();
|
|
|
|
}
|
2007-08-26 11:26:29 -04:00
|
|
|
else if (header.getRecordId() == EscherMetafileBlip.RECORD_ID_EMF ||
|
|
|
|
header.getRecordId() == EscherMetafileBlip.RECORD_ID_WMF ||
|
|
|
|
header.getRecordId() == EscherMetafileBlip.RECORD_ID_PICT)
|
|
|
|
{
|
|
|
|
r = new EscherMetafileBlip();
|
2009-05-19 15:21:12 -04:00
|
|
|
} else {
|
2005-05-01 07:26:18 -04:00
|
|
|
r = new EscherBlipRecord();
|
|
|
|
}
|
2004-04-09 07:45:38 -04:00
|
|
|
r.setRecordId( header.getRecordId() );
|
|
|
|
r.setOptions( header.getOptions() );
|
|
|
|
return r;
|
|
|
|
}
|
2009-05-19 15:21:12 -04:00
|
|
|
|
|
|
|
Constructor<? extends EscherRecord> recordConstructor = recordsMap.get(new Short(header.getRecordId()));
|
|
|
|
EscherRecord escherRecord = null;
|
|
|
|
if (recordConstructor == null) {
|
|
|
|
return new UnknownEscherRecord();
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
escherRecord = recordConstructor.newInstance(new Object[] {});
|
|
|
|
} catch (Exception e) {
|
|
|
|
return new UnknownEscherRecord();
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
2009-05-19 15:21:12 -04:00
|
|
|
escherRecord.setRecordId(header.getRecordId());
|
|
|
|
escherRecord.setOptions(header.getOptions());
|
|
|
|
return escherRecord;
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts from a list of classes into a map that contains the record id as the key and
|
|
|
|
* the Constructor in the value part of the map. It does this by using reflection to look up
|
|
|
|
* the RECORD_ID field then using reflection again to find a reference to the constructor.
|
2009-05-19 15:21:12 -04:00
|
|
|
*
|
|
|
|
* @param recClasses The records to convert
|
2004-04-09 07:45:38 -04:00
|
|
|
* @return The map containing the id/constructor pairs.
|
|
|
|
*/
|
2009-05-19 15:21:12 -04:00
|
|
|
private static Map<Short, Constructor<? extends EscherRecord>> recordsToMap(Class<?>[] recClasses) {
|
|
|
|
Map<Short, Constructor<? extends EscherRecord>> result = new HashMap<Short, Constructor<? extends EscherRecord>>();
|
|
|
|
final Class<?>[] EMPTY_CLASS_ARRAY = new Class[0];
|
2004-04-09 07:45:38 -04:00
|
|
|
|
2009-05-19 15:21:12 -04:00
|
|
|
for (int i = 0; i < recClasses.length; i++) {
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
Class<? extends EscherRecord> recCls = (Class<? extends EscherRecord>) recClasses[i];
|
|
|
|
short sid;
|
|
|
|
try {
|
|
|
|
sid = recCls.getField("RECORD_ID").getShort(null);
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
} catch (IllegalAccessException e) {
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
} catch (NoSuchFieldException e) {
|
|
|
|
throw new RuntimeException(e);
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
2009-05-19 15:21:12 -04:00
|
|
|
Constructor<? extends EscherRecord> constructor;
|
|
|
|
try {
|
|
|
|
constructor = recCls.getConstructor( EMPTY_CLASS_ARRAY );
|
|
|
|
} catch (NoSuchMethodException e) {
|
|
|
|
throw new RuntimeException(e);
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
2009-05-19 15:21:12 -04:00
|
|
|
result.put(new Short(sid), constructor);
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|