diff --git a/src/java/org/apache/poi/hssf/record/RecordFactory.java b/src/java/org/apache/poi/hssf/record/RecordFactory.java index 20c8b27e0..6f03c2c11 100644 --- a/src/java/org/apache/poi/hssf/record/RecordFactory.java +++ b/src/java/org/apache/poi/hssf/record/RecordFactory.java @@ -43,147 +43,147 @@ import java.util.Set; public final class RecordFactory { private static final int NUM_RECORDS = 512; - private static final Class[] CONSTRUCTOR_ARGS = { RecordInputStream.class, }; + private static final Class[] CONSTRUCTOR_ARGS = { RecordInputStream.class, }; /** - * contains the classes for all the records we want to parse.
- * Note - this most but not *every* subclass of Record. - */ - private static final Class[] records = { - BackupRecord.class, - BlankRecord.class, - BOFRecord.class, - BookBoolRecord.class, - BoolErrRecord.class, - BottomMarginRecord.class, - BoundSheetRecord.class, - CalcCountRecord.class, - CalcModeRecord.class, - CFHeaderRecord.class, - CFRuleRecord.class, - ChartRecord.class, - ChartTitleFormatRecord.class, - CodepageRecord.class, - ColumnInfoRecord.class, - ContinueRecord.class, - CountryRecord.class, - CRNCountRecord.class, - CRNRecord.class, - DateWindow1904Record.class, - DBCellRecord.class, - DefaultColWidthRecord.class, - DefaultRowHeightRecord.class, - DeltaRecord.class, - DimensionsRecord.class, - DrawingGroupRecord.class, - DrawingRecord.class, - DrawingSelectionRecord.class, - DSFRecord.class, - DVALRecord.class, - DVRecord.class, - EOFRecord.class, - ExtendedFormatRecord.class, - ExternalNameRecord.class, - ExternSheetRecord.class, - ExtSSTRecord.class, - FilePassRecord.class, - FileSharingRecord.class, - FnGroupCountRecord.class, - FontRecord.class, - FooterRecord.class, - FormatRecord.class, - FormulaRecord.class, - GridsetRecord.class, - GutsRecord.class, - HCenterRecord.class, - HeaderRecord.class, - HideObjRecord.class, - HorizontalPageBreakRecord.class, - HyperlinkRecord.class, - IndexRecord.class, - InterfaceEndRecord.class, - InterfaceHdrRecord.class, - IterationRecord.class, - LabelRecord.class, - LabelSSTRecord.class, - LeftMarginRecord.class, - LegendRecord.class, - MergeCellsRecord.class, - MMSRecord.class, - MulBlankRecord.class, - MulRKRecord.class, - NameRecord.class, - NoteRecord.class, - NumberRecord.class, - ObjectProtectRecord.class, - ObjRecord.class, - PaletteRecord.class, - PaneRecord.class, - PasswordRecord.class, - PasswordRev4Record.class, - PrecisionRecord.class, - PrintGridlinesRecord.class, - PrintHeadersRecord.class, - PrintSetupRecord.class, - ProtectionRev4Record.class, - ProtectRecord.class, - RecalcIdRecord.class, - RefModeRecord.class, - RefreshAllRecord.class, - RightMarginRecord.class, - RKRecord.class, - RowRecord.class, - SaveRecalcRecord.class, - ScenarioProtectRecord.class, - SelectionRecord.class, - SeriesRecord.class, - SeriesTextRecord.class, - SharedFormulaRecord.class, - SSTRecord.class, - StringRecord.class, - StyleRecord.class, - SupBookRecord.class, - TabIdRecord.class, - TableRecord.class, - TextObjectRecord.class, - TopMarginRecord.class, - UncalcedRecord.class, - UseSelFSRecord.class, - VCenterRecord.class, - VerticalPageBreakRecord.class, - WindowOneRecord.class, - WindowProtectRecord.class, - WindowTwoRecord.class, - WriteAccessRecord.class, - WriteProtectRecord.class, - WSBoolRecord.class, - }; - - /** - * cache of the recordsToMap(); - */ - private static Map recordsMap = recordsToMap(records); + * contains the classes for all the records we want to parse.
+ * Note - this most but not *every* subclass of Record. + */ + private static final Class[] records = { + BackupRecord.class, + BlankRecord.class, + BOFRecord.class, + BookBoolRecord.class, + BoolErrRecord.class, + BottomMarginRecord.class, + BoundSheetRecord.class, + CalcCountRecord.class, + CalcModeRecord.class, + CFHeaderRecord.class, + CFRuleRecord.class, + ChartRecord.class, + ChartTitleFormatRecord.class, + CodepageRecord.class, + ColumnInfoRecord.class, + ContinueRecord.class, + CountryRecord.class, + CRNCountRecord.class, + CRNRecord.class, + DateWindow1904Record.class, + DBCellRecord.class, + DefaultColWidthRecord.class, + DefaultRowHeightRecord.class, + DeltaRecord.class, + DimensionsRecord.class, + DrawingGroupRecord.class, + DrawingRecord.class, + DrawingSelectionRecord.class, + DSFRecord.class, + DVALRecord.class, + DVRecord.class, + EOFRecord.class, + ExtendedFormatRecord.class, + ExternalNameRecord.class, + ExternSheetRecord.class, + ExtSSTRecord.class, + FilePassRecord.class, + FileSharingRecord.class, + FnGroupCountRecord.class, + FontRecord.class, + FooterRecord.class, + FormatRecord.class, + FormulaRecord.class, + GridsetRecord.class, + GutsRecord.class, + HCenterRecord.class, + HeaderRecord.class, + HideObjRecord.class, + HorizontalPageBreakRecord.class, + HyperlinkRecord.class, + IndexRecord.class, + InterfaceEndRecord.class, + InterfaceHdrRecord.class, + IterationRecord.class, + LabelRecord.class, + LabelSSTRecord.class, + LeftMarginRecord.class, + LegendRecord.class, + MergeCellsRecord.class, + MMSRecord.class, + MulBlankRecord.class, + MulRKRecord.class, + NameRecord.class, + NoteRecord.class, + NumberRecord.class, + ObjectProtectRecord.class, + ObjRecord.class, + PaletteRecord.class, + PaneRecord.class, + PasswordRecord.class, + PasswordRev4Record.class, + PrecisionRecord.class, + PrintGridlinesRecord.class, + PrintHeadersRecord.class, + PrintSetupRecord.class, + ProtectionRev4Record.class, + ProtectRecord.class, + RecalcIdRecord.class, + RefModeRecord.class, + RefreshAllRecord.class, + RightMarginRecord.class, + RKRecord.class, + RowRecord.class, + SaveRecalcRecord.class, + ScenarioProtectRecord.class, + SelectionRecord.class, + SeriesRecord.class, + SeriesTextRecord.class, + SharedFormulaRecord.class, + SSTRecord.class, + StringRecord.class, + StyleRecord.class, + SupBookRecord.class, + TabIdRecord.class, + TableRecord.class, + TextObjectRecord.class, + TopMarginRecord.class, + UncalcedRecord.class, + UseSelFSRecord.class, + VCenterRecord.class, + VerticalPageBreakRecord.class, + WindowOneRecord.class, + WindowProtectRecord.class, + WindowTwoRecord.class, + WriteAccessRecord.class, + WriteProtectRecord.class, + WSBoolRecord.class, + }; + + /** + * cache of the recordsToMap(); + */ + private static Map recordsMap = recordsToMap(records); private static short[] _allKnownRecordSIDs; - - /** - * create a record, if there are MUL records than multiple records - * are returned digested into the non-mul form. - */ - public static Record [] createRecord(RecordInputStream in) { - Constructor constructor = (Constructor) recordsMap.get(new Short(in.getSid())); + + /** + * create a record, if there are MUL records than multiple records + * are returned digested into the non-mul form. + */ + public static Record [] createRecord(RecordInputStream in) { + Constructor constructor = (Constructor) recordsMap.get(new Short(in.getSid())); - if (constructor == null) { - return new Record[] { new UnknownRecord(in), }; - } - - Record retval; + if (constructor == null) { + return new Record[] { new UnknownRecord(in), }; + } + + Record retval; - try { - retval = ( Record ) constructor.newInstance(new Object[] { in }); - } catch (InvocationTargetException e) { - throw new RecordFormatException("Unable to construct record instance" , e.getTargetException()); - } catch (IllegalArgumentException e) { + try { + retval = ( Record ) constructor.newInstance(new Object[] { in }); + } catch (InvocationTargetException e) { + throw new RecordFormatException("Unable to construct record instance" , e.getTargetException()); + } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (InstantiationException e) { throw new RuntimeException(e); @@ -191,184 +191,182 @@ public final class RecordFactory { throw new RuntimeException(e); } - if (retval instanceof RKRecord) { - // RK record is a slightly smaller alternative to NumberRecord - // POI likes NumberRecord better - RKRecord rk = ( RKRecord ) retval; - NumberRecord num = new NumberRecord(); + if (retval instanceof RKRecord) { + // RK record is a slightly smaller alternative to NumberRecord + // POI likes NumberRecord better + RKRecord rk = ( RKRecord ) retval; + NumberRecord num = new NumberRecord(); - num.setColumn(rk.getColumn()); - num.setRow(rk.getRow()); - num.setXFIndex(rk.getXFIndex()); - num.setValue(rk.getRKNumber()); - return new Record[] { num, }; - } - if (retval instanceof DBCellRecord) { - // Not needed by POI. Regenerated from scratch by POI when spreadsheet is written - return new Record[] { null, }; - } + num.setColumn(rk.getColumn()); + num.setRow(rk.getRow()); + num.setXFIndex(rk.getXFIndex()); + num.setValue(rk.getRKNumber()); + return new Record[] { num, }; + } + if (retval instanceof DBCellRecord) { + // Not needed by POI. Regenerated from scratch by POI when spreadsheet is written + return new Record[] { null, }; + } // expand multiple records where necessary - if (retval instanceof MulRKRecord) { - MulRKRecord mrk = ( MulRKRecord ) retval; + if (retval instanceof MulRKRecord) { + MulRKRecord mrk = ( MulRKRecord ) retval; - Record[] mulRecs = new Record[ mrk.getNumColumns() ]; - for (int k = 0; k < mrk.getNumColumns(); k++) { - NumberRecord nr = new NumberRecord(); + Record[] mulRecs = new Record[ mrk.getNumColumns() ]; + for (int k = 0; k < mrk.getNumColumns(); k++) { + NumberRecord nr = new NumberRecord(); - nr.setColumn(( short ) (k + mrk.getFirstColumn())); - nr.setRow(mrk.getRow()); - nr.setXFIndex(mrk.getXFAt(k)); - nr.setValue(mrk.getRKNumberAt(k)); - mulRecs[ k ] = nr; - } - return mulRecs; - } - if (retval instanceof MulBlankRecord) { - MulBlankRecord mb = ( MulBlankRecord ) retval; + nr.setColumn(( short ) (k + mrk.getFirstColumn())); + nr.setRow(mrk.getRow()); + nr.setXFIndex(mrk.getXFAt(k)); + nr.setValue(mrk.getRKNumberAt(k)); + mulRecs[ k ] = nr; + } + return mulRecs; + } + if (retval instanceof MulBlankRecord) { + MulBlankRecord mb = ( MulBlankRecord ) retval; - Record[] mulRecs = new Record[ mb.getNumColumns() ]; - for (int k = 0; k < mb.getNumColumns(); k++) { - BlankRecord br = new BlankRecord(); + Record[] mulRecs = new Record[ mb.getNumColumns() ]; + for (int k = 0; k < mb.getNumColumns(); k++) { + BlankRecord br = new BlankRecord(); - br.setColumn(( short ) (k + mb.getFirstColumn())); - br.setRow(mb.getRow()); - br.setXFIndex(mb.getXFAt(k)); - mulRecs[ k ] = br; - } - return mulRecs; - } - return new Record[] { retval, }; - } + br.setColumn(( short ) (k + mb.getFirstColumn())); + br.setRow(mb.getRow()); + br.setXFIndex(mb.getXFAt(k)); + mulRecs[ k ] = br; + } + return mulRecs; + } + return new Record[] { retval, }; + } - /** - * @return an array of all the SIDS for all known records - */ - public static short[] getAllKnownRecordSIDs() { - if (_allKnownRecordSIDs == null) { - short[] results = new short[ recordsMap.size() ]; - int i = 0; + /** + * @return an array of all the SIDS for all known records + */ + public static short[] getAllKnownRecordSIDs() { + if (_allKnownRecordSIDs == null) { + short[] results = new short[ recordsMap.size() ]; + int i = 0; - for (Iterator iterator = recordsMap.keySet().iterator(); iterator.hasNext(); ) { - Short sid = (Short) iterator.next(); + for (Iterator iterator = recordsMap.keySet().iterator(); iterator.hasNext(); ) { + Short sid = (Short) iterator.next(); - results[i++] = sid.shortValue(); - } - Arrays.sort(results); + results[i++] = sid.shortValue(); + } + Arrays.sort(results); _allKnownRecordSIDs = results; } return (short[]) _allKnownRecordSIDs.clone(); - } + } - /** - * gets the record constructors and sticks them in the map by SID - * @return map of SIDs to short,short,byte[] constructors for Record classes - * most of org.apache.poi.hssf.record.* - */ - private static Map recordsToMap(Class [] records) { - Map result = new HashMap(); - Set uniqueRecClasses = new HashSet(records.length * 3 / 2); + /** + * gets the record constructors and sticks them in the map by SID + * @return map of SIDs to short,short,byte[] constructors for Record classes + * most of org.apache.poi.hssf.record.* + */ + private static Map recordsToMap(Class [] records) { + Map result = new HashMap(); + Set uniqueRecClasses = new HashSet(records.length * 3 / 2); - for (int i = 0; i < records.length; i++) { + for (int i = 0; i < records.length; i++) { - Class recClass = records[ i ]; - String cn = recClass.getName(); - System.out.println(cn.substring(cn.lastIndexOf('.')+1) + ".class,"); - if(!Record.class.isAssignableFrom(recClass)) { - throw new RuntimeException("Invalid record sub-class (" + cn + ")"); - } - if(Modifier.isAbstract(recClass.getModifiers())) { - throw new RuntimeException("Invalid record class (" + cn + ") - must not be abstract"); - } - if(!uniqueRecClasses.add(recClass)) { - throw new RuntimeException("duplicate record class (" + cn + ")"); - } - - short sid; - Constructor constructor; - try { - sid = recClass.getField("sid").getShort(null); - constructor = recClass.getConstructor(CONSTRUCTOR_ARGS); - } catch (Exception illegalArgumentException) { - throw new RecordFormatException( - "Unable to determine record types"); - } - Short key = new Short(sid); + Class recClass = records[ i ]; + if(!Record.class.isAssignableFrom(recClass)) { + throw new RuntimeException("Invalid record sub-class (" + recClass.getName() + ")"); + } + if(Modifier.isAbstract(recClass.getModifiers())) { + throw new RuntimeException("Invalid record class (" + recClass.getName() + ") - must not be abstract"); + } + if(!uniqueRecClasses.add(recClass)) { + throw new RuntimeException("duplicate record class (" + recClass.getName() + ")"); + } + + short sid; + Constructor constructor; + try { + sid = recClass.getField("sid").getShort(null); + constructor = recClass.getConstructor(CONSTRUCTOR_ARGS); + } catch (Exception illegalArgumentException) { + throw new RecordFormatException( + "Unable to determine record types"); + } + Short key = new Short(sid); if (result.containsKey(key)) { - Class prev = (Class)result.get(key); - throw new RuntimeException("duplicate record sid 0x" + Integer.toHexString(sid).toUpperCase() - + " for classes (" + cn + ") and (" + prev.getName() + ")"); - } - result.put(key, constructor); - } - return result; - } + Class prev = (Class)result.get(key); + throw new RuntimeException("duplicate record sid 0x" + Integer.toHexString(sid).toUpperCase() + + " for classes (" + recClass.getName() + ") and (" + prev.getName() + ")"); + } + result.put(key, constructor); + } + return result; + } - /** - * Create an array of records from an input stream - * - * @param in the InputStream from which the records will be obtained - * - * @return an array of Records created from the InputStream - * - * @exception RecordFormatException on error processing the InputStream - */ - public static List createRecords(InputStream in) throws RecordFormatException { + /** + * Create an array of records from an input stream + * + * @param in the InputStream from which the records will be obtained + * + * @return an array of Records created from the InputStream + * + * @exception RecordFormatException on error processing the InputStream + */ + public static List createRecords(InputStream in) throws RecordFormatException { - List records = new ArrayList(NUM_RECORDS); + List records = new ArrayList(NUM_RECORDS); - RecordInputStream recStream = new RecordInputStream(in); - DrawingRecord lastDrawingRecord = new DrawingRecord( ); - Record lastRecord = null; - while (recStream.hasNextRecord()) { - recStream.nextRecord(); - if (recStream.getSid() != 0) { - Record[] recs = createRecord(recStream); // handle MulRK records + RecordInputStream recStream = new RecordInputStream(in); + DrawingRecord lastDrawingRecord = new DrawingRecord( ); + Record lastRecord = null; + while (recStream.hasNextRecord()) { + recStream.nextRecord(); + if (recStream.getSid() != 0) { + Record[] recs = createRecord(recStream); // handle MulRK records - if (recs.length > 1) { - for (int k = 0; k < recs.length; k++) { - records.add(recs[ k ]); // these will be number records - } - } else { - Record record = recs[ 0 ]; + if (recs.length > 1) { + for (int k = 0; k < recs.length; k++) { + records.add(recs[ k ]); // these will be number records + } + } else { + Record record = recs[ 0 ]; - if (record != null) { - if (record.getSid() == DrawingGroupRecord.sid - && lastRecord instanceof DrawingGroupRecord) { - DrawingGroupRecord lastDGRecord = (DrawingGroupRecord) lastRecord; - lastDGRecord.join((AbstractEscherHolderRecord) record); - } else if (record.getSid() == ContinueRecord.sid && - ((lastRecord instanceof ObjRecord) || (lastRecord instanceof TextObjectRecord))) { - // Drawing records have a very strange continue behaviour. - //There can actually be OBJ records mixed between the continues. - lastDrawingRecord.processContinueRecord( ((ContinueRecord)record).getData() ); - //we must remember the position of the continue record. - //in the serialization procedure the original structure of records must be preserved - records.add(record); - } else if (record.getSid() == ContinueRecord.sid && - (lastRecord instanceof DrawingGroupRecord)) { - ((DrawingGroupRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData()); - } else if (record.getSid() == ContinueRecord.sid && - (lastRecord instanceof StringRecord)) { - ((StringRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData()); - } else if (record.getSid() == ContinueRecord.sid) { - if (lastRecord instanceof UnknownRecord) { - //Gracefully handle records that we dont know about, - //that happen to be continued - records.add(record); - } else - throw new RecordFormatException("Unhandled Continue Record"); - } else { - lastRecord = record; - if (record instanceof DrawingRecord) { + if (record != null) { + if (record.getSid() == DrawingGroupRecord.sid + && lastRecord instanceof DrawingGroupRecord) { + DrawingGroupRecord lastDGRecord = (DrawingGroupRecord) lastRecord; + lastDGRecord.join((AbstractEscherHolderRecord) record); + } else if (record.getSid() == ContinueRecord.sid && + ((lastRecord instanceof ObjRecord) || (lastRecord instanceof TextObjectRecord))) { + // Drawing records have a very strange continue behaviour. + //There can actually be OBJ records mixed between the continues. + lastDrawingRecord.processContinueRecord( ((ContinueRecord)record).getData() ); + //we must remember the position of the continue record. + //in the serialization procedure the original structure of records must be preserved + records.add(record); + } else if (record.getSid() == ContinueRecord.sid && + (lastRecord instanceof DrawingGroupRecord)) { + ((DrawingGroupRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData()); + } else if (record.getSid() == ContinueRecord.sid && + (lastRecord instanceof StringRecord)) { + ((StringRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData()); + } else if (record.getSid() == ContinueRecord.sid) { + if (lastRecord instanceof UnknownRecord) { + //Gracefully handle records that we dont know about, + //that happen to be continued + records.add(record); + } else + throw new RecordFormatException("Unhandled Continue Record"); + } else { + lastRecord = record; + if (record instanceof DrawingRecord) { lastDrawingRecord = (DrawingRecord) record; } - records.add(record); - } - } - } - } - } - return records; - } + records.add(record); + } + } + } + } + } + return records; + } }