From 124671715a04979f8fe55ab0bf601112a8569783 Mon Sep 17 00:00:00 2001 From: "Andrew C. Oliver" Date: Mon, 11 Nov 2002 01:34:01 +0000 Subject: [PATCH] event record factory git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@352913 13f79535-47bb-0310-9956-ffa450edef68 --- .classpath | 9 + .project | 17 + .../hssf/usermodel/examples/EventExample.java | 6 +- .../org/apache/poi/hssf/dev/EFBiffViewer.java | 1 + src/java/org/apache/poi/hssf/dev/EFHSSF.java | 1 + .../poi/hssf/eventmodel/ERFListener.java | 74 +++ .../hssf/eventmodel/EventRecordFactory.java | 504 ++++++++++++++++++ .../AbortableHSSFListener.java | 4 +- .../HSSFEventFactory.java | 4 +- .../HSSFListener.java | 4 +- .../HSSFRequest.java | 2 +- .../HSSFUserException.java | 2 +- .../package.html | 0 .../apache/poi/hssf/record/RecordFactory.java | 2 + .../eventmodel/TestEventRecordFactory.java | 176 ++++++ 15 files changed, 795 insertions(+), 11 deletions(-) create mode 100644 .classpath create mode 100644 .project create mode 100644 src/java/org/apache/poi/hssf/eventmodel/ERFListener.java create mode 100644 src/java/org/apache/poi/hssf/eventmodel/EventRecordFactory.java rename src/java/org/apache/poi/hssf/{eventmodel => eventusermodel}/AbortableHSSFListener.java (97%) rename src/java/org/apache/poi/hssf/{eventmodel => eventusermodel}/HSSFEventFactory.java (98%) rename src/java/org/apache/poi/hssf/{eventmodel => eventusermodel}/HSSFListener.java (97%) rename src/java/org/apache/poi/hssf/{eventmodel => eventusermodel}/HSSFRequest.java (99%) rename src/java/org/apache/poi/hssf/{eventmodel => eventusermodel}/HSSFUserException.java (99%) rename src/java/org/apache/poi/hssf/{eventmodel => eventusermodel}/package.html (100%) mode change 100755 => 100644 create mode 100644 src/testcases/org/apache/poi/hssf/eventmodel/TestEventRecordFactory.java diff --git a/.classpath b/.classpath new file mode 100644 index 0000000000..4dd30de565 --- /dev/null +++ b/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000000..c9ebc6d364 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + jakarta-poi + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/src/examples/src/org/apache/poi/hssf/usermodel/examples/EventExample.java b/src/examples/src/org/apache/poi/hssf/usermodel/examples/EventExample.java index b85a5883db..f550c28379 100644 --- a/src/examples/src/org/apache/poi/hssf/usermodel/examples/EventExample.java +++ b/src/examples/src/org/apache/poi/hssf/usermodel/examples/EventExample.java @@ -1,8 +1,8 @@ package org.apache.poi.hssf.usermodel.examples; -import org.apache.poi.hssf.eventmodel.HSSFEventFactory; -import org.apache.poi.hssf.eventmodel.HSSFListener; -import org.apache.poi.hssf.eventmodel.HSSFRequest; +import org.apache.poi.hssf.eventusermodel.HSSFEventFactory; +import org.apache.poi.hssf.eventusermodel.HSSFListener; +import org.apache.poi.hssf.eventusermodel.HSSFRequest; import org.apache.poi.hssf.record.*; import org.apache.poi.poifs.filesystem.POIFSFileSystem; diff --git a/src/java/org/apache/poi/hssf/dev/EFBiffViewer.java b/src/java/org/apache/poi/hssf/dev/EFBiffViewer.java index 6a93919293..8f4da19044 100644 --- a/src/java/org/apache/poi/hssf/dev/EFBiffViewer.java +++ b/src/java/org/apache/poi/hssf/dev/EFBiffViewer.java @@ -61,6 +61,7 @@ import java.io.IOException; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.hssf.eventmodel.*; +import org.apache.poi.hssf.eventusermodel.*; import org.apache.poi.hssf.record.Record; /** diff --git a/src/java/org/apache/poi/hssf/dev/EFHSSF.java b/src/java/org/apache/poi/hssf/dev/EFHSSF.java index 78b5be4562..6a493f9d95 100644 --- a/src/java/org/apache/poi/hssf/dev/EFHSSF.java +++ b/src/java/org/apache/poi/hssf/dev/EFHSSF.java @@ -63,6 +63,7 @@ import java.io.IOException; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.eventmodel.*; +import org.apache.poi.hssf.eventusermodel.*; import org.apache.poi.hssf.usermodel.*; /** diff --git a/src/java/org/apache/poi/hssf/eventmodel/ERFListener.java b/src/java/org/apache/poi/hssf/eventmodel/ERFListener.java new file mode 100644 index 0000000000..44edc4cce7 --- /dev/null +++ b/src/java/org/apache/poi/hssf/eventmodel/ERFListener.java @@ -0,0 +1,74 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.poi.hssf.eventmodel; + +import org.apache.poi.hssf.record.Record; + +/** + * An ERFListener is registered with the EventRecordFactory. + * An ERFListener listens for Records coming from the stream + * via the EventRecordFactory + * + * @see EventRecordFactory + * @author Andrew C. Oliver acoliver@apache.org + */ +public interface ERFListener +{ + /** + * Process a Record. This method is called by the + * EventRecordFactory when a record is returned. + * @return boolean specifying whether the effort was a success. + */ + public boolean processRecord(Record rec); +} diff --git a/src/java/org/apache/poi/hssf/eventmodel/EventRecordFactory.java b/src/java/org/apache/poi/hssf/eventmodel/EventRecordFactory.java new file mode 100644 index 0000000000..3d22913cfe --- /dev/null +++ b/src/java/org/apache/poi/hssf/eventmodel/EventRecordFactory.java @@ -0,0 +1,504 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.poi.hssf.eventmodel; + +import java.io.InputStream; +import java.io.IOException; + +import java.util.*; + +import java.lang.reflect.Constructor; + +import org.apache.poi.hssf.record.BOFRecord; +import org.apache.poi.hssf.record.BackupRecord; +import org.apache.poi.hssf.record.BlankRecord; +import org.apache.poi.hssf.record.BookBoolRecord; +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.CalcCountRecord; +import org.apache.poi.hssf.record.CalcModeRecord; +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.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.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.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.IndexRecord; +import org.apache.poi.hssf.record.InterfaceEndRecord; +import org.apache.poi.hssf.record.InterfaceHdrRecord; +import org.apache.poi.hssf.record.IterationRecord; +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.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.NumberRecord; +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; +import org.apache.poi.hssf.record.PrintGridlinesRecord; +import org.apache.poi.hssf.record.PrintHeadersRecord; +import org.apache.poi.hssf.record.PrintSetupRecord; +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.Record; +import org.apache.poi.hssf.record.RecordFormatException; +import org.apache.poi.hssf.record.RefModeRecord; +import org.apache.poi.hssf.record.RefreshAllRecord; +import org.apache.poi.hssf.record.RightMarginRecord; +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.SelectionRecord; +import org.apache.poi.hssf.record.StringRecord; +import org.apache.poi.hssf.record.StyleRecord; +import org.apache.poi.hssf.record.TabIdRecord; +import org.apache.poi.hssf.record.TopMarginRecord; +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.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.util.LittleEndian; + + +/** + * 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 + * to ensure that ContinueRecords are processed first. + * + * @author Andrew C. Oliver acoliver@apache.org + */ +public class EventRecordFactory +{ + 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, + BoolErrRecord.class, ExternSheetRecord.class, NameRecord.class, + LeftMarginRecord.class, RightMarginRecord.class, + TopMarginRecord.class, BottomMarginRecord.class, + PaletteRecord.class, StringRecord.class + }; + + } + private static Map recordsMap = recordsToMap(records); + + private static short[] sidscache; + + private List listeners; + + private boolean abortable; + + public EventRecordFactory() { + this(true); + } + + public EventRecordFactory(boolean abortable) { + this.abortable = abortable; + listeners = new ArrayList(recordsMap.size()); + + if (sidscache == null) { + sidscache = getAllKnownRecordSIDs(); + } + + } + + /** + * Register a listener for records. These can be for all records + * or just a subset. + * + * @param sids an array of Record.sid values identifying the records + * the listener will work with. Alternatively if this is "null" then + * all records are passed. + */ + public void registerListener(ERFListener listener, short[] sids) { + if (sids == null) + sids = sidscache; + ERFListener wrapped = new ListenerWrapper(listener, sids, abortable); + listeners.add(wrapped); + } + + /** + * used for unit tests to test the registration of record listeners. + * @return Iterator of ERFListeners + */ + protected Iterator listeners() { + return listeners.iterator(); + } + + /** + * sends the record event to all registered listeners. + * @param record the record to be thrown. + * @return boolean abort. If exitability is turned on this aborts + * out of the event loop should any listener specify to do so. + */ + private boolean throwRecordEvent(Record record) + { + Iterator i = listeners.iterator(); + + while (i.hasNext()) { + ((ERFListener) i.next()).processRecord(record); + } + return false; + } + + /** + * 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 void processRecords(InputStream in) + throws RecordFormatException + { + Record last_record = null; + + try + { + short rectype = 0; + + do + { + rectype = LittleEndian.readShort(in); + if (rectype != 0) + { + short recsize = LittleEndian.readShort(in); + byte[] data = new byte[ ( int ) recsize ]; + + in.read(data); + Record[] recs = createRecord(rectype, recsize, + data); // handle MulRK records + + if (recs.length > 1) + { + for (int k = 0; k < recs.length; k++) + { + if ( last_record != null ) { + if (throwRecordEvent(last_record) == false && abortable == true) { + last_record = null; + break; + } + } + // records.add( + // recs[ k ]); // these will be number records + last_record = + recs[ k ]; // do to keep the algorythm homogenous...you can't + } // actually continue a number record anyhow. + } + else + { + Record record = recs[ 0 ]; + + if (record != null) + { + if (rectype == ContinueRecord.sid) + { + if (last_record == null) + { + throw new RecordFormatException( + "First record is a ContinueRecord??"); + } + last_record.processContinueRecord(data); + } + else + { + if (last_record != null) { + if (throwRecordEvent(last_record) == false && abortable == true) { + last_record = null; + break; + } + } + + last_record = record; + + //records.add(record); + } + } + } + } + } + while (rectype != 0); + + if (last_record != null) { + throwRecordEvent(last_record); + } + } + catch (IOException e) + { + throw new RecordFormatException("Error reading bytes"); + } + + // Record[] retval = new Record[ records.size() ]; + // retval = ( Record [] ) records.toArray(retval); + + } + + public static Record [] createRecord(short rectype, short size, + byte [] data) + { + Record retval = null; + Record[] realretval = null; + + try + { + Constructor constructor = + ( Constructor ) recordsMap.get(new Short(rectype)); + + if (constructor != null) + { + retval = ( Record ) constructor.newInstance(new Object[] + { + new Short(rectype), new Short(size), data + }); + } + else + { + retval = new UnknownRecord(rectype, size, data); + } + } + catch (Exception introspectionException) + { + introspectionException.printStackTrace(); + throw new RecordFormatException( + "Unable to construct record instance, the following exception occured: " + introspectionException.getMessage()); + } + 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; + } + + 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; + } + + 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("sid").getShort(null); + constructor = record.getConstructor(new Class[] + { + short.class, short.class, byte [].class + }); + } + catch (Exception illegalArgumentException) + { + throw new RecordFormatException( + "Unable to determine record types"); + } + result.put(new Short(sid), constructor); + } + return result; + } + +} + +class ListenerWrapper implements ERFListener { + private ERFListener listener; + private short[] sids; + private boolean abortable; + + ListenerWrapper(ERFListener listener, short[] sids, boolean abortable) { + this.listener = listener; + this.sids = sids; + this.abortable = abortable; + } + + + public boolean processRecord(Record rec) + { + boolean result = false; + for (int k = 0; k < sids.length; k++) { + if (sids[k] == rec.getSid()) { + result = listener.processRecord(rec); + + if (abortable == true && result == false) { + break; + } + } + } + return result; + } +} diff --git a/src/java/org/apache/poi/hssf/eventmodel/AbortableHSSFListener.java b/src/java/org/apache/poi/hssf/eventusermodel/AbortableHSSFListener.java similarity index 97% rename from src/java/org/apache/poi/hssf/eventmodel/AbortableHSSFListener.java rename to src/java/org/apache/poi/hssf/eventusermodel/AbortableHSSFListener.java index 7c0b2696f1..2f3876e7b7 100644 --- a/src/java/org/apache/poi/hssf/eventmodel/AbortableHSSFListener.java +++ b/src/java/org/apache/poi/hssf/eventusermodel/AbortableHSSFListener.java @@ -53,10 +53,10 @@ * . */ -package org.apache.poi.hssf.eventmodel; +package org.apache.poi.hssf.eventusermodel; import org.apache.poi.hssf.record.Record; -import org.apache.poi.hssf.eventmodel.HSSFUserException; +import org.apache.poi.hssf.eventusermodel.HSSFUserException; /** * Interface for use with the HSSFRequest and HSSFEventFactory. Users should create diff --git a/src/java/org/apache/poi/hssf/eventmodel/HSSFEventFactory.java b/src/java/org/apache/poi/hssf/eventusermodel/HSSFEventFactory.java similarity index 98% rename from src/java/org/apache/poi/hssf/eventmodel/HSSFEventFactory.java rename to src/java/org/apache/poi/hssf/eventusermodel/HSSFEventFactory.java index 9c1f0bf243..56ac0c921c 100644 --- a/src/java/org/apache/poi/hssf/eventmodel/HSSFEventFactory.java +++ b/src/java/org/apache/poi/hssf/eventusermodel/HSSFEventFactory.java @@ -53,13 +53,13 @@ * . */ -package org.apache.poi.hssf.eventmodel; +package org.apache.poi.hssf.eventusermodel; import java.io.InputStream; import java.io.IOException; import org.apache.poi.util.LittleEndian; -import org.apache.poi.hssf.eventmodel.HSSFUserException; +import org.apache.poi.hssf.eventusermodel.HSSFUserException; import org.apache.poi.hssf.record.RecordFormatException; import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.RecordFactory; diff --git a/src/java/org/apache/poi/hssf/eventmodel/HSSFListener.java b/src/java/org/apache/poi/hssf/eventusermodel/HSSFListener.java similarity index 97% rename from src/java/org/apache/poi/hssf/eventmodel/HSSFListener.java rename to src/java/org/apache/poi/hssf/eventusermodel/HSSFListener.java index 09ac21c757..6c59c69307 100644 --- a/src/java/org/apache/poi/hssf/eventmodel/HSSFListener.java +++ b/src/java/org/apache/poi/hssf/eventusermodel/HSSFListener.java @@ -53,7 +53,7 @@ * . */ -package org.apache.poi.hssf.eventmodel; +package org.apache.poi.hssf.eventusermodel; import org.apache.poi.hssf.record.Record; @@ -64,7 +64,7 @@ import org.apache.poi.hssf.record.Record; * * @see org.apache.poi.hssf.eventmodel.HSSFEventFactory * @see org.apache.poi.hssf.eventmodel.HSSFRequest - * @author andy + * @author acoliver@apache.org */ public interface HSSFListener diff --git a/src/java/org/apache/poi/hssf/eventmodel/HSSFRequest.java b/src/java/org/apache/poi/hssf/eventusermodel/HSSFRequest.java similarity index 99% rename from src/java/org/apache/poi/hssf/eventmodel/HSSFRequest.java rename to src/java/org/apache/poi/hssf/eventusermodel/HSSFRequest.java index 4f01d305e6..be08b31397 100644 --- a/src/java/org/apache/poi/hssf/eventmodel/HSSFRequest.java +++ b/src/java/org/apache/poi/hssf/eventusermodel/HSSFRequest.java @@ -53,7 +53,7 @@ * . */ -package org.apache.poi.hssf.eventmodel; +package org.apache.poi.hssf.eventusermodel; import java.util.HashMap; import java.util.List; diff --git a/src/java/org/apache/poi/hssf/eventmodel/HSSFUserException.java b/src/java/org/apache/poi/hssf/eventusermodel/HSSFUserException.java similarity index 99% rename from src/java/org/apache/poi/hssf/eventmodel/HSSFUserException.java rename to src/java/org/apache/poi/hssf/eventusermodel/HSSFUserException.java index 8a0a688b8e..543b886673 100644 --- a/src/java/org/apache/poi/hssf/eventmodel/HSSFUserException.java +++ b/src/java/org/apache/poi/hssf/eventusermodel/HSSFUserException.java @@ -56,7 +56,7 @@ * University of Illinois, Urbana-Champaign. */ -package org.apache.poi.hssf.eventmodel; +package org.apache.poi.hssf.eventusermodel; /** *

This exception is provided as a way for API users to throw diff --git a/src/java/org/apache/poi/hssf/eventmodel/package.html b/src/java/org/apache/poi/hssf/eventusermodel/package.html old mode 100755 new mode 100644 similarity index 100% rename from src/java/org/apache/poi/hssf/eventmodel/package.html rename to src/java/org/apache/poi/hssf/eventusermodel/package.html diff --git a/src/java/org/apache/poi/hssf/record/RecordFactory.java b/src/java/org/apache/poi/hssf/record/RecordFactory.java index 29b9422df6..9d8b38b90c 100644 --- a/src/java/org/apache/poi/hssf/record/RecordFactory.java +++ b/src/java/org/apache/poi/hssf/record/RecordFactory.java @@ -68,6 +68,8 @@ import org.apache.poi.util.LittleEndian; * Title: Record Factory

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

* + * @deprecated use EventRecordFactory instead + * @see org.apache.poi.hssf.record.EventRecordFactory * @author Andrew C. Oliver (acoliver at apache dot org) * @author Marc Johnson (mjohnson at apache dot org) * @author Glen Stampoultzis (glens at apache.org) diff --git a/src/testcases/org/apache/poi/hssf/eventmodel/TestEventRecordFactory.java b/src/testcases/org/apache/poi/hssf/eventmodel/TestEventRecordFactory.java new file mode 100644 index 0000000000..992fd9cc46 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/eventmodel/TestEventRecordFactory.java @@ -0,0 +1,176 @@ +package org.apache.poi.hssf.eventmodel; + +import java.io.ByteArrayInputStream; +import java.io.EOFException; +import java.util.Iterator; + +import org.apache.poi.hssf.record.BOFRecord; +import org.apache.poi.hssf.record.EOFRecord; +import org.apache.poi.hssf.record.Record; + +import junit.framework.TestCase; + +/** + * enclosing_type describe the purpose here + * + * @author Andrew C. Oliver acoliver@apache.org + */ +public class TestEventRecordFactory extends TestCase +{ + boolean wascalled; + + private EventRecordFactory factory; + /** + * Constructor for TestEventRecordFactory. + * @param arg0 + */ + public TestEventRecordFactory(String arg0) + { + super(arg0); + } + + public static void main(String[] args) + { + junit.textui.TestRunner.run(TestEventRecordFactory.class); + } + + protected void setUp() throws Exception + { + super.setUp(); + factory = new EventRecordFactory(); + } + + protected void tearDown() throws Exception + { + super.tearDown(); + } + + /** + * tests that a listener can be registered and that once + * registered can be returned as expected. + */ + public void testRegisterListener() + { + factory.registerListener(new ERFListener() { + public boolean processRecord(Record rec) { + return true; + } + },null); + + Iterator i = factory.listeners(); + assertTrue("iterator must have one",i.hasNext()); + + factory.registerListener(new ERFListener() { + public boolean processRecord(Record rec) { + return true; + } + },null); + + i = factory.listeners(); + + i.next(); + assertTrue("iterator must have two",i.hasNext()); + factory = new EventRecordFactory(); + } + + /** + * tests that the records can be processed and properly return + * values. + */ + public void testProcessRecords() + { + byte[] bytes = null; + int offset = 0; + //boolean wascalled = false; + factory.registerListener(new ERFListener() { + public boolean processRecord(Record rec) { + wascalled = true; + assertTrue("must be BOFRecord got SID="+rec.getSid(), + (rec.getSid() == BOFRecord.sid)); + return true; + } + }, new short[] {BOFRecord.sid}); + + BOFRecord bof = new BOFRecord(); + bof.setBuild((short)0); + bof.setBuildYear((short)1999); + bof.setRequiredVersion(123); + bof.setType(BOFRecord.TYPE_WORKBOOK); + bof.setVersion((short)0x06); + bof.setHistoryBitMask(BOFRecord.HISTORY_MASK); + + EOFRecord eof = new EOFRecord(); + bytes = new byte[bof.getRecordSize() + eof.getRecordSize()]; + offset = bof.serialize(offset,bytes); + offset = eof.serialize(offset,bytes); + + factory.processRecords(new ByteArrayInputStream(bytes)); + assertTrue("The record listener must be called",wascalled); + } + + /** + * tests that the create record function returns a properly + * constructed record in the simple case. + */ + public void testCreateRecord() + { + byte[] bytes = null; + byte[] nbytes = null; + Record[] records = null; + BOFRecord bof = new BOFRecord(); + bof.setBuild((short)0); + bof.setBuildYear((short)1999); + bof.setRequiredVersion(123); + bof.setType(BOFRecord.TYPE_WORKBOOK); + bof.setVersion((short)0x06); + bof.setHistoryBitMask(BOFRecord.HISTORY_MASK); + + bytes = bof.serialize(); + nbytes = new byte[bytes.length - 4]; + System.arraycopy(bytes,4,nbytes,0,nbytes.length); + + records = factory.createRecord(bof.getSid(),(short)nbytes.length,nbytes); + + assertTrue("record.length must be 1, was ="+records.length,records.length == 1); + assertTrue("record is the same", compareRec(bof,records[0])); + + } + + /** + * Compare the serialized bytes of two records are equal + * @param first the first record to compare + * @param second the second record to compare + * @return boolean whether or not the record where equal + */ + private boolean compareRec(Record first, Record second) + { + boolean retval = true; + byte[] rec1 = first.serialize(); + byte[] rec2 = second.serialize(); + + if (rec1.length == rec2.length) { + for (int k=0; k