| |
| /* ==================================================================== |
| 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.ddf; |
| |
| import org.apache.poi.hssf.record.RecordFormatException; |
| |
| 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 |
| * @author Nick Burch (nick at torchbox . com) |
| * |
| * @see EscherRecordFactory |
| */ |
| public class DefaultEscherRecordFactory |
| implements EscherRecordFactory |
| { |
| private static Class[] escherRecordClasses = { |
| EscherBSERecord.class, EscherOptRecord.class, EscherClientAnchorRecord.class, EscherDgRecord.class, |
| EscherSpgrRecord.class, EscherSpRecord.class, EscherClientDataRecord.class, EscherDggRecord.class, |
| EscherSplitMenuColorsRecord.class, EscherChildAnchorRecord.class, EscherTextboxRecord.class |
| }; |
| private static Map recordsMap = recordsToMap( escherRecordClasses ); |
| |
| /** |
| * Creates an instance of the escher record factory |
| */ |
| public DefaultEscherRecordFactory() |
| { |
| } |
| |
| /** |
| * 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 |
| */ |
| public EscherRecord createRecord( byte[] data, int offset ) |
| { |
| EscherRecord.EscherRecordHeader header = EscherRecord.EscherRecordHeader.readHeader( data, offset ); |
| |
| // 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 |
| if ( ( header.getOptions() & (short) 0x000F ) == (short) 0x000F |
| && header.getRecordId() != EscherTextboxRecord.RECORD_ID ) { |
| EscherContainerRecord r = new EscherContainerRecord(); |
| r.setRecordId( header.getRecordId() ); |
| r.setOptions( header.getOptions() ); |
| return r; |
| } |
| else if ( header.getRecordId() >= EscherBlipRecord.RECORD_ID_START && header.getRecordId() <= EscherBlipRecord.RECORD_ID_END ) |
| { |
| EscherBlipRecord r; |
| if (header.getRecordId() == EscherBitmapBlip.RECORD_ID_DIB || |
| header.getRecordId() == EscherBitmapBlip.RECORD_ID_JPEG || |
| header.getRecordId() == EscherBitmapBlip.RECORD_ID_PNG) |
| { |
| r = new EscherBitmapBlip(); |
| } |
| else if (header.getRecordId() == EscherMetafileBlip.RECORD_ID_EMF || |
| header.getRecordId() == EscherMetafileBlip.RECORD_ID_WMF || |
| header.getRecordId() == EscherMetafileBlip.RECORD_ID_PICT) |
| { |
| r = new EscherMetafileBlip(); |
| } |
| else |
| { |
| r = new EscherBlipRecord(); |
| } |
| r.setRecordId( header.getRecordId() ); |
| r.setOptions( header.getOptions() ); |
| return r; |
| } |
| else |
| { |
| Constructor recordConstructor = (Constructor) recordsMap.get( new Short( header.getRecordId() ) ); |
| EscherRecord escherRecord = null; |
| if ( recordConstructor != null ) |
| { |
| try |
| { |
| escherRecord = (EscherRecord) recordConstructor.newInstance( new Object[]{} ); |
| escherRecord.setRecordId( header.getRecordId() ); |
| escherRecord.setOptions( header.getOptions() ); |
| } |
| catch ( Exception e ) |
| { |
| escherRecord = null; |
| } |
| } |
| return escherRecord == null ? new UnknownEscherRecord() : escherRecord; |
| } |
| } |
| |
| /** |
| * 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. |
| * |
| * @param records The records to convert |
| * @return The map containing the id/constructor pairs. |
| */ |
| private static Map recordsToMap( Class[] records ) |
| { |
| Map result = new HashMap(); |
| Constructor constructor; |
| |
| for ( int i = 0; i < records.length; i++ ) |
| { |
| Class record = null; |
| short sid = 0; |
| |
| record = records[i]; |
| try |
| { |
| sid = record.getField( "RECORD_ID" ).getShort( null ); |
| constructor = record.getConstructor( new Class[] |
| { |
| } ); |
| } |
| catch ( Exception illegalArgumentException ) |
| { |
| throw new RecordFormatException( |
| "Unable to determine record types" ); |
| } |
| result.put( new Short( sid ), constructor ); |
| } |
| return result; |
| } |
| |
| } |