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
|
|
|
|
2019-03-26 15:11:21 -04:00
|
|
|
package com.moparisthebest.poi.ddf;
|
2004-04-09 07:45:38 -04:00
|
|
|
|
|
|
|
import java.lang.reflect.Constructor;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Map;
|
|
|
|
|
2019-03-26 15:11:21 -04:00
|
|
|
import com.moparisthebest.poi.util.LittleEndian;
|
2011-09-06 07:13:41 -04:00
|
|
|
|
2004-04-09 07:45:38 -04:00
|
|
|
/**
|
|
|
|
* Generates escher records when provided the byte array containing those records.
|
|
|
|
*
|
|
|
|
* @see EscherRecordFactory
|
|
|
|
*/
|
2009-05-19 15:21:12 -04:00
|
|
|
public class DefaultEscherRecordFactory implements EscherRecordFactory {
|
2011-07-28 07:44:50 -04:00
|
|
|
private static Class<?>[] escherRecordClasses = { EscherBSERecord.class,
|
|
|
|
EscherOptRecord.class, EscherTertiaryOptRecord.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
|
|
|
}
|
|
|
|
|
2016-06-06 19:33:00 -04:00
|
|
|
@Override
|
2009-05-19 15:21:12 -04:00
|
|
|
public EscherRecord createRecord(byte[] data, int offset) {
|
2011-09-06 07:13:41 -04:00
|
|
|
short options = LittleEndian.getShort( data, offset );
|
|
|
|
short recordId = LittleEndian.getShort( data, offset + 2 );
|
|
|
|
// int remainingBytes = LittleEndian.getInt( data, offset + 4 );
|
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
|
2012-06-19 17:00:04 -04:00
|
|
|
if (isContainer(options, recordId)) {
|
2004-04-09 07:45:38 -04:00
|
|
|
EscherContainerRecord r = new EscherContainerRecord();
|
2011-09-06 07:13:41 -04:00
|
|
|
r.setRecordId( recordId );
|
|
|
|
r.setOptions( options );
|
2004-04-09 07:45:38 -04:00
|
|
|
return r;
|
|
|
|
}
|
2009-05-19 15:21:12 -04:00
|
|
|
|
2011-09-06 07:13:41 -04:00
|
|
|
if (recordId >= EscherBlipRecord.RECORD_ID_START
|
|
|
|
&& recordId <= EscherBlipRecord.RECORD_ID_END) {
|
2005-05-01 07:26:18 -04:00
|
|
|
EscherBlipRecord r;
|
2011-09-06 07:13:41 -04:00
|
|
|
if (recordId == EscherBitmapBlip.RECORD_ID_DIB ||
|
|
|
|
recordId == EscherBitmapBlip.RECORD_ID_JPEG ||
|
|
|
|
recordId == EscherBitmapBlip.RECORD_ID_PNG)
|
2005-05-01 07:26:18 -04:00
|
|
|
{
|
|
|
|
r = new EscherBitmapBlip();
|
|
|
|
}
|
2011-09-06 07:13:41 -04:00
|
|
|
else if (recordId == EscherMetafileBlip.RECORD_ID_EMF ||
|
|
|
|
recordId == EscherMetafileBlip.RECORD_ID_WMF ||
|
|
|
|
recordId == EscherMetafileBlip.RECORD_ID_PICT)
|
2007-08-26 11:26:29 -04:00
|
|
|
{
|
|
|
|
r = new EscherMetafileBlip();
|
2009-05-19 15:21:12 -04:00
|
|
|
} else {
|
2005-05-01 07:26:18 -04:00
|
|
|
r = new EscherBlipRecord();
|
|
|
|
}
|
2011-09-06 07:13:41 -04:00
|
|
|
r.setRecordId( recordId );
|
|
|
|
r.setOptions( options );
|
2004-04-09 07:45:38 -04:00
|
|
|
return r;
|
|
|
|
}
|
2009-05-19 15:21:12 -04:00
|
|
|
|
2011-09-06 07:13:41 -04:00
|
|
|
Constructor<? extends EscherRecord> recordConstructor = recordsMap.get(Short.valueOf(recordId));
|
2016-07-17 17:18:07 -04:00
|
|
|
final EscherRecord escherRecord;
|
2009-05-19 15:21:12 -04:00
|
|
|
if (recordConstructor == null) {
|
|
|
|
return new UnknownEscherRecord();
|
|
|
|
}
|
|
|
|
try {
|
2016-07-17 17:18:07 -04:00
|
|
|
escherRecord = recordConstructor.newInstance();
|
2009-05-19 15:21:12 -04:00
|
|
|
} catch (Exception e) {
|
|
|
|
return new UnknownEscherRecord();
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
2011-09-06 07:13:41 -04:00
|
|
|
escherRecord.setRecordId(recordId);
|
|
|
|
escherRecord.setOptions(options);
|
2009-05-19 15:21:12 -04:00
|
|
|
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.
|
|
|
|
*/
|
2015-07-07 20:09:34 -04:00
|
|
|
protected static Map<Short, Constructor<? extends EscherRecord>> recordsToMap(Class<?>[] recClasses) {
|
2009-05-19 15:21:12 -04:00
|
|
|
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
|
|
|
|
2016-07-17 17:18:07 -04:00
|
|
|
for (Class<?> recClass : recClasses) {
|
2009-05-19 15:21:12 -04:00
|
|
|
@SuppressWarnings("unchecked")
|
2016-07-17 17:18:07 -04:00
|
|
|
Class<? extends EscherRecord> recCls = (Class<? extends EscherRecord>) recClass;
|
2009-05-19 15:21:12 -04:00
|
|
|
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 {
|
2016-07-17 17:18:07 -04:00
|
|
|
constructor = recCls.getConstructor(EMPTY_CLASS_ARRAY);
|
2009-05-19 15:21:12 -04:00
|
|
|
} catch (NoSuchMethodException e) {
|
|
|
|
throw new RuntimeException(e);
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
2009-10-08 18:29:41 -04:00
|
|
|
result.put(Short.valueOf(sid), constructor);
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
2012-06-19 17:00:04 -04:00
|
|
|
|
|
|
|
public static boolean isContainer(short options, short recordId){
|
|
|
|
if(recordId >= EscherContainerRecord.DGG_CONTAINER && recordId
|
|
|
|
<= EscherContainerRecord.SOLVER_CONTAINER){
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
if (recordId == EscherTextboxRecord.RECORD_ID) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return ( options & (short) 0x000F ) == (short) 0x000F;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|