Index: C:\josh\client\poi\svn\trunk-h2/src/java/org/apache/poi/hssf/eventmodel/EventRecordFactory.java =================================================================== --- C:\josh\client\poi\svn\trunk-h2/src/java/org/apache/poi/hssf/eventmodel/EventRecordFactory.java (revision 652045) +++ C:\josh\client\poi\svn\trunk-h2/src/java/org/apache/poi/hssf/eventmodel/EventRecordFactory.java (working copy) @@ -19,11 +19,14 @@ import java.io.InputStream; import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.poi.hssf.record.BOFRecord; import org.apache.poi.hssf.record.BackupRecord; @@ -32,32 +35,49 @@ import org.apache.poi.hssf.record.BoolErrRecord; import org.apache.poi.hssf.record.BottomMarginRecord; import org.apache.poi.hssf.record.BoundSheetRecord; +import org.apache.poi.hssf.record.CFHeaderRecord; +import org.apache.poi.hssf.record.CFRuleRecord; +import org.apache.poi.hssf.record.CRNCountRecord; +import org.apache.poi.hssf.record.CRNRecord; import org.apache.poi.hssf.record.CalcCountRecord; import org.apache.poi.hssf.record.CalcModeRecord; +import org.apache.poi.hssf.record.ChartRecord; +import org.apache.poi.hssf.record.ChartTitleFormatRecord; import org.apache.poi.hssf.record.CodepageRecord; import org.apache.poi.hssf.record.ColumnInfoRecord; import org.apache.poi.hssf.record.ContinueRecord; import org.apache.poi.hssf.record.CountryRecord; import org.apache.poi.hssf.record.DBCellRecord; import org.apache.poi.hssf.record.DSFRecord; +import org.apache.poi.hssf.record.DVALRecord; +import org.apache.poi.hssf.record.DVRecord; import org.apache.poi.hssf.record.DateWindow1904Record; import org.apache.poi.hssf.record.DefaultColWidthRecord; import org.apache.poi.hssf.record.DefaultRowHeightRecord; import org.apache.poi.hssf.record.DeltaRecord; import org.apache.poi.hssf.record.DimensionsRecord; +import org.apache.poi.hssf.record.DrawingGroupRecord; +import org.apache.poi.hssf.record.DrawingRecord; +import org.apache.poi.hssf.record.DrawingSelectionRecord; import org.apache.poi.hssf.record.EOFRecord; import org.apache.poi.hssf.record.ExtSSTRecord; import org.apache.poi.hssf.record.ExtendedFormatRecord; import org.apache.poi.hssf.record.ExternSheetRecord; +import org.apache.poi.hssf.record.ExternalNameRecord; +import org.apache.poi.hssf.record.FilePassRecord; +import org.apache.poi.hssf.record.FileSharingRecord; import org.apache.poi.hssf.record.FnGroupCountRecord; import org.apache.poi.hssf.record.FontRecord; import org.apache.poi.hssf.record.FooterRecord; import org.apache.poi.hssf.record.FormatRecord; +import org.apache.poi.hssf.record.FormulaRecord; import org.apache.poi.hssf.record.GridsetRecord; import org.apache.poi.hssf.record.GutsRecord; import org.apache.poi.hssf.record.HCenterRecord; import org.apache.poi.hssf.record.HeaderRecord; import org.apache.poi.hssf.record.HideObjRecord; +import org.apache.poi.hssf.record.HorizontalPageBreakRecord; +import org.apache.poi.hssf.record.HyperlinkRecord; import org.apache.poi.hssf.record.IndexRecord; import org.apache.poi.hssf.record.InterfaceEndRecord; import org.apache.poi.hssf.record.InterfaceHdrRecord; @@ -65,14 +85,18 @@ import org.apache.poi.hssf.record.LabelRecord; import org.apache.poi.hssf.record.LabelSSTRecord; import org.apache.poi.hssf.record.LeftMarginRecord; +import org.apache.poi.hssf.record.LegendRecord; import org.apache.poi.hssf.record.MMSRecord; import org.apache.poi.hssf.record.MergeCellsRecord; import org.apache.poi.hssf.record.MulBlankRecord; import org.apache.poi.hssf.record.MulRKRecord; import org.apache.poi.hssf.record.NameRecord; +import org.apache.poi.hssf.record.NoteRecord; import org.apache.poi.hssf.record.NumberRecord; +import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.ObjectProtectRecord; +import org.apache.poi.hssf.record.PaletteRecord; import org.apache.poi.hssf.record.PaneRecord; -import org.apache.poi.hssf.record.PaletteRecord; import org.apache.poi.hssf.record.PasswordRecord; import org.apache.poi.hssf.record.PasswordRev4Record; import org.apache.poi.hssf.record.PrecisionRecord; @@ -82,6 +106,7 @@ import org.apache.poi.hssf.record.ProtectRecord; import org.apache.poi.hssf.record.ProtectionRev4Record; import org.apache.poi.hssf.record.RKRecord; +import org.apache.poi.hssf.record.RecalcIdRecord; import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.RecordFormatException; import org.apache.poi.hssf.record.RecordInputStream; @@ -91,29 +116,34 @@ import org.apache.poi.hssf.record.RowRecord; import org.apache.poi.hssf.record.SSTRecord; import org.apache.poi.hssf.record.SaveRecalcRecord; +import org.apache.poi.hssf.record.ScenarioProtectRecord; import org.apache.poi.hssf.record.SelectionRecord; +import org.apache.poi.hssf.record.SeriesRecord; +import org.apache.poi.hssf.record.SeriesTextRecord; import org.apache.poi.hssf.record.SharedFormulaRecord; import org.apache.poi.hssf.record.StringRecord; import org.apache.poi.hssf.record.StyleRecord; +import org.apache.poi.hssf.record.SupBookRecord; import org.apache.poi.hssf.record.TabIdRecord; +import org.apache.poi.hssf.record.TextObjectRecord; import org.apache.poi.hssf.record.TopMarginRecord; +import org.apache.poi.hssf.record.UncalcedRecord; import org.apache.poi.hssf.record.UnknownRecord; import org.apache.poi.hssf.record.UseSelFSRecord; import org.apache.poi.hssf.record.VCenterRecord; +import org.apache.poi.hssf.record.VerticalPageBreakRecord; import org.apache.poi.hssf.record.WSBoolRecord; import org.apache.poi.hssf.record.WindowOneRecord; import org.apache.poi.hssf.record.WindowProtectRecord; import org.apache.poi.hssf.record.WindowTwoRecord; import org.apache.poi.hssf.record.WriteAccessRecord; import org.apache.poi.hssf.record.WriteProtectRecord; -import org.apache.poi.hssf.record.FilePassRecord; -import org.apache.poi.hssf.record.NoteRecord; /** * Event-based record factory. As opposed to RecordFactory - * this refactored version throws record events as it comes - * accross the records. I throws the "lazily" one record behind + * this refactored version fires record events as it comes + * across the records. I throws the "lazily" one record behind * to ensure that ContinueRecords are processed first. * * @author Andrew C. Oliver (acoliver@apache.org) - probably to blame for the bugs (so yank his chain on the list) @@ -121,8 +151,7 @@ * @author Glen Stampoultzis (glens at apache.org) - methods taken from RecordFactory * @author Csaba Nagy (ncsaba at yahoo dot com) */ -public class EventRecordFactory -{ +public final class EventRecordFactory { /** * contains the classes for all the records we want to parse. @@ -160,7 +189,26 @@ TopMarginRecord.class, BottomMarginRecord.class, PaletteRecord.class, StringRecord.class, SharedFormulaRecord.class, WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class, - NoteRecord.class + NoteRecord.class, + + ObjectProtectRecord.class, ScenarioProtectRecord.class, + FileSharingRecord.class, ChartTitleFormatRecord.class, + DVRecord.class, DVALRecord.class, UncalcedRecord.class, + ChartRecord.class, LegendRecord.class, + SeriesRecord.class, SeriesTextRecord.class, + HyperlinkRecord.class, + ExternalNameRecord.class, + SupBookRecord.class, + CRNCountRecord.class, + CRNRecord.class, + CFHeaderRecord.class, + CFRuleRecord.class, + + FormulaRecord.class, + HorizontalPageBreakRecord.class, VerticalPageBreakRecord.class, + RecalcIdRecord.class, + ObjRecord.class, TextObjectRecord.class, + DrawingRecord.class, DrawingGroupRecord.class, DrawingSelectionRecord.class, }; } @@ -177,7 +225,7 @@ private static short[] sidscache; /** - * List of the listners that are registred. should all be ERFListener + * List of the listeners that are registered. should all be ERFListener */ private List listeners; @@ -422,17 +470,26 @@ { Map result = new HashMap(); Constructor constructor; + Set uniqueRecClasses = new HashSet(records.length * 3 / 2); for (int i = 0; i < records.length; i++) { - Class record = null; - short sid = 0; + short sid; - record = records[ i ]; + 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() + ")"); + } try { - sid = record.getField("sid").getShort(null); - constructor = record.getConstructor(new Class[] + sid = recClass.getField("sid").getShort(null); + constructor = recClass.getConstructor(new Class[] { RecordInputStream.class }); Index: C:\josh\client\poi\svn\trunk-h2/src/java/org/apache/poi/hssf/record/RecordFactory.java =================================================================== --- C:\josh\client\poi\svn\trunk-h2/src/java/org/apache/poi/hssf/record/RecordFactory.java (revision 652045) +++ C:\josh\client\poi\svn\trunk-h2/src/java/org/apache/poi/hssf/record/RecordFactory.java (working copy) @@ -1,4 +1,3 @@ - /* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -15,14 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - package org.apache.poi.hssf.record; import java.io.InputStream; -import java.lang.reflect.Constructor; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import org.apache.poi.hssf.eventmodel.EventRecordFactory; + /** * Title: Record Factory

* Description: Takes a stream and outputs an array of Record objects.

@@ -34,62 +34,10 @@ * @author Glen Stampoultzis (glens at apache.org) * @author Csaba Nagy (ncsaba at yahoo dot com) */ - public class RecordFactory { private static int NUM_RECORDS = 10000; - private static final Class[] records; - static { - records = new Class[] - { - BOFRecord.class, InterfaceHdrRecord.class, MMSRecord.class, - InterfaceEndRecord.class, WriteAccessRecord.class, - CodepageRecord.class, DSFRecord.class, TabIdRecord.class, - FnGroupCountRecord.class, WindowProtectRecord.class, - ProtectRecord.class, PasswordRecord.class, ProtectionRev4Record.class, - PasswordRev4Record.class, WindowOneRecord.class, BackupRecord.class, - HideObjRecord.class, DateWindow1904Record.class, - PrecisionRecord.class, RefreshAllRecord.class, BookBoolRecord.class, - FontRecord.class, FormatRecord.class, ExtendedFormatRecord.class, - StyleRecord.class, UseSelFSRecord.class, BoundSheetRecord.class, - CountryRecord.class, SSTRecord.class, ExtSSTRecord.class, - EOFRecord.class, IndexRecord.class, CalcModeRecord.class, - CalcCountRecord.class, RefModeRecord.class, IterationRecord.class, - DeltaRecord.class, SaveRecalcRecord.class, PrintHeadersRecord.class, - PrintGridlinesRecord.class, GridsetRecord.class, GutsRecord.class, - DefaultRowHeightRecord.class, WSBoolRecord.class, HeaderRecord.class, - FooterRecord.class, HCenterRecord.class, VCenterRecord.class, - PrintSetupRecord.class, DefaultColWidthRecord.class, - DimensionsRecord.class, RowRecord.class, LabelSSTRecord.class, - RKRecord.class, NumberRecord.class, DBCellRecord.class, - WindowTwoRecord.class, SelectionRecord.class, ContinueRecord.class, - LabelRecord.class, BlankRecord.class, ColumnInfoRecord.class, - MulRKRecord.class, MulBlankRecord.class, MergeCellsRecord.class, - FormulaRecord.class, BoolErrRecord.class, ExternSheetRecord.class, - NameRecord.class, LeftMarginRecord.class, RightMarginRecord.class, - TopMarginRecord.class, BottomMarginRecord.class, - DrawingRecord.class, DrawingGroupRecord.class, DrawingSelectionRecord.class, - ObjRecord.class, TextObjectRecord.class, - PaletteRecord.class, StringRecord.class, RecalcIdRecord.class, SharedFormulaRecord.class, - HorizontalPageBreakRecord.class, VerticalPageBreakRecord.class, - WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class, - NoteRecord.class, ObjectProtectRecord.class, ScenarioProtectRecord.class, - FileSharingRecord.class, ChartTitleFormatRecord.class, - DVRecord.class, DVALRecord.class, UncalcedRecord.class, - ChartRecord.class, LegendRecord.class, ChartTitleFormatRecord.class, - SeriesRecord.class, SeriesTextRecord.class, - HyperlinkRecord.class, - ExternalNameRecord.class, // TODO - same changes in non-@deprecated version of this class - SupBookRecord.class, - CRNCountRecord.class, - CRNRecord.class, - CFHeaderRecord.class, - CFRuleRecord.class, - }; - } - private static Map recordsMap = recordsToMap(records); - /** * changes the default capacity (10000) to handle larger files */ @@ -150,7 +98,7 @@ // 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 rememeber the position of the continue record. + //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 && @@ -183,125 +131,11 @@ public static Record [] createRecord(RecordInputStream in) { - Record retval; - Record[] realretval = null; - - try - { - Constructor constructor = - ( Constructor ) recordsMap.get(new Short(in.getSid())); - - if (constructor != null) - { - retval = ( Record ) constructor.newInstance(new Object[] - { - in - }); - } - else - { - retval = new UnknownRecord(in); - } - } - catch (Exception introspectionException) - { - throw new RecordFormatException("Unable to construct record instance",introspectionException); - } - if (retval instanceof RKRecord) - { - RKRecord rk = ( RKRecord ) retval; - NumberRecord num = new NumberRecord(); - - num.setColumn(rk.getColumn()); - num.setRow(rk.getRow()); - num.setXFIndex(rk.getXFIndex()); - num.setValue(rk.getRKNumber()); - retval = num; - } - else if (retval instanceof DBCellRecord) - { - retval = null; - } - else if (retval instanceof MulRKRecord) - { - MulRKRecord mrk = ( MulRKRecord ) retval; - - realretval = 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)); - realretval[ k ] = nr; - } - } - else if (retval instanceof MulBlankRecord) - { - MulBlankRecord mb = ( MulBlankRecord ) retval; - - realretval = 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)); - realretval[ k ] = br; - } - } - if (realretval == null) - { - realretval = new Record[ 1 ]; - realretval[ 0 ] = retval; - } - return realretval; + return EventRecordFactory.createRecord(in); } public static short [] getAllKnownRecordSIDs() { - short[] results = new short[ recordsMap.size() ]; - int i = 0; - - for (Iterator iterator = recordsMap.keySet().iterator(); - iterator.hasNext(); ) - { - Short sid = ( Short ) iterator.next(); - - results[ i++ ] = sid.shortValue(); - } - return results; + return EventRecordFactory.getAllKnownRecordSIDs(); } - - private static Map recordsToMap(Class [] records) - { - Map result = new HashMap(); - Constructor constructor; - - for (int i = 0; i < records.length; i++) - { - Class record; - short sid; - - record = records[ i ]; - try - { - sid = record.getField("sid").getShort(null); - constructor = record.getConstructor(new Class[] - { - RecordInputStream.class - }); - } - catch (Exception illegalArgumentException) - { - throw new RecordFormatException( - "Unable to determine record types", illegalArgumentException); - } - result.put(new Short(sid), constructor); - } - return result; - } }