From: Andrew C. Oliver Date: Mon, 11 Nov 2002 01:34:01 +0000 (+0000) Subject: event record factory X-Git-Tag: REL_1_10~96 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=124671715a04979f8fe55ab0bf601112a8569783;p=poi.git event record factory git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@352913 13f79535-47bb-0310-9956-ffa450edef68 --- 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/AbortableHSSFListener.java b/src/java/org/apache/poi/hssf/eventmodel/AbortableHSSFListener.java deleted file mode 100644 index 7c0b2696f1..0000000000 --- a/src/java/org/apache/poi/hssf/eventmodel/AbortableHSSFListener.java +++ /dev/null @@ -1,106 +0,0 @@ - -/* ==================================================================== - * 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; -import org.apache.poi.hssf.eventmodel.HSSFUserException; - -/** - * Interface for use with the HSSFRequest and HSSFEventFactory. Users should create - * a listener supporting this interface and register it with the HSSFRequest (associating - * it with Record SID's). - * - * @see org.apache.poi.hssf.eventmodel.HSSFEventFactory - * @see org.apache.poi.hssf.eventmodel.HSSFRequest - * @see org.apache.poi.hssf.HSSFUserException - * - * @author Carey Sublette (careysub@earthling.net) - * - */ - -public abstract class AbortableHSSFListener implements HSSFListener -{ - /** - * This method, inherited from HSSFListener is implemented as a stub. - * It is never called by HSSFEventFActory or HSSFRequest. - * - */ - - public void processRecord(Record record) - { - } - - /** - * Process an HSSF Record. Called when a record occurs in an HSSF file. - * Provides two options for halting the processing of the HSSF file. - * - * The return value provides a means of non-error termination with a - * user-defined result code. A value of zero must be returned to - * continue processing, any other value will halt processing by - * HSSFEventFactory with the code being passed back by - * its abortable process events methods. - * - * Error termination can be done by throwing the HSSFUserException. - * - * Note that HSSFEventFactory will not call the inherited process - * - * @return result code of zero for continued processing. - * - * @throws HSSFUserException User code can throw this to abort - * file processing by HSSFEventFactory and return diagnostic information. - */ - public abstract short abortableProcessRecord(Record record) throws HSSFUserException; -} 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/HSSFEventFactory.java b/src/java/org/apache/poi/hssf/eventmodel/HSSFEventFactory.java deleted file mode 100644 index 9c1f0bf243..0000000000 --- a/src/java/org/apache/poi/hssf/eventmodel/HSSFEventFactory.java +++ /dev/null @@ -1,270 +0,0 @@ - -/* ==================================================================== - * 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 org.apache.poi.util.LittleEndian; -import org.apache.poi.hssf.eventmodel.HSSFUserException; -import org.apache.poi.hssf.record.RecordFormatException; -import org.apache.poi.hssf.record.Record; -import org.apache.poi.hssf.record.RecordFactory; -import org.apache.poi.hssf.record.ContinueRecord; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; - -/** - * Low level event based HSSF reader. Pass either a DocumentInputStream to - * process events along with a request object or pass a POIFS POIFSFileSystem to - * processWorkbookEvents along with a request. - * - * This will cause your file to be processed a record at a time. Each record with - * a static id matching one that you have registed in your HSSFRequest will be passed - * to your associated HSSFListener. - * - * @see org.apache.poi.hssf.dev.EFHSSF - * - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Carey Sublette (careysub@earthling.net) - */ - -public class HSSFEventFactory -{ - /** Creates a new instance of HSSFEventFactory */ - - public HSSFEventFactory() - { - } - - /** - * Processes a file into essentially record events. - * - * @param req an Instance of HSSFRequest which has your registered listeners - * @param fs a POIFS filesystem containing your workbook - */ - - public void processWorkbookEvents(HSSFRequest req, POIFSFileSystem fs) - throws IOException - { - InputStream in = fs.createDocumentInputStream("Workbook"); - - processEvents(req, in); - } - - /** - * Processes a file into essentially record events. - * - * @param req an Instance of HSSFRequest which has your registered listeners - * @param fs a POIFS filesystem containing your workbook - * @return numeric user-specified result code. - */ - - public short abortableProcessWorkbookEvents(HSSFRequest req, POIFSFileSystem fs) - throws IOException, HSSFUserException - { - InputStream in = fs.createDocumentInputStream("Workbook"); - return abortableProcessEvents(req, in); - } - - /** - * Processes a DocumentInputStream into essentially Record events. - * - * If an AbortableHSSFListener causes a halt to processing during this call - * the method will return just as with abortableProcessEvents, but no - * user code or HSSFUserException will be passed back. - * - * @see org.apache.poi.poifs.filesystem.POIFSFileSystem#createDocumentInputStream(String) - * @param req an Instance of HSSFRequest which has your registered listeners - * @param in a DocumentInputStream obtained from POIFS's POIFSFileSystem object - */ - - public void processEvents(HSSFRequest req, InputStream in) - throws IOException - { - try - { - genericProcessEvents(req, in); - } - catch (HSSFUserException hue) - {/*If an HSSFUserException user exception is thrown, ignore it.*/ } - } - - - /** - * Processes a DocumentInputStream into essentially Record events. - * - * @see org.apache.poi.poifs.filesystem.POIFSFileSystem#createDocumentInputStream(String) - * @param req an Instance of HSSFRequest which has your registered listeners - * @param in a DocumentInputStream obtained from POIFS's POIFSFileSystem object - * @return numeric user-specified result code. - */ - - public short abortableProcessEvents(HSSFRequest req, InputStream in) - throws IOException, HSSFUserException - { - return genericProcessEvents(req, in); - } - - /** - * Processes a DocumentInputStream into essentially Record events. - * - * @see org.apache.poi.poifs.filesystem.POIFSFileSystem#createDocumentInputStream(String) - * @param req an Instance of HSSFRequest which has your registered listeners - * @param in a DocumentInputStream obtained from POIFS's POIFSFileSystem object - * @param in a DocumentInputStream obtained from POIFS's POIFSFileSystem object - * @return numeric user-specified result code. - */ - - protected short genericProcessEvents(HSSFRequest req, InputStream in) - throws IOException, HSSFUserException - { - short userCode = 0; - - short sid = 0; - process: - try - { - byte[] sidbytes = new byte[ 2 ]; - int bytesread = in.read(sidbytes); - Record rec = null; - - while (bytesread > 0) - { - - sid = LittleEndian.getShort(sidbytes); - - // - // for some reasons we have to make the workbook to be at least 4096 bytes - // but if we have such workbook we fill the end of it with zeros (many zeros) - // - // it is not good: - // if the length( all zero records ) % 4 = 1 - // e.g.: any zero record would be readed as 4 bytes at once ( 2 - id and 2 - size ). - // And the last 1 byte will be readed WRONG ( the id must be 2 bytes ) - // - // So we should better to check if the sid is zero and not to read more data - // The zero sid shows us that rest of the stream data is a fake to make workbook - // certain size - // - if ( sid == 0 ) - break; - - - if ((rec != null) && (sid != ContinueRecord.sid)) - { - userCode = req.processRecord(rec); - if (userCode != 0) break process; - } - if (sid != ContinueRecord.sid) - { - short size = LittleEndian.readShort(in); - byte[] data = new byte[ size ]; - - if (data.length > 0) - { - in.read(data); - } - System.out.println("creating "+sid); - Record[] recs = RecordFactory.createRecord(sid, size, - data); - - if (recs.length > 1) - { // we know that the multiple - for (int k = 0; k < (recs.length - 1); k++) - { // record situations do not - userCode = req.processRecord( - recs[ k ]); // contain continue records - if (userCode != 0) break process; - } - } - rec = recs[ recs.length - 1 ]; // regardless we'll process - - // the last record as though - // it might be continued - // if there is only one - // records, it will go here too. - } - else - { // we do have a continue record - short size = LittleEndian.readShort(in); - byte[] data = new byte[ size ]; - - if (data.length > 0) - { - in.read(data); - } - rec.processContinueRecord(data); - } - bytesread = in.read(sidbytes); // read next record sid - } - if (rec != null) - { - userCode = req.processRecord(rec); - if (userCode != 0) break process; - } - } - catch (IOException e) - { - throw new RecordFormatException("Error reading bytes" + - "while processing record sid="+sid); - } - return userCode; - - // Record[] retval = new Record[ records.size() ]; - // retval = ( Record [] ) records.toArray(retval); - // return null; - } -} diff --git a/src/java/org/apache/poi/hssf/eventmodel/HSSFListener.java b/src/java/org/apache/poi/hssf/eventmodel/HSSFListener.java deleted file mode 100644 index 09ac21c757..0000000000 --- a/src/java/org/apache/poi/hssf/eventmodel/HSSFListener.java +++ /dev/null @@ -1,78 +0,0 @@ - -/* ==================================================================== - * 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; - -/** - * Interface for use with the HSSFRequest and HSSFEventFactory. Users should create - * a listener supporting this interface and register it with the HSSFRequest (associating - * it with Record SID's). - * - * @see org.apache.poi.hssf.eventmodel.HSSFEventFactory - * @see org.apache.poi.hssf.eventmodel.HSSFRequest - * @author andy - */ - -public interface HSSFListener -{ - - /** - * process an HSSF Record. Called when a record occurs in an HSSF file. - */ - - public void processRecord(Record record); -} diff --git a/src/java/org/apache/poi/hssf/eventmodel/HSSFRequest.java b/src/java/org/apache/poi/hssf/eventmodel/HSSFRequest.java deleted file mode 100644 index 4f01d305e6..0000000000 --- a/src/java/org/apache/poi/hssf/eventmodel/HSSFRequest.java +++ /dev/null @@ -1,179 +0,0 @@ - -/* ==================================================================== - * 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 userCode 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.util.HashMap; -import java.util.List; -import java.util.ArrayList; - -import org.apache.poi.hssf.record.Record; -import org.apache.poi.hssf.record.RecordFactory; - -/** - * An HSSFRequest object should be constructed registering an instance or multiple - * instances of HSSFListener with each Record.sid you wish to listen for. - * - * @see org.apache.poi.hssf.eventmodel.HSSFEventFactory - * @see org.apache.poi.hssf.eventmodel.HSSFListener - * @see org.apache.poi.hssf.dev.EFHSSF - * @see org.apache.poi.hssf.HSSFUserException - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Carey Sublette (careysub@earthling.net) - */ - -public class HSSFRequest -{ - private HashMap records; - - /** Creates a new instance of HSSFRequest */ - - public HSSFRequest() - { - records = - new HashMap(50); // most folks won't listen for too many of these - } - - /** - * add an event listener for a particular record type. The trick is you have to know - * what the records are for or just start with our examples and build on them. Alternatively, - * you CAN call addListenerForAllRecords and you'll recieve ALL record events in one listener, - * but if you like to squeeze every last byte of efficiency out of life you my not like this. - * (its sure as heck what I plan to do) - * - * @see #addListenerForAllRecords(HSSFListener) - * - * @param lsnr for the event - * @param sid identifier for the record type this is the .sid static member on the individual records - * for example req.addListener(myListener, BOFRecord.sid) - */ - - public void addListener(HSSFListener lsnr, short sid) - { - List list = null; - Object obj = records.get(new Short(sid)); - - if (obj != null) - { - list = ( List ) obj; - } - else - { - list = new ArrayList( - 1); // probably most people will use one listener - list.add(lsnr); - records.put(new Short(sid), list); - } - } - - /** - * This is the equivilent of calling addListener(myListener, sid) for EVERY - * record in the org.apache.poi.hssf.record package. This is for lazy - * people like me. You can call this more than once with more than one listener, but - * that seems like a bad thing to do from a practice-perspective unless you have a - * compelling reason to do so (like maybe you send the event two places or log it or - * something?). - * - * @param lsnr a single listener to associate with ALL records - */ - - public void addListenerForAllRecords(HSSFListener lsnr) - { - short[] rectypes = RecordFactory.getAllKnownRecordSIDs(); - - for (int k = 0; k < rectypes.length; k++) - { - addListener(lsnr, rectypes[ k ]); - } - } - - /** - * Called by HSSFEventFactory, passes the Record to each listener associated with - * a record.sid. - * - * Exception and return value added 2002-04-19 by Carey Sublette - * - * @return numeric user-specified result code. If zero continue processing. - * @throws HSSFUserException User exception condition - */ - - protected short processRecord(Record rec) throws HSSFUserException - { - Object obj = records.get(new Short(rec.getSid())); - short userCode = 0; - - if (obj != null) - { - List listeners = ( List ) obj; - - for (int k = 0; k < listeners.size(); k++) - { - Object listenObj = listeners.get(k); - if (listenObj instanceof AbortableHSSFListener) - { - AbortableHSSFListener listener = ( AbortableHSSFListener ) listenObj; - userCode = listener.abortableProcessRecord(rec); - if (userCode!=0) break; - } - else - { - HSSFListener listener = ( HSSFListener ) listenObj; - listener.processRecord(rec); - } - } - } - return userCode; - } -} diff --git a/src/java/org/apache/poi/hssf/eventmodel/HSSFUserException.java b/src/java/org/apache/poi/hssf/eventmodel/HSSFUserException.java deleted file mode 100644 index 8a0a688b8e..0000000000 --- a/src/java/org/apache/poi/hssf/eventmodel/HSSFUserException.java +++ /dev/null @@ -1,140 +0,0 @@ -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2000 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" 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", - * 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 - * . - * - * Portions of this software are based upon public domain software - * originally written at the National Center for Supercomputing Applications, - * University of Illinois, Urbana-Champaign. - */ - -package org.apache.poi.hssf.eventmodel; - -/** - *

This exception is provided as a way for API users to throw - * exceptions from their event handling code. By doing so they - * abort file processing by the HSSFEventFactory and by - * catching it from outside the HSSFEventFactory.processEvents - * method they can diagnose the cause for the abort.

- * - *

The HSSFUserException supports a nested "reason" - * throwable, i.e. an exception that caused this one to be thrown.

- * - *

The HSSF package does not itself throw any of these - * exceptions.

- * - * @author Rainer Klute (klute@rainer-klute.de) - * @author Carey Sublette (careysub@earthling.net) - * @version HSSFUserException.java,v 1.0 - * @since 2002-04-19 - */ -public class HSSFUserException extends Exception -{ - - private Throwable reason; - - - - /** - *

Creates a new {@link HSSFUserException}.

- */ - public HSSFUserException() - { - super(); - } - - - - /** - *

Creates a new {@link HSSFUserException} with a message - * string.

- */ - public HSSFUserException(final String msg) - { - super(msg); - } - - - - /** - *

Creates a new {@link HSSFUserException} with a reason.

- */ - public HSSFUserException(final Throwable reason) - { - super(); - this.reason = reason; - } - - - - /** - *

Creates a new {@link HSSFUserException} with a message string - * and a reason.

- */ - public HSSFUserException(final String msg, final Throwable reason) - { - super(msg); - this.reason = reason; - } - - - - /** - *

Returns the {@link Throwable} that caused this exception to - * be thrown or null if there was no such {@link - * Throwable}.

- */ - public Throwable getReason() - { - return reason; - } - -} diff --git a/src/java/org/apache/poi/hssf/eventmodel/package.html b/src/java/org/apache/poi/hssf/eventmodel/package.html deleted file mode 100755 index 5a2ecf39ee..0000000000 --- a/src/java/org/apache/poi/hssf/eventmodel/package.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - -HSSF eventmodel Package provides an event-based API for reading HSSF files. - -

Related Documentation

-The event model can reald XLS files with a very small memory footprint. For -writing you still have to use the usermodel. The eventmodel is to the usermodel -what SAX is to DOM. - -For overviews, tutorials, examples, guides, and tool documentation, please see: - - - -@see org.apache.poi.hssf.usermodel -@see org.apache.poi.hssf.record - - diff --git a/src/java/org/apache/poi/hssf/eventusermodel/AbortableHSSFListener.java b/src/java/org/apache/poi/hssf/eventusermodel/AbortableHSSFListener.java new file mode 100644 index 0000000000..2f3876e7b7 --- /dev/null +++ b/src/java/org/apache/poi/hssf/eventusermodel/AbortableHSSFListener.java @@ -0,0 +1,106 @@ + +/* ==================================================================== + * 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.eventusermodel; + +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.eventusermodel.HSSFUserException; + +/** + * Interface for use with the HSSFRequest and HSSFEventFactory. Users should create + * a listener supporting this interface and register it with the HSSFRequest (associating + * it with Record SID's). + * + * @see org.apache.poi.hssf.eventmodel.HSSFEventFactory + * @see org.apache.poi.hssf.eventmodel.HSSFRequest + * @see org.apache.poi.hssf.HSSFUserException + * + * @author Carey Sublette (careysub@earthling.net) + * + */ + +public abstract class AbortableHSSFListener implements HSSFListener +{ + /** + * This method, inherited from HSSFListener is implemented as a stub. + * It is never called by HSSFEventFActory or HSSFRequest. + * + */ + + public void processRecord(Record record) + { + } + + /** + * Process an HSSF Record. Called when a record occurs in an HSSF file. + * Provides two options for halting the processing of the HSSF file. + * + * The return value provides a means of non-error termination with a + * user-defined result code. A value of zero must be returned to + * continue processing, any other value will halt processing by + * HSSFEventFactory with the code being passed back by + * its abortable process events methods. + * + * Error termination can be done by throwing the HSSFUserException. + * + * Note that HSSFEventFactory will not call the inherited process + * + * @return result code of zero for continued processing. + * + * @throws HSSFUserException User code can throw this to abort + * file processing by HSSFEventFactory and return diagnostic information. + */ + public abstract short abortableProcessRecord(Record record) throws HSSFUserException; +} diff --git a/src/java/org/apache/poi/hssf/eventusermodel/HSSFEventFactory.java b/src/java/org/apache/poi/hssf/eventusermodel/HSSFEventFactory.java new file mode 100644 index 0000000000..56ac0c921c --- /dev/null +++ b/src/java/org/apache/poi/hssf/eventusermodel/HSSFEventFactory.java @@ -0,0 +1,270 @@ + +/* ==================================================================== + * 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.eventusermodel; + +import java.io.InputStream; +import java.io.IOException; + +import org.apache.poi.util.LittleEndian; +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; +import org.apache.poi.hssf.record.ContinueRecord; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; + +/** + * Low level event based HSSF reader. Pass either a DocumentInputStream to + * process events along with a request object or pass a POIFS POIFSFileSystem to + * processWorkbookEvents along with a request. + * + * This will cause your file to be processed a record at a time. Each record with + * a static id matching one that you have registed in your HSSFRequest will be passed + * to your associated HSSFListener. + * + * @see org.apache.poi.hssf.dev.EFHSSF + * + * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Carey Sublette (careysub@earthling.net) + */ + +public class HSSFEventFactory +{ + /** Creates a new instance of HSSFEventFactory */ + + public HSSFEventFactory() + { + } + + /** + * Processes a file into essentially record events. + * + * @param req an Instance of HSSFRequest which has your registered listeners + * @param fs a POIFS filesystem containing your workbook + */ + + public void processWorkbookEvents(HSSFRequest req, POIFSFileSystem fs) + throws IOException + { + InputStream in = fs.createDocumentInputStream("Workbook"); + + processEvents(req, in); + } + + /** + * Processes a file into essentially record events. + * + * @param req an Instance of HSSFRequest which has your registered listeners + * @param fs a POIFS filesystem containing your workbook + * @return numeric user-specified result code. + */ + + public short abortableProcessWorkbookEvents(HSSFRequest req, POIFSFileSystem fs) + throws IOException, HSSFUserException + { + InputStream in = fs.createDocumentInputStream("Workbook"); + return abortableProcessEvents(req, in); + } + + /** + * Processes a DocumentInputStream into essentially Record events. + * + * If an AbortableHSSFListener causes a halt to processing during this call + * the method will return just as with abortableProcessEvents, but no + * user code or HSSFUserException will be passed back. + * + * @see org.apache.poi.poifs.filesystem.POIFSFileSystem#createDocumentInputStream(String) + * @param req an Instance of HSSFRequest which has your registered listeners + * @param in a DocumentInputStream obtained from POIFS's POIFSFileSystem object + */ + + public void processEvents(HSSFRequest req, InputStream in) + throws IOException + { + try + { + genericProcessEvents(req, in); + } + catch (HSSFUserException hue) + {/*If an HSSFUserException user exception is thrown, ignore it.*/ } + } + + + /** + * Processes a DocumentInputStream into essentially Record events. + * + * @see org.apache.poi.poifs.filesystem.POIFSFileSystem#createDocumentInputStream(String) + * @param req an Instance of HSSFRequest which has your registered listeners + * @param in a DocumentInputStream obtained from POIFS's POIFSFileSystem object + * @return numeric user-specified result code. + */ + + public short abortableProcessEvents(HSSFRequest req, InputStream in) + throws IOException, HSSFUserException + { + return genericProcessEvents(req, in); + } + + /** + * Processes a DocumentInputStream into essentially Record events. + * + * @see org.apache.poi.poifs.filesystem.POIFSFileSystem#createDocumentInputStream(String) + * @param req an Instance of HSSFRequest which has your registered listeners + * @param in a DocumentInputStream obtained from POIFS's POIFSFileSystem object + * @param in a DocumentInputStream obtained from POIFS's POIFSFileSystem object + * @return numeric user-specified result code. + */ + + protected short genericProcessEvents(HSSFRequest req, InputStream in) + throws IOException, HSSFUserException + { + short userCode = 0; + + short sid = 0; + process: + try + { + byte[] sidbytes = new byte[ 2 ]; + int bytesread = in.read(sidbytes); + Record rec = null; + + while (bytesread > 0) + { + + sid = LittleEndian.getShort(sidbytes); + + // + // for some reasons we have to make the workbook to be at least 4096 bytes + // but if we have such workbook we fill the end of it with zeros (many zeros) + // + // it is not good: + // if the length( all zero records ) % 4 = 1 + // e.g.: any zero record would be readed as 4 bytes at once ( 2 - id and 2 - size ). + // And the last 1 byte will be readed WRONG ( the id must be 2 bytes ) + // + // So we should better to check if the sid is zero and not to read more data + // The zero sid shows us that rest of the stream data is a fake to make workbook + // certain size + // + if ( sid == 0 ) + break; + + + if ((rec != null) && (sid != ContinueRecord.sid)) + { + userCode = req.processRecord(rec); + if (userCode != 0) break process; + } + if (sid != ContinueRecord.sid) + { + short size = LittleEndian.readShort(in); + byte[] data = new byte[ size ]; + + if (data.length > 0) + { + in.read(data); + } + System.out.println("creating "+sid); + Record[] recs = RecordFactory.createRecord(sid, size, + data); + + if (recs.length > 1) + { // we know that the multiple + for (int k = 0; k < (recs.length - 1); k++) + { // record situations do not + userCode = req.processRecord( + recs[ k ]); // contain continue records + if (userCode != 0) break process; + } + } + rec = recs[ recs.length - 1 ]; // regardless we'll process + + // the last record as though + // it might be continued + // if there is only one + // records, it will go here too. + } + else + { // we do have a continue record + short size = LittleEndian.readShort(in); + byte[] data = new byte[ size ]; + + if (data.length > 0) + { + in.read(data); + } + rec.processContinueRecord(data); + } + bytesread = in.read(sidbytes); // read next record sid + } + if (rec != null) + { + userCode = req.processRecord(rec); + if (userCode != 0) break process; + } + } + catch (IOException e) + { + throw new RecordFormatException("Error reading bytes" + + "while processing record sid="+sid); + } + return userCode; + + // Record[] retval = new Record[ records.size() ]; + // retval = ( Record [] ) records.toArray(retval); + // return null; + } +} diff --git a/src/java/org/apache/poi/hssf/eventusermodel/HSSFListener.java b/src/java/org/apache/poi/hssf/eventusermodel/HSSFListener.java new file mode 100644 index 0000000000..6c59c69307 --- /dev/null +++ b/src/java/org/apache/poi/hssf/eventusermodel/HSSFListener.java @@ -0,0 +1,78 @@ + +/* ==================================================================== + * 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.eventusermodel; + +import org.apache.poi.hssf.record.Record; + +/** + * Interface for use with the HSSFRequest and HSSFEventFactory. Users should create + * a listener supporting this interface and register it with the HSSFRequest (associating + * it with Record SID's). + * + * @see org.apache.poi.hssf.eventmodel.HSSFEventFactory + * @see org.apache.poi.hssf.eventmodel.HSSFRequest + * @author acoliver@apache.org + */ + +public interface HSSFListener +{ + + /** + * process an HSSF Record. Called when a record occurs in an HSSF file. + */ + + public void processRecord(Record record); +} diff --git a/src/java/org/apache/poi/hssf/eventusermodel/HSSFRequest.java b/src/java/org/apache/poi/hssf/eventusermodel/HSSFRequest.java new file mode 100644 index 0000000000..be08b31397 --- /dev/null +++ b/src/java/org/apache/poi/hssf/eventusermodel/HSSFRequest.java @@ -0,0 +1,179 @@ + +/* ==================================================================== + * 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 userCode 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.eventusermodel; + +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; + +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.RecordFactory; + +/** + * An HSSFRequest object should be constructed registering an instance or multiple + * instances of HSSFListener with each Record.sid you wish to listen for. + * + * @see org.apache.poi.hssf.eventmodel.HSSFEventFactory + * @see org.apache.poi.hssf.eventmodel.HSSFListener + * @see org.apache.poi.hssf.dev.EFHSSF + * @see org.apache.poi.hssf.HSSFUserException + * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Carey Sublette (careysub@earthling.net) + */ + +public class HSSFRequest +{ + private HashMap records; + + /** Creates a new instance of HSSFRequest */ + + public HSSFRequest() + { + records = + new HashMap(50); // most folks won't listen for too many of these + } + + /** + * add an event listener for a particular record type. The trick is you have to know + * what the records are for or just start with our examples and build on them. Alternatively, + * you CAN call addListenerForAllRecords and you'll recieve ALL record events in one listener, + * but if you like to squeeze every last byte of efficiency out of life you my not like this. + * (its sure as heck what I plan to do) + * + * @see #addListenerForAllRecords(HSSFListener) + * + * @param lsnr for the event + * @param sid identifier for the record type this is the .sid static member on the individual records + * for example req.addListener(myListener, BOFRecord.sid) + */ + + public void addListener(HSSFListener lsnr, short sid) + { + List list = null; + Object obj = records.get(new Short(sid)); + + if (obj != null) + { + list = ( List ) obj; + } + else + { + list = new ArrayList( + 1); // probably most people will use one listener + list.add(lsnr); + records.put(new Short(sid), list); + } + } + + /** + * This is the equivilent of calling addListener(myListener, sid) for EVERY + * record in the org.apache.poi.hssf.record package. This is for lazy + * people like me. You can call this more than once with more than one listener, but + * that seems like a bad thing to do from a practice-perspective unless you have a + * compelling reason to do so (like maybe you send the event two places or log it or + * something?). + * + * @param lsnr a single listener to associate with ALL records + */ + + public void addListenerForAllRecords(HSSFListener lsnr) + { + short[] rectypes = RecordFactory.getAllKnownRecordSIDs(); + + for (int k = 0; k < rectypes.length; k++) + { + addListener(lsnr, rectypes[ k ]); + } + } + + /** + * Called by HSSFEventFactory, passes the Record to each listener associated with + * a record.sid. + * + * Exception and return value added 2002-04-19 by Carey Sublette + * + * @return numeric user-specified result code. If zero continue processing. + * @throws HSSFUserException User exception condition + */ + + protected short processRecord(Record rec) throws HSSFUserException + { + Object obj = records.get(new Short(rec.getSid())); + short userCode = 0; + + if (obj != null) + { + List listeners = ( List ) obj; + + for (int k = 0; k < listeners.size(); k++) + { + Object listenObj = listeners.get(k); + if (listenObj instanceof AbortableHSSFListener) + { + AbortableHSSFListener listener = ( AbortableHSSFListener ) listenObj; + userCode = listener.abortableProcessRecord(rec); + if (userCode!=0) break; + } + else + { + HSSFListener listener = ( HSSFListener ) listenObj; + listener.processRecord(rec); + } + } + } + return userCode; + } +} diff --git a/src/java/org/apache/poi/hssf/eventusermodel/HSSFUserException.java b/src/java/org/apache/poi/hssf/eventusermodel/HSSFUserException.java new file mode 100644 index 0000000000..543b886673 --- /dev/null +++ b/src/java/org/apache/poi/hssf/eventusermodel/HSSFUserException.java @@ -0,0 +1,140 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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" 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", + * 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 + * . + * + * Portions of this software are based upon public domain software + * originally written at the National Center for Supercomputing Applications, + * University of Illinois, Urbana-Champaign. + */ + +package org.apache.poi.hssf.eventusermodel; + +/** + *

This exception is provided as a way for API users to throw + * exceptions from their event handling code. By doing so they + * abort file processing by the HSSFEventFactory and by + * catching it from outside the HSSFEventFactory.processEvents + * method they can diagnose the cause for the abort.

+ * + *

The HSSFUserException supports a nested "reason" + * throwable, i.e. an exception that caused this one to be thrown.

+ * + *

The HSSF package does not itself throw any of these + * exceptions.

+ * + * @author Rainer Klute (klute@rainer-klute.de) + * @author Carey Sublette (careysub@earthling.net) + * @version HSSFUserException.java,v 1.0 + * @since 2002-04-19 + */ +public class HSSFUserException extends Exception +{ + + private Throwable reason; + + + + /** + *

Creates a new {@link HSSFUserException}.

+ */ + public HSSFUserException() + { + super(); + } + + + + /** + *

Creates a new {@link HSSFUserException} with a message + * string.

+ */ + public HSSFUserException(final String msg) + { + super(msg); + } + + + + /** + *

Creates a new {@link HSSFUserException} with a reason.

+ */ + public HSSFUserException(final Throwable reason) + { + super(); + this.reason = reason; + } + + + + /** + *

Creates a new {@link HSSFUserException} with a message string + * and a reason.

+ */ + public HSSFUserException(final String msg, final Throwable reason) + { + super(msg); + this.reason = reason; + } + + + + /** + *

Returns the {@link Throwable} that caused this exception to + * be thrown or null if there was no such {@link + * Throwable}.

+ */ + public Throwable getReason() + { + return reason; + } + +} diff --git a/src/java/org/apache/poi/hssf/eventusermodel/package.html b/src/java/org/apache/poi/hssf/eventusermodel/package.html new file mode 100644 index 0000000000..5a2ecf39ee --- /dev/null +++ b/src/java/org/apache/poi/hssf/eventusermodel/package.html @@ -0,0 +1,23 @@ + + + + + + +HSSF eventmodel Package provides an event-based API for reading HSSF files. + +

Related Documentation

+The event model can reald XLS files with a very small memory footprint. For +writing you still have to use the usermodel. The eventmodel is to the usermodel +what SAX is to DOM. + +For overviews, tutorials, examples, guides, and tool documentation, please see: + + + +@see org.apache.poi.hssf.usermodel +@see org.apache.poi.hssf.record + + 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