diff options
author | (no author) <(no author)@unknown> | 2002-06-15 03:21:07 +0000 |
---|---|---|
committer | (no author) <(no author)@unknown> | 2002-06-15 03:21:07 +0000 |
commit | 02031ec26e8757f6daa140677f03f924b6fee952 (patch) | |
tree | ecf8954959b72ce95a5886054aeae2dacf501646 /src | |
parent | 899521e1d61088cd280a0be0167f6c7cb5f2178a (diff) | |
download | poi-02031ec26e8757f6daa140677f03f924b6fee952.tar.gz poi-02031ec26e8757f6daa140677f03f924b6fee952.zip |
This commit was manufactured by cvs2svn to create tag 'REL_1_5_1'.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/tags/REL_1_5_1@352699 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
45 files changed, 2924 insertions, 2083 deletions
diff --git a/src/documentation/images/logoRaPiGmbH1.png b/src/documentation/images/logoRaPiGmbH1.png Binary files differnew file mode 100644 index 0000000000..3bef8bb6e9 --- /dev/null +++ b/src/documentation/images/logoRaPiGmbH1.png diff --git a/src/documentation/images/logoRaPiGmbH2.png b/src/documentation/images/logoRaPiGmbH2.png Binary files differnew file mode 100644 index 0000000000..d842217557 --- /dev/null +++ b/src/documentation/images/logoRaPiGmbH2.png diff --git a/src/documentation/images/logoRaPiGmbH3.png b/src/documentation/images/logoRaPiGmbH3.png Binary files differnew file mode 100644 index 0000000000..0419155689 --- /dev/null +++ b/src/documentation/images/logoRaPiGmbH3.png diff --git a/src/documentation/images/logoRaPiGmbH4.png b/src/documentation/images/logoRaPiGmbH4.png Binary files differnew file mode 100644 index 0000000000..3b8d44d6e4 --- /dev/null +++ b/src/documentation/images/logoRaPiGmbH4.png diff --git a/src/documentation/images/logoRaPiGmbH5.png b/src/documentation/images/logoRaPiGmbH5.png Binary files differnew file mode 100644 index 0000000000..f96ef9ef91 --- /dev/null +++ b/src/documentation/images/logoRaPiGmbH5.png diff --git a/src/documentation/images/logoRaPiGmbH6.png b/src/documentation/images/logoRaPiGmbH6.png Binary files differnew file mode 100644 index 0000000000..53ee5e9eab --- /dev/null +++ b/src/documentation/images/logoRaPiGmbH6.png diff --git a/src/documentation/images/logoRaPiGmbH7.png b/src/documentation/images/logoRaPiGmbH7.png Binary files differnew file mode 100644 index 0000000000..498499d9df --- /dev/null +++ b/src/documentation/images/logoRaPiGmbH7.png diff --git a/src/documentation/xdocs/book.xml b/src/documentation/xdocs/book.xml index e5ab10098e..1d4b945e38 100644 --- a/src/documentation/xdocs/book.xml +++ b/src/documentation/xdocs/book.xml @@ -39,6 +39,7 @@ <menu label="Get Involved"> <menu-item label="Contributing" href="contrib.html"/> + <menu-item label="Branching" href="branching.html"/> <menu-item label="Bug Database" href="http://nagoya.apache.org/bugzilla/buglist.cgi?product=POI"/> <menu-item label="CVS" href="http://jakarta.apache.org/site/cvsindex.html"/> <menu-item label="Mail Lists" href="http://jakarta.apache.org/site/mail.html"/> diff --git a/src/documentation/xdocs/branching.xml b/src/documentation/xdocs/branching.xml new file mode 100644 index 0000000000..4246d83443 --- /dev/null +++ b/src/documentation/xdocs/branching.xml @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "./dtd/document-v11.dtd"> + +<document> + + <header> + <title>Branching</title> + <authors> + <person id="GJS" name="Glen Stampoultzis" email="glens@apache.org"/> + </authors> + </header> + + <body> + <section title="Branching Conventions"> + <p> + Branches are tagged in the following way: + </p> + <ul> + <li>REL_1_5_BRANCH</li> + <li>REL_2_0_BRANCH</li> + </ul> + <p> + Merge points should be tagged as follows: + </p> + <ul> + <li>REL_1_5_BRANCH_MERGE1</li> + <li>REL_1_5_BRANCH_MERGE2</li> + <li>etc...</li> + </ul> + <p> + Releases should be tagged as: + </p> + <ul> + <li>REL_1_5</li> + <li>REL_1_5_1</li> + <li>REL_1_5_2</li> + <li>etc...</li> + </ul> + + </section> + <section title="Branching Advise"> + <p> + Don't forget which branch you are currently on. This is critically + important. Committing stuff to the wrong branch causes all sorts of + headaches. Best to name your checkout after the branch you are on. + </p> + </section> + <section title="Who Manages Branching?"> + <p> + All branching is currently managed by Glen Stampoultzis. If you wish + to create your own branch please let him know. Merging is also + handled by Glen. Just pop him a mail if you feel it's necessary to + create a branch or perform a merge. + </p> + <p> + The reason to go through a single point for branching is that it can be + an easy thing to get wrong. Having a single person managing branches + means there is less chance of getting getting our wires crossed with this + difficult area of CVS. + </p> + </section> + <section title="Currently Active Branches"> + <p> + The following branches are currently active: + </p> + <table> + <tr> + <th> + <b>Branch</b> + </th> + <th> + <b>Description</b> + </th> + </tr> + <tr> + <td> + HEAD + </td> + <td> + This is the trunk and is always active. Currently it is being used to continue development + of the 2.0 release. + </td> + </tr> + <tr> + <td> + REL_1_5_BRANCH + </td> + <td> + All bug fixes not specifically relevant to the 2.0 work should be placed in this branch. + From here they will merged back to the trunk and the merge point marked. + </td> + </tr> + </table> + </section> + </body> + +</document>
\ No newline at end of file diff --git a/src/documentation/xdocs/changes.xml b/src/documentation/xdocs/changes.xml index 36223b2ff6..9540dcfd76 100644 --- a/src/documentation/xdocs/changes.xml +++ b/src/documentation/xdocs/changes.xml @@ -11,7 +11,11 @@ <person id="NKB" name="Nicola Ken Barozzi" email="barozzi@nicolaken.com"/> <person id="POI-DEVELOPERS" name="Poi Developers" email="poi-dev@jakarta.apache.org"/> </devs> - <release version="1.5" date="Coming Soon"> + <release version="1.5.1" date="16 June 2002"> + <action dev="GJS" type="update">Removed depedency on commons logging. Now define poi.logging system property to enable logging to standard out.</action> + <action dev="GJS" type="fix">Fixed SST string handling so that spreadsheets with rich text or extended text will be read correctly.</action> + </release> + <release version="1.5" date="06 May 2002"> <action dev="NKB" type="update">New project build.</action> <action dev="NKB" type="update">New project documentation system based on Cocoon.</action> <action dev="POI-DEVELOPERS" type="update">Package rename</action> diff --git a/src/documentation/xdocs/historyandfuture.xml b/src/documentation/xdocs/historyandfuture.xml index 3855480f69..741f6aad5c 100755 --- a/src/documentation/xdocs/historyandfuture.xml +++ b/src/documentation/xdocs/historyandfuture.xml @@ -3,7 +3,7 @@ <document> <header> - <title></title> + <title>Project History</title> <authors> <person id="AO" name="Andrew C. Oliver" email="acoliver@apache.org"/> </authors> diff --git a/src/documentation/xdocs/hssf/how-to.xml b/src/documentation/xdocs/hssf/how-to.xml index 8c5d930dba..2ad13bec85 100644 --- a/src/documentation/xdocs/hssf/how-to.xml +++ b/src/documentation/xdocs/hssf/how-to.xml @@ -397,55 +397,20 @@ export CLASSPATH=$CLASSPATH:$HSSFDIR/hssf.jar:$HSSFDIR/poi-poifs.jar:$HSSFDIR/po <ul> <li>Type: <code>java org.apache.poi.hssf.dev.HSSF ~/input.xls output.xls</code> - <p> + <br/> + <br/> This is the read/write/modify test. It reads in the spreadsheet, modifies a cell, and writes it back out. Failing this test is not necessarily a bad thing. If HSSF tries to modify a non-existant sheet then this will -most likely fail. No big deal. </p></li> +most likely fail. No big deal. </li> </ul> </section> - <section title="HSSF Logging facility"> -<p>HSSF now has a logging facility (using - <link href="http://jakarta.apache.org/commons/logging.html">commons logging</link>) -that will record massive amounts of debugging information. Its mostly -useful to us hssf-developing geeks, but might be useful in tracking -down problems. -</p> -<p>So Why use commons logging rather than log4j? Well the following discussion from -the jakarta-general mailing list sums it up pretty well. (Thanks Morgan) -</p> -<p><em>Here's the problem, as I see it.</em> -</p> -<p><em>Suppose Commons component A decides to adopt Log4J, Commons component B -decides to adopt LogKit, and Commons component C adopts JDK1.4 logging. -They will all minimally function with the right jars in the classpath. -However you (the end-user) are left with maintaining configuration for 3 -different logging APIs, which is tedious at best. When you take into -account cool features like variable log levels, Log4J appenders and the -like, you're pretty much guaranteed to swallow up useful configuration -options because sophisticated configurations are too difficult to maintain -over mutiple logging implementations.</em> -</p> -<p> -<em>Contrarily, if all three Commons components use a logging facade, you can -focus all your configuration efforts on one logging implementation. Sure, -there is a trade-off; you don't have access to all the features, and the -interface between the facade and the implementation must be maintained. But -the benefits are not just political; they potentially make the end-users -configuration much easier.</em> -</p> -<p><em>Even if all Commons components used the same logging implementation (Log4J -for example), other projects in Jakarta-land may choose otherwise. If you -add enough Jakarta projects to your environment, you eventually end up with -the scenario described above. It's a worthwhile effort to attempt a logging -solution that plays well with the Jakarta community at large. I think in -many cases the Commons Logging component can fill that role.</em> -</p> + <section title="HSSF Logging Facility"> <p> -Refer to the commons logging package level javadoc for more information concerning how to -<link href="http://jakarta.apache.org/commons/logging/api/index.html">configure commons logging.</link> + POI has a small amount of logging code embedded within it. Defining the system property + poi.logging will enable logging to standard out. </p> </section> - <section title="HSSF Developer's tools"> + <section title="HSSF Developer's Tools"> <p>HSSF has a number of tools useful for developers to debug/develop stuff using HSSF (and more generally XLS files). We've already diff --git a/src/documentation/xdocs/hssf/quick-guide.xml b/src/documentation/xdocs/hssf/quick-guide.xml index 2d660255dd..53eaee8c25 100644 --- a/src/documentation/xdocs/hssf/quick-guide.xml +++ b/src/documentation/xdocs/hssf/quick-guide.xml @@ -28,6 +28,7 @@ <li><link href="#MergedCells">Merging cells</link></li> <li><link href="#WorkingWithFonts">Working with fonts</link></li> <li><link href="#ReadWriteWorkbook">Reading and writing</link></li> + <li><link href="#NewLinesInCells">Use newlines in cells.</link></li> </ul> </section> <section title="Features"> @@ -294,6 +295,35 @@ fileOut.close(); </source> </section> + <anchor id="UseNewLinesInCells"/> + <section title="Using newlines in cells"> + <source> + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet s = wb.createSheet(); + HSSFRow r = null; + HSSFCell c = null; + HSSFCellStyle cs = wb.createCellStyle(); + HSSFFont f = wb.createFont(); + HSSFFont f2 = wb.createFont(); + + cs = wb.createCellStyle(); + + cs.setFont( f2 ); + //Word Wrap MUST be turned on + cs.setWrapText( true ); + + r = s.createRow( (short) 2 ); + r.setHeight( (short) 0x349 ); + c = r.createCell( (short) 2 ); + c.setCellType( HSSFCell.CELL_TYPE_STRING ); + c.setCellValue( "Use \n with word wrap on to create a new line" ); + c.setCellStyle( cs ); + s.setColumnWidth( (short) 2, (short) ( ( 50 * 8 ) / ( (double) 1 / 20 ) ) ); + + FileOutputStream fileOut = new FileOutputStream( "workbook.xls" ); + wb.write( fileOut ); + fileOut.close();</source> + </section> </section> </section> </body> diff --git a/src/documentation/xdocs/news/logocontest.xml b/src/documentation/xdocs/news/logocontest.xml index 9c45d06c66..9d9179c865 100644 --- a/src/documentation/xdocs/news/logocontest.xml +++ b/src/documentation/xdocs/news/logocontest.xml @@ -2,114 +2,139 @@ <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd"> <document> - <header> - <title></title> - <authors> - <person id="AO" name="Andrew C. Oliver" email="acoliver@apache.org"/> - </authors> - </header> - - <body> - <section title="POI logos"> - <p> - Here are the current logo submissions. Thanks to the artists! - </p> - <section title="Michael Mosmann"> - <p> - <img src="images/logoMichaelMosmann.png"/> + <header> + <title></title> + <authors> + <person id="AO" name="Andrew C. Oliver" email="acoliver@apache.org"/> + <person id="GS" name="Glen Stampoultzis" email="glens@apache.org"/> + </authors> + </header> + + <body> + <section title="POI logos"> + <p> + Here are the current logo submissions. Thanks to the artists! + </p> + <section title="Michael Mosmann"> + <p> + <img src="images/logoMichaelMosmann.png"/> </p> - </section> - <section title="Lo�c Lef�vre"> + </section> + <section title="Lo�c Lef�vre"> <p> - <img src="images/logoLoicLefevre.png"/> - <img src="images/logoLoicLefevre2.png"/> + <img src="images/logoLoicLefevre.png"/> + <img src="images/logoLoicLefevre2.png"/> </p> - </section> - <section title="Glen Stampoultzis"> + </section> + <section title="Glen Stampoultzis"> <p> - <img src="images/logoGlenStampoutlzis.png"/> + <img src="images/logoGlenStampoutlzis.png"/> </p> - </section> - <section title="Marcus Gustafsson"> + </section> + <section title="Marcus Gustafsson"> <p> - <img src="images/logoGustafsson1.png"/> - <img src="images/logoGustafsson2.png"/> + <img src="images/logoGustafsson1.png"/> + <img src="images/logoGustafsson2.png"/> </p> - </section> - <section title="Adrianus Handoyo"> + </section> + <section title="Adrianus Handoyo"> <p> - <img src="images/logoAdria1.png"/> - <img src="images/logoAdria2.png"/> - <img src="images/logoAdria3.png"/> + <img src="images/logoAdria1.png"/> + <img src="images/logoAdria2.png"/> + <img src="images/logoAdria3.png"/> </p> - </section> - <section title="RussellBeattie"> + </section> + <section title="RussellBeattie"> <p> - <img src="images/logoRussellBeattie1.png"/> - <img src="images/logoRussellBeattie2.png"/> - <img src="images/logoRussellBeattie3.png"/> + <img src="images/logoRussellBeattie1.png"/> + <img src="images/logoRussellBeattie2.png"/> + <img src="images/logoRussellBeattie3.png"/> </p> <p> - <img src="images/logoRussellBeattie4.png"/> - <img src="images/logoRussellBeattie5.png"/> + <img src="images/logoRussellBeattie4.png"/> + <img src="images/logoRussellBeattie5.png"/> </p> - </section> - <section title="Daniel Fernandez"> + </section> + <section title="Daniel Fernandez"> <p> - <img src="images/logoDanielFernandez.png"/> + <img src="images/logoDanielFernandez.png"/> </p> - </section> - <section title="Andrew Clements"> + </section> + <section title="Andrew Clements"> <p> - <img src="images/logoAndrewClements.png"/> - <img src="images/logoAndrewClements2.png"/> + <img src="images/logoAndrewClements.png"/> + <img src="images/logoAndrewClements2.png"/> </p> - </section> - <section title="Wendy Wise"> + </section> + <section title="Wendy Wise"> <p> - <img src="images/logoWendyWise.png"/> - <img src="images/logoWendyWise2.png"/> + <img src="images/logoWendyWise.png"/> + <img src="images/logoWendyWise2.png"/> </p> - </section> - <section title="Nikhil Karmokar"> + </section> + <section title="Nikhil Karmokar"> <p> - <img src="images/logoKarmokar1.png"/> - <img src="images/logoKarmokar1s.png"/> + <img src="images/logoKarmokar1.png"/> + <img src="images/logoKarmokar1s.png"/> </p> <p> - <img src="images/logoKarmokar2.png"/> - <img src="images/logoKarmokar2s.png"/> + <img src="images/logoKarmokar2.png"/> + <img src="images/logoKarmokar2s.png"/> </p> <p> - <img src="images/logoKarmokar3.png"/> - <img src="images/logoKarmokar3s.png"/> + <img src="images/logoKarmokar3.png"/> + <img src="images/logoKarmokar3s.png"/> </p> <p> - <img src="images/logoKarmokar4.png"/> - <img src="images/logoKarmokar4s.png"/> + <img src="images/logoKarmokar4.png"/> + <img src="images/logoKarmokar4s.png"/> </p> <p> - <img src="images/logoKarmokar5.png"/> - <img src="images/logoKarmokar5s.png"/> + <img src="images/logoKarmokar5.png"/> + <img src="images/logoKarmokar5s.png"/> </p> <p> - <img src="images/logoKarmokar6.png"/> - <img src="images/logoKarmokar6s.png"/> + <img src="images/logoKarmokar6.png"/> + <img src="images/logoKarmokar6s.png"/> </p> - </section> - <section title="Lieven Janssen"> + </section> + <section title="Lieven Janssen"> + <p> + <img src="images/logoJanssen1.png"/> + <img src="images/logoJanssen2.png"/> + </p> + </section> + <section title="RaPi GmbH"> <p> - <img src="images/logoJanssen1.png"/> - <img src="images/logoJanssen2.png"/> + Contact Person: Fancy at: fancy at my-feiqi.com </p> + <p> + <img src="images/logoRaPiGmbH1.png"/> + <img src="images/logoRaPiGmbH2.png"/> + </p> + <p> + <img src="images/logoRaPiGmbH3.png"/> + </p> + <p> + <img src="images/logoRaPiGmbH4.png"/> + </p> + <p> + <img src="images/logoRaPiGmbH5.png"/> + </p> + <p> + <img src="images/logoRaPiGmbH6.png"/> + </p> + <p> + <img src="images/logoRaPiGmbH7.png"/> + </p> + </section> + </section> - - </section> - </body> - <footer> - <legal> - Copyright (c) @year@ The Apache Software Foundation All rights reserved. - $Revision$ $Date$ - </legal> - </footer> + </body> + <footer> + <legal> + Copyright (c) @year@ The Apache Software Foundation All rights reserved. + $Revision$ $Date$ + </legal> + </footer> </document> diff --git a/src/examples/src/org/apache/poi/hssf/usermodel/examples/NewLinesInCells.java b/src/examples/src/org/apache/poi/hssf/usermodel/examples/NewLinesInCells.java new file mode 100644 index 0000000000..517234fc97 --- /dev/null +++ b/src/examples/src/org/apache/poi/hssf/usermodel/examples/NewLinesInCells.java @@ -0,0 +1,100 @@ +/* ==================================================================== + * 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 + * <http://www.apache.org/>. + */ + +package org.apache.poi.hssf.usermodel.examples; + +import org.apache.poi.hssf.usermodel.*; + +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * Demonstrates how to use newlines in cells. + * + * @author Glen Stampoultzis (glens at apache.org) + * @author Fauzia Lala <fauzia.lala at wcom.com> + */ +public class NewLinesInCells +{ + public static void main( String[] args ) throws IOException + { + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet s = wb.createSheet(); + HSSFRow r = null; + HSSFCell c = null; + HSSFCellStyle cs = wb.createCellStyle(); + HSSFFont f = wb.createFont(); + HSSFFont f2 = wb.createFont(); + + cs = wb.createCellStyle(); + + cs.setFont( f2 ); + //Word Wrap MUST be turned on + cs.setWrapText( true ); + + r = s.createRow( (short) 2 ); + r.setHeight( (short) 0x349 ); + c = r.createCell( (short) 2 ); + c.setCellType( HSSFCell.CELL_TYPE_STRING ); + c.setCellValue( "Use \n with word wrap on to create a new line" ); + c.setCellStyle( cs ); + s.setColumnWidth( (short) 2, (short) ( ( 50 * 8 ) / ( (double) 1 / 20 ) ) ); + + FileOutputStream fileOut = new FileOutputStream( "workbook.xls" ); + wb.write( fileOut ); + fileOut.close(); + + } +} diff --git a/src/java/org/apache/poi/hssf/dev/BiffViewer.java b/src/java/org/apache/poi/hssf/dev/BiffViewer.java index 12267d23d8..7d366f1455 100644 --- a/src/java/org/apache/poi/hssf/dev/BiffViewer.java +++ b/src/java/org/apache/poi/hssf/dev/BiffViewer.java @@ -631,12 +631,12 @@ public class BiffViewer retval = new LinkedDataRecord(rectype, size, data); break; - case FormulaRecord.sid: - retval = new FormulaRecord(rectype, size, data); - break; +// case FormulaRecord.sid: +// retval = new FormulaRecord(rectype, size, data); +// break; case SheetPropertiesRecord.sid: - retval = new FormulaRecord(rectype, size, data); + retval = new SheetPropertiesRecord(rectype, size, data); break; diff --git a/src/java/org/apache/poi/hssf/model/Workbook.java b/src/java/org/apache/poi/hssf/model/Workbook.java index d45153f9c9..55fe659322 100644 --- a/src/java/org/apache/poi/hssf/model/Workbook.java +++ b/src/java/org/apache/poi/hssf/model/Workbook.java @@ -643,26 +643,11 @@ public class Workbook { log.log(DEBUG, "Serializing Workbook with offsets"); - // ArrayList bytes = new ArrayList(records.size()); -// int arraysize = getSize(); // 0; int pos = 0; -// for (int k = 0; k < records.size(); k++) -// { -// bytes.add((( Record ) records.get(k)).serialize()); -// -// } -// for (int k = 0; k < bytes.size(); k++) -// { -// arraysize += (( byte [] ) bytes.get(k)).length; -// } for (int k = 0; k < records.size(); k++) { - - // byte[] rec = (( byte [] ) bytes.get(k)); - // System.arraycopy(rec, 0, data, offset + pos, rec.length); - pos += (( Record ) records.get(k)).serialize(pos + offset, - data); // rec.length; + pos += (( Record ) records.get(k)).serialize(pos + offset, data); // rec.length; } log.log(DEBUG, "Exiting serialize workbook"); return pos; diff --git a/src/java/org/apache/poi/hssf/record/ContinueRecord.java b/src/java/org/apache/poi/hssf/record/ContinueRecord.java index 2b67a62d40..5017ade922 100644 --- a/src/java/org/apache/poi/hssf/record/ContinueRecord.java +++ b/src/java/org/apache/poi/hssf/record/ContinueRecord.java @@ -161,9 +161,7 @@ public class ContinueRecord // how many continue records do we need // System.out.println("In ProcessContinue"); - int records = - (data.length - / 8214); // we've a 1 offset but we're also off by one due to rounding...so it balances out + int records = (data.length / 8214); // we've a 1 offset but we're also off by one due to rounding...so it balances out int offset = 8214; // System.out.println("we have "+records+" continue records to process"); @@ -174,8 +172,7 @@ public class ContinueRecord for (int cr = 0; cr < records; cr++) { ContinueRecord contrec = new ContinueRecord(); - int arraysize = Math.min((8214 - 4), - (data.length - offset)); + int arraysize = Math.min((8214 - 4), (data.length - offset)); byte[] crdata = new byte[ arraysize ]; System.arraycopy(data, offset, crdata, 0, arraysize); diff --git a/src/java/org/apache/poi/hssf/record/RecordProcessor.java b/src/java/org/apache/poi/hssf/record/RecordProcessor.java new file mode 100644 index 0000000000..13bfc3a188 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/RecordProcessor.java @@ -0,0 +1,202 @@ +/* ==================================================================== + * 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 + * <http://www.apache.org/>. + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LittleEndian; + +/** + * Process a single record. That is, an SST record or a continue record. + * Refactored from code originally in SSTRecord. + * + * @author Glen Stampoultzis (glens at apache.org) + */ +class RecordProcessor +{ + private byte[] data; + private int recordOffset; + private int available; + private SSTRecordHeader sstRecordHeader; + + public RecordProcessor( byte[] data, int available, int numStrings, int numUniqueStrings ) + { + this.data = data; + this.available = available; + this.sstRecordHeader = new SSTRecordHeader(numStrings, numUniqueStrings); + } + + public int getAvailable() + { + return available; + } + + public void writeRecordHeader( int offset, int totalWritten, int recordLength, boolean first_record ) + { + if ( first_record ) + { + available -= 8; + recordOffset = sstRecordHeader.writeSSTHeader( data, recordOffset + offset + totalWritten, recordLength ); + } + else + { + recordOffset = writeContinueHeader( data, recordOffset + offset + totalWritten, recordLength ); + } + } + + public byte[] writeStringRemainder( boolean lastStringCompleted, byte[] stringreminant, int offset, int totalWritten ) + { + if ( !lastStringCompleted ) + { + // write reminant -- it'll all fit neatly + System.arraycopy( stringreminant, 0, data, recordOffset + offset + totalWritten, stringreminant.length ); + adjustPointers( stringreminant.length ); + } + else + { + // write as much of the remnant as possible + System.arraycopy( stringreminant, 0, data, recordOffset + offset + totalWritten, available ); + byte[] leftover = new byte[( stringreminant.length - available ) + LittleEndianConsts.BYTE_SIZE]; + + System.arraycopy( stringreminant, available, leftover, LittleEndianConsts.BYTE_SIZE, stringreminant.length - available ); + leftover[0] = stringreminant[0]; + stringreminant = leftover; + adjustPointers( available ); // Consume all available remaining space + } + return stringreminant; + } + + public void writeWholeString( UnicodeString unistr, int offset, int totalWritten ) + { + unistr.serialize( recordOffset + offset + totalWritten, data ); + int rsize = unistr.getRecordSize(); + adjustPointers( rsize ); + } + + public byte[] writePartString( UnicodeString unistr, int offset, int totalWritten ) + { + byte[] stringReminant; + byte[] ucs = unistr.serialize(); + + System.arraycopy( ucs, 0, data, recordOffset + offset + totalWritten, available ); + stringReminant = new byte[( ucs.length - available ) + LittleEndianConsts.BYTE_SIZE]; + System.arraycopy( ucs, available, stringReminant, LittleEndianConsts.BYTE_SIZE, ucs.length - available ); + stringReminant[0] = ucs[LittleEndianConsts.SHORT_SIZE]; + available = 0; + return stringReminant; + } + + + private int writeContinueHeader( final byte[] data, final int pos, + final int recsize ) + { + int offset = pos; + + LittleEndian.putShort( data, offset, ContinueRecord.sid ); + offset += LittleEndianConsts.SHORT_SIZE; + LittleEndian.putShort( data, offset, (short) ( recsize ) ); + offset += LittleEndianConsts.SHORT_SIZE; + return offset - pos; + } + + + private void adjustPointers( int amount ) + { + recordOffset += amount; + available -= amount; + } +} + +class SSTRecordHeader +{ + int numStrings; + int numUniqueStrings; + + /** + * + */ + public SSTRecordHeader( int numStrings, int numUniqueStrings ) + { + this.numStrings = numStrings; + this.numUniqueStrings = numUniqueStrings; + } + + /** + * Writes out the SST record. This consists of the sid, the record size, the number of + * strings and the number of unique strings. + * + * @param data The data buffer to write the header to. + * @param bufferIndex The index into the data buffer where the header should be written. + * @param recSize The number of records written. + * + * @return The bufer of bytes modified. + */ + public int writeSSTHeader( byte[] data, int bufferIndex, int recSize ) + { + int offset = bufferIndex; + + LittleEndian.putShort( data, offset, SSTRecord.sid ); + offset += LittleEndianConsts.SHORT_SIZE; + LittleEndian.putShort( data, offset, (short) ( recSize ) ); + offset += LittleEndianConsts.SHORT_SIZE; +// LittleEndian.putInt( data, offset, getNumStrings() ); + LittleEndian.putInt( data, offset, numStrings ); + offset += LittleEndianConsts.INT_SIZE; +// LittleEndian.putInt( data, offset, getNumUniqueStrings() ); + LittleEndian.putInt( data, offset, numUniqueStrings ); + offset += LittleEndianConsts.INT_SIZE; + return offset - bufferIndex; + } + +}
\ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/record/RowRecord.java b/src/java/org/apache/poi/hssf/record/RowRecord.java index 65b627ea55..fc29fcbd26 100644 --- a/src/java/org/apache/poi/hssf/record/RowRecord.java +++ b/src/java/org/apache/poi/hssf/record/RowRecord.java @@ -452,8 +452,8 @@ public class RowRecord LittleEndian.putShort(data, 0 + offset, sid); LittleEndian.putShort(data, 2 + offset, ( short ) 16); LittleEndian.putShort(data, 4 + offset, getRowNumber()); - LittleEndian.putShort(data, 6 + offset, getFirstCol()); - LittleEndian.putShort(data, 8 + offset, getLastCol()); + LittleEndian.putShort(data, 6 + offset, getFirstCol() == -1 ? (short)0 : getFirstCol()); + LittleEndian.putShort(data, 8 + offset, getLastCol() == -1 ? (short)0 : getLastCol()); LittleEndian.putShort(data, 10 + offset, getHeight()); LittleEndian.putShort(data, 12 + offset, getOptimize()); LittleEndian.putShort(data, 14 + offset, field_6_reserved); diff --git a/src/java/org/apache/poi/hssf/record/SSTDeserializer.java b/src/java/org/apache/poi/hssf/record/SSTDeserializer.java new file mode 100644 index 0000000000..c4698df0fb --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/SSTDeserializer.java @@ -0,0 +1,562 @@ +/* ==================================================================== + * 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 + * <http://www.apache.org/>. + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.BinaryTree; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; + +/** + * Handles the task of deserializing a SST string. The two main entry points are + * + * @author Glen Stampoultzis (glens at apache.org) + */ +class SSTDeserializer +{ + + private BinaryTree strings; + /** this is the number of characters we expect in the first sub-record in a subsequent continuation record */ + private int continuationExpectedChars; + /** this is the string we were working on before hitting the end of the current record. This string is NOT finished. */ + private String unfinishedString; + /** this is true if the string uses wide characters */ + private boolean wideChar; + /** this is true if the string is a rich text string */ + private boolean richText; + /** this is true if the string is a far east string or some other wierd string */ + private boolean extendedText; + /** Number of formatting runs in this rich text field */ + private short runCount; + /** Number of characters in current string */ + private int charCount; + private int extensionLength; + + + public SSTDeserializer( BinaryTree strings ) + { + this.strings = strings; + initVars(); + } + + private void initVars() + { + runCount = 0; + continuationExpectedChars = 0; + unfinishedString = ""; +// bytesInCurrentSegment = 0; +// stringDataOffset = 0; + wideChar = false; + richText = false; + extendedText = false; + } + + /** + * This is the starting point where strings are constructed. Note that + * strings may span across multiple continuations. Read the SST record + * carefully before beginning to hack. + */ + public void manufactureStrings( final byte[] data, final int initialOffset, short dataSize ) + { + initVars(); + + int offset = initialOffset; + while ( ( offset - initialOffset ) < dataSize ) + { + int remaining = dataSize - offset + initialOffset; + + if ( ( remaining > 0 ) && ( remaining < LittleEndianConsts.SHORT_SIZE ) ) + { + throw new RecordFormatException( "Cannot get length of the last string in SSTRecord" ); + } + if ( remaining == LittleEndianConsts.SHORT_SIZE ) + { + setContinuationExpectedChars( LittleEndian.getUShort( data, offset ) ); + unfinishedString = ""; + break; + } + charCount = LittleEndian.getUShort( data, offset ); + readStringHeader( data, offset ); + boolean stringContinuesOverContinuation = remaining < totalStringSize(); + if ( stringContinuesOverContinuation ) + { + int remainingBytes = ( initialOffset + dataSize ) - offset - stringHeaderOverhead(); + setContinuationExpectedChars( charCount - calculateCharCount( remainingBytes ) ); + charCount -= getContinuationExpectedChars(); + } + else + { + setContinuationExpectedChars( 0 ); + } + processString( data, offset, charCount ); + offset += totalStringSize(); + if ( getContinuationExpectedChars() != 0 ) + { + break; + } + } + } + +// private void dump( final byte[] data, int offset, int length ) +// { +// try +// { +// System.out.println( "------------------- SST DUMP -------------------------" ); +// HexDump.dump( (byte[]) data, offset, System.out, offset, length ); +// } +// catch ( IOException e ) +// { +// } +// catch ( ArrayIndexOutOfBoundsException e ) +// { +// } +// catch ( IllegalArgumentException e ) +// { +// } +// } + + /** + * Detemines the option types for the string (ie, compressed or uncompressed unicode, rich text string or + * plain string etc) and calculates the length and offset for the string. + * + */ + private void readStringHeader( final byte[] data, final int index ) + { + + byte optionFlag = data[index + LittleEndianConsts.SHORT_SIZE]; + + wideChar = ( optionFlag & 1 ) == 1; + extendedText = ( optionFlag & 4 ) == 4; + richText = ( optionFlag & 8 ) == 8; + runCount = 0; + if ( richText ) + { + runCount = LittleEndian.getShort( data, index + SSTRecord.STRING_MINIMAL_OVERHEAD ); + } + extensionLength = 0; + if ( extendedText ) + { + extensionLength = LittleEndian.getInt( data, index + SSTRecord.STRING_MINIMAL_OVERHEAD + + (richText ? LittleEndianConsts.SHORT_SIZE : 0) ); + } + + } + + + /** + * Reads a string or the first part of a string. + * + * @param characters the number of characters to write. + * + * @return the number of bytes written. + */ + private int processString( final byte[] data, final int dataIndex, final int characters ) + { + + // length is the length we store it as. not the length that is read. + int length = SSTRecord.STRING_MINIMAL_OVERHEAD + calculateByteCount( characters ); + byte[] unicodeStringBuffer = new byte[length]; + + int offset = 0; + + // Set the length in characters + LittleEndian.putUShort( unicodeStringBuffer, offset, characters ); + offset += LittleEndianConsts.SHORT_SIZE; + // Set the option flags + unicodeStringBuffer[offset] = data[dataIndex + offset]; + // Copy in the string data + int bytesRead = unicodeStringBuffer.length - SSTRecord.STRING_MINIMAL_OVERHEAD; + arraycopy( data, dataIndex + stringHeaderOverhead(), unicodeStringBuffer, SSTRecord.STRING_MINIMAL_OVERHEAD, bytesRead ); + // Create the unicode string + UnicodeString string = new UnicodeString( UnicodeString.sid, + (short) unicodeStringBuffer.length, + unicodeStringBuffer ); + + if ( isStringFinished() ) + { + Integer integer = new Integer( strings.size() ); + addToStringTable( strings, integer, string ); + } + else + { + unfinishedString = string.getString(); + } + + return bytesRead; + } + + private boolean isStringFinished() + { + return getContinuationExpectedChars() == 0; + } + + /** + * Okay, we are doing some major cheating here. Because we can't handle rich text strings properly + * we end up getting duplicate strings. To get around this I'm doing two things: 1. Converting rich + * text to normal text and 2. If there's a duplicate I'm adding a space onto the end. Sneaky perhaps + * but it gets the job done until we can handle this a little better. + */ + static public void addToStringTable( BinaryTree strings, Integer integer, UnicodeString string ) + { + + if ( string.isRichText() ) + string.setOptionFlags( (byte) ( string.getOptionFlags() & ( ~8 ) ) ); + if ( string.isExtendedText() ) + string.setOptionFlags( (byte) ( string.getOptionFlags() & ( ~4 ) ) ); + + boolean added = false; + while ( added == false ) + { + try + { + strings.put( integer, string ); + added = true; + } + catch ( Exception ignore ) + { + string.setString( string.getString() + " " ); + } + } + + } + + + private int calculateCharCount( final int byte_count ) + { + return byte_count / ( wideChar ? LittleEndianConsts.SHORT_SIZE : LittleEndianConsts.BYTE_SIZE ); + } + + /** + * Process a Continue record. A Continue record for an SST record + * contains the same kind of data that the SST record contains, + * with the following exceptions: + * <P> + * <OL> + * <LI>The string counts at the beginning of the SST record are + * not in the Continue record + * <LI>The first string in the Continue record might NOT begin + * with a size. If the last string in the previous record is + * continued in this record, the size is determined by that + * last string in the previous record; the first string will + * begin with a flag byte, followed by the remaining bytes (or + * words) of the last string from the previous + * record. Otherwise, the first string in the record will + * begin with a string length + * </OL> + * + * @param record the Continue record's byte data + */ + public void processContinueRecord( final byte[] record ) + { + if ( isStringFinished() ) + { + initVars(); + manufactureStrings( record, 0, (short) record.length ); + } + else + { + // reset the wide bit because that can change across a continuation. the fact that it's + // actually rich text doesn't change across continuations even though the rich text + // may on longer be set in the "new" option flag. confusing huh? + wideChar = ( record[0] & 1 ) == 1; + + if ( stringSpansContinuation( record.length - LittleEndianConsts.BYTE_SIZE ) ) + { + processEntireContinuation( record ); + } + else + { + readStringRemainder( record ); + } + } + + } + + /** + * Reads the remainder string and any subsequent strings from the continuation record. + * + * @param record The entire continuation record data. + */ + private void readStringRemainder( final byte[] record ) + { + int stringRemainderSizeInBytes = calculateByteCount( getContinuationExpectedChars() ); +// stringDataOffset = LittleEndianConsts.BYTE_SIZE; + byte[] unicodeStringData = new byte[SSTRecord.STRING_MINIMAL_OVERHEAD + + calculateByteCount( getContinuationExpectedChars() )]; + + // write the string length + LittleEndian.putShort( unicodeStringData, 0, (short) getContinuationExpectedChars() ); + + // write the options flag + unicodeStringData[LittleEndianConsts.SHORT_SIZE] = createOptionByte( wideChar, richText, extendedText ); + + // copy the bytes/words making up the string; skipping + // past all the overhead of the str_data array + arraycopy( record, LittleEndianConsts.BYTE_SIZE, unicodeStringData, + SSTRecord.STRING_MINIMAL_OVERHEAD, + unicodeStringData.length - SSTRecord.STRING_MINIMAL_OVERHEAD ); + + // use special constructor to create the final string + UnicodeString string = new UnicodeString( UnicodeString.sid, + (short) unicodeStringData.length, unicodeStringData, + unfinishedString ); + Integer integer = new Integer( strings.size() ); + + addToStringTable( strings, integer, string ); + + int newOffset = offsetForContinuedRecord( stringRemainderSizeInBytes ); + manufactureStrings( record, newOffset, (short) ( record.length - newOffset ) ); + } + + /** + * Calculates the size of the string in bytes based on the character width + */ + private int stringSizeInBytes() + { + return calculateByteCount( charCount ); + } + + /** + * Calculates the size of the string in byes. This figure includes all the over + * heads for the string. + */ + private int totalStringSize() + { + return stringSizeInBytes() + + stringHeaderOverhead() + + LittleEndianConsts.INT_SIZE * runCount + + extensionLength; + } + + private int stringHeaderOverhead() + { + return SSTRecord.STRING_MINIMAL_OVERHEAD + + ( richText ? LittleEndianConsts.SHORT_SIZE : 0 ) + + ( extendedText ? LittleEndianConsts.INT_SIZE : 0 ); + } + + private int offsetForContinuedRecord( int stringRemainderSizeInBytes ) + { + return stringRemainderSizeInBytes + LittleEndianConsts.BYTE_SIZE + + runCount * LittleEndianConsts.INT_SIZE + extensionLength; + } + + private byte createOptionByte( boolean wideChar, boolean richText, boolean farEast ) + { + return (byte) ( ( wideChar ? 1 : 0 ) + ( farEast ? 4 : 0 ) + ( richText ? 8 : 0 ) ); + } + + /** + * If the continued record is so long is spans into the next continue then + * simply suck the remaining string data into the existing <code>unfinishedString</code>. + * + * @param record The data from the continuation record. + */ + private void processEntireContinuation( final byte[] record ) + { + // create artificial data to create a UnicodeString + int dataLengthInBytes = record.length - LittleEndianConsts.BYTE_SIZE; + byte[] unicodeStringData = new byte[record.length + LittleEndianConsts.SHORT_SIZE]; + + LittleEndian.putShort( unicodeStringData, (byte) 0, (short) calculateCharCount( dataLengthInBytes ) ); + arraycopy( record, 0, unicodeStringData, LittleEndianConsts.SHORT_SIZE, record.length ); + UnicodeString ucs = new UnicodeString( UnicodeString.sid, (short) unicodeStringData.length, unicodeStringData ); + + unfinishedString = unfinishedString + ucs.getString(); + setContinuationExpectedChars( getContinuationExpectedChars() - calculateCharCount( dataLengthInBytes ) ); + } + + private boolean stringSpansContinuation( int continuationSizeInBytes ) + { + return calculateByteCount( getContinuationExpectedChars() ) > continuationSizeInBytes; + } + + /** + * @return the number of characters we expect in the first + * sub-record in a subsequent continuation record + */ + + int getContinuationExpectedChars() + { + return continuationExpectedChars; + } + + private void setContinuationExpectedChars( final int count ) + { + continuationExpectedChars = count; + } + + private int calculateByteCount( final int character_count ) + { + return character_count * ( wideChar ? LittleEndianConsts.SHORT_SIZE : LittleEndianConsts.BYTE_SIZE ); + } + + + /** + * Copies an array from the specified source array, beginning at the + * specified position, to the specified position of the destination array. + * A subsequence of array components are copied from the source + * array referenced by <code>src</code> to the destination array + * referenced by <code>dst</code>. The number of components copied is + * equal to the <code>length</code> argument. The components at + * positions <code>srcOffset</code> through + * <code>srcOffset+length-1</code> in the source array are copied into + * positions <code>dstOffset</code> through + * <code>dstOffset+length-1</code>, respectively, of the destination + * array. + * <p> + * If the <code>src</code> and <code>dst</code> arguments refer to the + * same array object, then the copying is performed as if the + * components at positions <code>srcOffset</code> through + * <code>srcOffset+length-1</code> were first copied to a temporary + * array with <code>length</code> components and then the contents of + * the temporary array were copied into positions + * <code>dstOffset</code> through <code>dstOffset+length-1</code> of the + * destination array. + * <p> + * If <code>dst</code> is <code>null</code>, then a + * <code>NullPointerException</code> is thrown. + * <p> + * If <code>src</code> is <code>null</code>, then a + * <code>NullPointerException</code> is thrown and the destination + * array is not modified. + * <p> + * Otherwise, if any of the following is true, an + * <code>ArrayStoreException</code> is thrown and the destination is + * not modified: + * <ul> + * <li>The <code>src</code> argument refers to an object that is not an + * array. + * <li>The <code>dst</code> argument refers to an object that is not an + * array. + * <li>The <code>src</code> argument and <code>dst</code> argument refer to + * arrays whose component types are different primitive types. + * <li>The <code>src</code> argument refers to an array with a primitive + * component type and the <code>dst</code> argument refers to an array + * with a reference component type. + * <li>The <code>src</code> argument refers to an array with a reference + * component type and the <code>dst</code> argument refers to an array + * with a primitive component type. + * </ul> + * <p> + * Otherwise, if any of the following is true, an + * <code>IndexOutOfBoundsException</code> is + * thrown and the destination is not modified: + * <ul> + * <li>The <code>srcOffset</code> argument is negative. + * <li>The <code>dstOffset</code> argument is negative. + * <li>The <code>length</code> argument is negative. + * <li><code>srcOffset+length</code> is greater than + * <code>src.length</code>, the length of the source array. + * <li><code>dstOffset+length</code> is greater than + * <code>dst.length</code>, the length of the destination array. + * </ul> + * <p> + * Otherwise, if any actual component of the source array from + * position <code>srcOffset</code> through + * <code>srcOffset+length-1</code> cannot be converted to the component + * type of the destination array by assignment conversion, an + * <code>ArrayStoreException</code> is thrown. In this case, let + * <b><i>k</i></b> be the smallest nonnegative integer less than + * length such that <code>src[srcOffset+</code><i>k</i><code>]</code> + * cannot be converted to the component type of the destination + * array; when the exception is thrown, source array components from + * positions <code>srcOffset</code> through + * <code>srcOffset+</code><i>k</i><code>-1</code> + * will already have been copied to destination array positions + * <code>dstOffset</code> through + * <code>dstOffset+</code><i>k</I><code>-1</code> and no other + * positions of the destination array will have been modified. + * (Because of the restrictions already itemized, this + * paragraph effectively applies only to the situation where both + * arrays have component types that are reference types.) + * + * @param src the source array. + * @param src_position start position in the source array. + * @param dst the destination array. + * @param dst_position pos start position in the destination data. + * @param length the number of array elements to be copied. + * @exception IndexOutOfBoundsException if copying would cause + * access of data outside array bounds. + * @exception ArrayStoreException if an element in the <code>src</code> + * array could not be stored into the <code>dest</code> array + * because of a type mismatch. + * @exception NullPointerException if either <code>src</code> or + * <code>dst</code> is <code>null</code>. + */ + private void arraycopy( byte[] src, int src_position, + byte[] dst, int dst_position, + int length ) + { + System.arraycopy( src, src_position, dst, dst_position, length ); + } + + /** + * @return the unfinished string + */ + String getUnfinishedString() + { + return unfinishedString; + } + + /** + * @return true if current string uses wide characters + */ + boolean isWideChar() + { + return wideChar; + } + + +} diff --git a/src/java/org/apache/poi/hssf/record/SSTRecord.java b/src/java/org/apache/poi/hssf/record/SSTRecord.java index d8428148ab..734a90f6f4 100644 --- a/src/java/org/apache/poi/hssf/record/SSTRecord.java +++ b/src/java/org/apache/poi/hssf/record/SSTRecord.java @@ -1,4 +1,3 @@ - /* ==================================================================== * The Apache Software License, Version 1.1 * @@ -59,7 +58,8 @@ import org.apache.poi.util.BinaryTree; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianConsts; -import java.util.*; +import java.util.Iterator; +import java.util.List; /** * Title: Static String Table Record @@ -71,65 +71,45 @@ import java.util.*; * <P> * @author Andrew C. Oliver (acoliver at apache dot org) * @author Marc Johnson (mjohnson at apache dot org) + * @author Glen Stampoultzis (glens at apache.org) * @version 2.0-pre * @see org.apache.poi.hssf.record.LabelSSTRecord * @see org.apache.poi.hssf.record.ContinueRecord */ public class SSTRecord - extends Record + extends Record { - // how big can an SST record be? As big as any record can be: 8228 - // bytes - private static final int _max = 8228; - - // standard record overhead: two shorts (record id plus data space - // size) - private static final int _std_record_overhead = - 2 * LittleEndianConsts.SHORT_SIZE; - - // SST overhead: the standard record overhead, plus the number of - // strings and the number of unique strings -- two ints - private static final int _sst_record_overhead = - (_std_record_overhead + (2 * LittleEndianConsts.INT_SIZE)); + /** how big can an SST record be? As big as any record can be: 8228 bytes */ + static final int MAX_RECORD_SIZE = 8228; - // how much data can we stuff into an SST record? That would be - // _max minus the standard SST record overhead - private static final int _max_data_space = - _max - _sst_record_overhead; + /** standard record overhead: two shorts (record id plus data space size)*/ + static final int STD_RECORD_OVERHEAD = + 2 * LittleEndianConsts.SHORT_SIZE; - // overhead for each string includes the string's character count - // (a short) and the flag describing its characteristics (a byte) - private static final int _string_minimal_overhead = - LittleEndianConsts.SHORT_SIZE + LittleEndianConsts.BYTE_SIZE; - public static final short sid = 0xfc; + /** SST overhead: the standard record overhead, plus the number of strings and the number of unique strings -- two ints */ + static final int SST_RECORD_OVERHEAD = + ( STD_RECORD_OVERHEAD + ( 2 * LittleEndianConsts.INT_SIZE ) ); - // union of strings in the SST and EXTSST - private int field_1_num_strings; + /** how much data can we stuff into an SST record? That would be _max minus the standard SST record overhead */ + static final int MAX_DATA_SPACE = MAX_RECORD_SIZE - SST_RECORD_OVERHEAD; - // according to docs ONLY SST - private int field_2_num_unique_strings; - private BinaryTree field_3_strings; + /** overhead for each string includes the string's character count (a short) and the flag describing its characteristics (a byte) */ + static final int STRING_MINIMAL_OVERHEAD = LittleEndianConsts.SHORT_SIZE + LittleEndianConsts.BYTE_SIZE; - // this is the number of characters we expect in the first - // sub-record in a subsequent continuation record - private int __expected_chars; + public static final short sid = 0xfc; - // this is the string we were working on before hitting the end of - // the current record. This string is NOT finished. - private String _unfinished_string; + /** union of strings in the SST and EXTSST */ + private int field_1_num_strings; - // this is the total length of the current string being handled - private int _total_length_bytes; + /** according to docs ONLY SST */ + private int field_2_num_unique_strings; + private BinaryTree field_3_strings; - // this is the offset into a string field of the actual string - // data - private int _string_data_offset; - - // this is true if the string uses wide characters - private boolean _wide_char; - private List _record_lengths = null; + /** Record lengths for initial SST record and all continue records */ + private List _record_lengths = null; + private SSTDeserializer deserializer; /** * default constructor @@ -137,14 +117,10 @@ public class SSTRecord public SSTRecord() { - field_1_num_strings = 0; + field_1_num_strings = 0; field_2_num_unique_strings = 0; - field_3_strings = new BinaryTree(); - setExpectedChars(0); - _unfinished_string = ""; - _total_length_bytes = 0; - _string_data_offset = 0; - _wide_char = false; + field_3_strings = new BinaryTree(); + deserializer = new SSTDeserializer(field_3_strings); } /** @@ -156,9 +132,9 @@ public class SSTRecord * @param data of the record (should not contain sid/len) */ - public SSTRecord(final short id, final short size, final byte [] data) + public SSTRecord( final short id, final short size, final byte[] data ) { - super(id, size, data); + super( id, size, data ); } /** @@ -171,10 +147,10 @@ public class SSTRecord * @param offset of the record */ - public SSTRecord(final short id, final short size, final byte [] data, - int offset) + public SSTRecord( final short id, final short size, final byte[] data, + int offset ) { - super(id, size, data, offset); + super( id, size, data, offset ); } /** @@ -192,13 +168,13 @@ public class SSTRecord * @return the index of that string in the table */ - public int addString(final String string) + public int addString( final String string ) { int rval; - if (string == null) + if ( string == null ) { - rval = addString("", false); + rval = addString( "", false ); } else { @@ -207,17 +183,17 @@ public class SSTRecord // present, we have to use 16-bit encoding. Otherwise, we // can use 8-bit encoding boolean useUTF16 = false; - int strlen = string.length(); + int strlen = string.length(); - for (int j = 0; j < strlen; j++) + for ( int j = 0; j < strlen; j++ ) { - if (string.charAt(j) > 255) + if ( string.charAt( j ) > 255 ) { useUTF16 = true; break; } } - rval = addString(string, useUTF16); + rval = addString( string, useUTF16 ); } return rval; } @@ -238,21 +214,21 @@ public class SSTRecord * @return the index of that string in the table */ - public int addString(final String string, final boolean useUTF16) + public int addString( final String string, final boolean useUTF16 ) { field_1_num_strings++; - String str = (string == null) ? "" - : string; - int rval = -1; - UnicodeString ucs = new UnicodeString(); - - ucs.setString(str); - ucs.setCharCount(( short ) str.length()); - ucs.setOptionFlags(( byte ) (useUTF16 ? 1 - : 0)); - Integer integer = ( Integer ) field_3_strings.getKeyForValue(ucs); - - if (integer != null) + String str = ( string == null ) ? "" + : string; + int rval = -1; + UnicodeString ucs = new UnicodeString(); + + ucs.setString( str ); + ucs.setCharCount( (short) str.length() ); + ucs.setOptionFlags( (byte) ( useUTF16 ? 1 + : 0 ) ); + Integer integer = (Integer) field_3_strings.getKeyForValue( ucs ); + + if ( integer != null ) { rval = integer.intValue(); } @@ -263,8 +239,9 @@ public class SSTRecord // strings we've already collected rval = field_3_strings.size(); field_2_num_unique_strings++; - integer = new Integer(rval); - field_3_strings.put(integer, ucs); + integer = new Integer( rval ); + SSTDeserializer.addToStringTable( field_3_strings, integer, ucs ); +// field_3_strings.put( integer, ucs ); } return rval; } @@ -298,7 +275,7 @@ public class SSTRecord * */ - public void setNumStrings(final int count) + public void setNumStrings( final int count ) { field_1_num_strings = count; } @@ -314,7 +291,7 @@ public class SSTRecord * @param count number of strings */ - public void getNumUniqueStrings(final int count) + public void getNumUniqueStrings( final int count ) { field_2_num_unique_strings = count; } @@ -327,16 +304,15 @@ public class SSTRecord * @return the desired string */ - public String getString(final int id) + public String getString( final int id ) { - return (( UnicodeString ) field_3_strings.get(new Integer(id))) - .getString(); + return ( (UnicodeString) field_3_strings.get( new Integer( id ) ) ).getString(); } - public boolean getString16bit(final int id) + public boolean isString16bit( final int id ) { - return ((( UnicodeString ) field_3_strings.get(new Integer(id))) - .getOptionFlags() == 1); + UnicodeString unicodeString = ( (UnicodeString) field_3_strings.get( new Integer( id ) ) ); + return ( ( unicodeString.getOptionFlags() & 0x01 ) == 1 ); } /** @@ -349,326 +325,24 @@ public class SSTRecord { StringBuffer buffer = new StringBuffer(); - buffer.append("[SST]\n"); - buffer.append(" .numstrings = ") - .append(Integer.toHexString(getNumStrings())).append("\n"); - buffer.append(" .uniquestrings = ") - .append(Integer.toHexString(getNumUniqueStrings())).append("\n"); - for (int k = 0; k < field_3_strings.size(); k++) + buffer.append( "[SST]\n" ); + buffer.append( " .numstrings = " ) + .append( Integer.toHexString( getNumStrings() ) ).append( "\n" ); + buffer.append( " .uniquestrings = " ) + .append( Integer.toHexString( getNumUniqueStrings() ) ).append( "\n" ); + for ( int k = 0; k < field_3_strings.size(); k++ ) { - buffer.append(" .string_" + k + " = ") - .append((( UnicodeString ) field_3_strings - .get(new Integer(k))).toString()).append("\n"); + buffer.append( " .string_" + k + " = " ) + .append( ( (UnicodeString) field_3_strings + .get( new Integer( k ) ) ).toString() ).append( "\n" ); } - buffer.append("[/SST]\n"); + buffer.append( "[/SST]\n" ); return buffer.toString(); } /** - * Create a byte array consisting of an SST record and any - * required Continue records, ready to be written out. - * <p> - * If an SST record and any subsequent Continue records are read - * in to create this instance, this method should produce a byte - * array that is identical to the byte array produced by - * concatenating the input records' data. - * - * @return the byte array - */ - - public int serialize(int offset, byte [] data) - { - int rval = getRecordSize(); - int record_length_index = 0; - - // get the linear size of that array - int unicodesize = calculateUnicodeSize(); - - if (unicodesize > _max_data_space) - { - byte[] stringreminant = null; - int unipos = 0; - boolean lastneedcontinue = false; - int stringbyteswritten = 0; - boolean first_record = true; - int totalWritten = 0; - int size = 0; - - while (totalWritten != rval) - { - int pos = 0; - - // write the appropriate header - int available; - - if (first_record) - { - size = - (( Integer ) _record_lengths - .get(record_length_index++)).intValue(); - available = size - 8; - pos = writeSSTHeader(data, - pos + offset - + totalWritten, size); - size += _std_record_overhead; - first_record = false; - } - else - { - pos = 0; - int to_be_written = (unicodesize - stringbyteswritten) - + (lastneedcontinue ? 1 - : 0); // not used? - - size = - (( Integer ) _record_lengths - .get(record_length_index++)).intValue(); - available = size; - pos = writeContinueHeader(data, - pos + offset - + totalWritten, size); - size = size + _std_record_overhead; - } - - // now, write the rest of the data into the current - // record space - if (lastneedcontinue) - { - - // the last string in the previous record was not - // written out completely - if (stringreminant.length <= available) - { - - // write reminant -- it'll all fit neatly - System.arraycopy(stringreminant, 0, data, - pos + offset + totalWritten, - stringreminant.length); - stringbyteswritten += stringreminant.length - 1; - pos += stringreminant.length; - lastneedcontinue = false; - available -= stringreminant.length; - } - else - { - - // write as much of the remnant as possible - System.arraycopy(stringreminant, 0, data, - pos + offset + totalWritten, - available); - stringbyteswritten += available - 1; - pos += available; - byte[] leftover = - new byte[ (stringreminant.length - available) + LittleEndianConsts.BYTE_SIZE ]; - - System.arraycopy(stringreminant, available, leftover, - LittleEndianConsts.BYTE_SIZE, - stringreminant.length - available); - leftover[ 0 ] = stringreminant[ 0 ]; - stringreminant = leftover; - available = 0; - lastneedcontinue = true; - } - } - - // last string's remnant, if any, is cleaned up as - // best as can be done ... now let's try and write - // some more strings - for (; unipos < field_3_strings.size(); unipos++) - { - Integer intunipos = new Integer(unipos); - UnicodeString unistr = - (( UnicodeString ) field_3_strings.get(intunipos)); - - if (unistr.getRecordSize() <= available) - { - unistr.serialize(pos + offset + totalWritten, data); - int rsize = unistr.getRecordSize(); - - stringbyteswritten += rsize; - pos += rsize; - available -= rsize; - } - else - { - - // can't write the entire string out - if (available >= _string_minimal_overhead) - { - - // we can write some of it - byte[] ucs = unistr.serialize(); - - System.arraycopy(ucs, 0, data, - pos + offset + totalWritten, - available); - stringbyteswritten += available; - stringreminant = - new byte[ (ucs.length - available) + LittleEndianConsts.BYTE_SIZE ]; - System.arraycopy(ucs, available, stringreminant, - LittleEndianConsts.BYTE_SIZE, - ucs.length - available); - stringreminant[ 0 ] = - ucs[ LittleEndianConsts.SHORT_SIZE ]; - available = 0; - lastneedcontinue = true; - unipos++; - } - break; - } - } - totalWritten += size; - } - } - else - { - - // short data: write one simple SST record - int datasize = _sst_record_overhead + unicodesize; // not used? - - writeSSTHeader( - data, 0 + offset, - _sst_record_overhead - + (( Integer ) _record_lengths.get( - record_length_index++)).intValue() - _std_record_overhead); - int pos = _sst_record_overhead; - - for (int k = 0; k < field_3_strings.size(); k++) - { - UnicodeString unistr = - (( UnicodeString ) field_3_strings.get(new Integer(k))); - - System.arraycopy(unistr.serialize(), 0, data, pos + offset, - unistr.getRecordSize()); - pos += unistr.getRecordSize(); - } - } - return rval; - } - - // not used: remove? - private int calculateStringsize() - { - int retval = 0; - - for (int k = 0; k < field_3_strings.size(); k++) - { - retval += - (( UnicodeString ) field_3_strings.get(new Integer(k))) - .getRecordSize(); - } - return retval; - } - - /** - * Process a Continue record. A Continue record for an SST record - * contains the same kind of data that the SST record contains, - * with the following exceptions: - * <P> - * <OL> - * <LI>The string counts at the beginning of the SST record are - * not in the Continue record - * <LI>The first string in the Continue record might NOT begin - * with a size. If the last string in the previous record is - * continued in this record, the size is determined by that - * last string in the previous record; the first string will - * begin with a flag byte, followed by the remaining bytes (or - * words) of the last string from the previous - * record. Otherwise, the first string in the record will - * begin with a string length - * </OL> - * - * @param record the Continue record's byte data - */ - - public void processContinueRecord(final byte [] record) - { - if (getExpectedChars() == 0) - { - _unfinished_string = ""; - _total_length_bytes = 0; - _string_data_offset = 0; - _wide_char = false; - manufactureStrings(record, 0, ( short ) record.length); - } - else - { - int data_length = record.length - LittleEndianConsts.BYTE_SIZE; - - if (calculateByteCount(getExpectedChars()) > data_length) - { - - // create artificial data to create a UnicodeString - byte[] input = - new byte[ record.length + LittleEndianConsts.SHORT_SIZE ]; - short size = ( short ) (((record[ 0 ] & 1) == 1) - ? (data_length - / LittleEndianConsts.SHORT_SIZE) - : (data_length - / LittleEndianConsts.BYTE_SIZE)); - - LittleEndian.putShort(input, ( byte ) 0, size); - System.arraycopy(record, 0, input, - LittleEndianConsts.SHORT_SIZE, - record.length); - UnicodeString ucs = new UnicodeString(UnicodeString.sid, - ( short ) input.length, - input); - - _unfinished_string = _unfinished_string + ucs.getString(); - setExpectedChars(getExpectedChars() - size); - } - else - { - setupStringParameters(record, -LittleEndianConsts.SHORT_SIZE, - getExpectedChars()); - byte[] str_data = new byte[ _total_length_bytes ]; - int length = _string_minimal_overhead - + (calculateByteCount(getExpectedChars())); - byte[] bstring = new byte[ length ]; - - // Copy data from the record into the string - // buffer. Copy skips the length of a short in the - // string buffer, to leave room for the string length. - System.arraycopy(record, 0, str_data, - LittleEndianConsts.SHORT_SIZE, - str_data.length - - LittleEndianConsts.SHORT_SIZE); - - // write the string length - LittleEndian.putShort(bstring, 0, - ( short ) getExpectedChars()); - - // write the options flag - bstring[ LittleEndianConsts.SHORT_SIZE ] = - str_data[ LittleEndianConsts.SHORT_SIZE ]; - - // copy the bytes/words making up the string; skipping - // past all the overhead of the str_data array - System.arraycopy(str_data, _string_data_offset, bstring, - _string_minimal_overhead, - bstring.length - _string_minimal_overhead); - - // use special constructor to create the final string - UnicodeString string = - new UnicodeString(UnicodeString.sid, - ( short ) bstring.length, bstring, - _unfinished_string); - Integer integer = new Integer(field_3_strings.size()); - - field_3_strings.put(integer, string); - manufactureStrings(record, - _total_length_bytes - - LittleEndianConsts - .SHORT_SIZE, ( short ) record.length); - } - } - } - - /** * @return sid */ - public short getSid() { return sid; @@ -677,30 +351,23 @@ public class SSTRecord /** * @return hashcode */ - public int hashCode() { return field_2_num_unique_strings; } - /** - * - * @param o - * @return true if equal - */ - - public boolean equals(Object o) + public boolean equals( Object o ) { - if ((o == null) || (o.getClass() != this.getClass())) + if ( ( o == null ) || ( o.getClass() != this.getClass() ) ) { return false; } - SSTRecord other = ( SSTRecord ) o; + SSTRecord other = (SSTRecord) o; - return ((field_1_num_strings == other - .field_1_num_strings) && (field_2_num_unique_strings == other - .field_2_num_unique_strings) && field_3_strings - .equals(other.field_3_strings)); + return ( ( field_1_num_strings == other + .field_1_num_strings ) && ( field_2_num_unique_strings == other + .field_2_num_unique_strings ) && field_3_strings + .equals( other.field_3_strings ) ); } /** @@ -711,12 +378,12 @@ public class SSTRecord * @exception RecordFormatException if validation fails */ - protected void validateSid(final short id) - throws RecordFormatException + protected void validateSid( final short id ) + throws RecordFormatException { - if (id != sid) + if ( id != sid ) { - throw new RecordFormatException("NOT An SST RECORD"); + throw new RecordFormatException( "NOT An SST RECORD" ); } } @@ -800,33 +467,20 @@ public class SSTRecord * @param size size of the raw data */ - protected void fillFields(final byte [] data, final short size, - int offset) + protected void fillFields( final byte[] data, final short size, + int offset ) { // this method is ALWAYS called after construction -- using // the nontrivial constructor, of course -- so this is where // we initialize our fields - field_1_num_strings = LittleEndian.getInt(data, 0 + offset); - field_2_num_unique_strings = LittleEndian.getInt(data, 4 + offset); - field_3_strings = new BinaryTree(); - setExpectedChars(0); - _unfinished_string = ""; - _total_length_bytes = 0; - _string_data_offset = 0; - _wide_char = false; - manufactureStrings(data, 8 + offset, size); + field_1_num_strings = LittleEndian.getInt( data, 0 + offset ); + field_2_num_unique_strings = LittleEndian.getInt( data, 4 + offset ); + field_3_strings = new BinaryTree(); + deserializer = new SSTDeserializer(field_3_strings); + deserializer.manufactureStrings( data, 8 + offset, (short)(size - 8) ); } - /** - * @return the number of characters we expect in the first - * sub-record in a subsequent continuation record - */ - - int getExpectedChars() - { - return __expected_chars; - } /** * @return an iterator of the strings we hold. All instances are @@ -848,372 +502,43 @@ public class SSTRecord } /** - * @return the unfinished string + * called by the class that is responsible for writing this sucker. + * Subclasses should implement this so that their data is passed back in a + * byte array. + * + * @return byte array containing instance data */ - String getUnfinishedString() + public int serialize( int offset, byte[] data ) { - return _unfinished_string; + SSTSerializer serializer = new SSTSerializer( + _record_lengths, field_3_strings, getNumStrings(), getNumUniqueStrings() ); + return serializer.serialize( offset, data ); } - /** - * @return the total length of the current string - */ - int getTotalLength() + // we can probably simplify this later...this calculates the size + // w/o serializing but still is a bit slow + public int getRecordSize() { - return _total_length_bytes; - } + SSTSerializer serializer = new SSTSerializer( + _record_lengths, field_3_strings, getNumStrings(), getNumUniqueStrings() ); - /** - * @return offset into current string data - */ + return serializer.getRecordSize(); + } - int getStringDataOffset() + SSTDeserializer getDeserializer() { - return _string_data_offset; + return deserializer; } /** - * @return true if current string uses wide characters + * Strange to handle continue records this way. Is it a smell? */ - - boolean isWideChar() - { - return _wide_char; - } - - private int writeSSTHeader(final byte [] data, final int pos, - final int recsize) - { - int offset = pos; - - LittleEndian.putShort(data, offset, sid); - offset += LittleEndianConsts.SHORT_SIZE; - LittleEndian.putShort(data, offset, ( short ) (recsize)); - offset += LittleEndianConsts.SHORT_SIZE; - LittleEndian.putInt(data, offset, getNumStrings()); - offset += LittleEndianConsts.INT_SIZE; - LittleEndian.putInt(data, offset, getNumUniqueStrings()); - offset += LittleEndianConsts.INT_SIZE; - return offset - pos; - } - - private int writeContinueHeader(final byte [] data, final int pos, - final int recsize) - { - int offset = pos; - - LittleEndian.putShort(data, offset, ContinueRecord.sid); - offset += LittleEndianConsts.SHORT_SIZE; - LittleEndian.putShort(data, offset, ( short ) (recsize)); - offset += LittleEndianConsts.SHORT_SIZE; - return offset - pos; - } - - private int calculateUCArrayLength(final byte [][] ucarray) - { - int retval = 0; - - for (int k = 0; k < ucarray.length; k++) - { - retval += ucarray[ k ].length; - } - return retval; - } - - private void manufactureStrings(final byte [] data, final int index, - short size) - { - int offset = index; - - while (offset < size) - { - int remaining = size - offset; - - if ((remaining > 0) - && (remaining < LittleEndianConsts.SHORT_SIZE)) - { - throw new RecordFormatException( - "Cannot get length of the last string in SSTRecord"); - } - if (remaining == LittleEndianConsts.SHORT_SIZE) - { - setExpectedChars(LittleEndian.getShort(data, offset)); - _unfinished_string = ""; - break; - } - short char_count = LittleEndian.getShort(data, offset); - - setupStringParameters(data, offset, char_count); - if (remaining < _total_length_bytes) - { - setExpectedChars(calculateCharCount(_total_length_bytes - - remaining)); - char_count -= getExpectedChars(); - _total_length_bytes = remaining; - } - else - { - setExpectedChars(0); - } - processString(data, offset, char_count); - offset += _total_length_bytes; - if (getExpectedChars() != 0) - { - break; - } - } - } - - private void setupStringParameters(final byte [] data, final int index, - final int char_count) - { - byte flag = data[ index + LittleEndianConsts.SHORT_SIZE ]; - - _wide_char = (flag & 1) == 1; - boolean extended = (flag & 4) == 4; - boolean formatted_run = (flag & 8) == 8; - - _total_length_bytes = _string_minimal_overhead - + calculateByteCount(char_count); - _string_data_offset = _string_minimal_overhead; - if (formatted_run) - { - short run_count = LittleEndian.getShort(data, - index - + _string_data_offset); - - _string_data_offset += LittleEndianConsts.SHORT_SIZE; - _total_length_bytes += LittleEndianConsts.SHORT_SIZE - + (LittleEndianConsts.INT_SIZE - * run_count); - } - if (extended) - { - int extension_length = LittleEndian.getInt(data, - index - + _string_data_offset); - - _string_data_offset += LittleEndianConsts.INT_SIZE; - _total_length_bytes += LittleEndianConsts.INT_SIZE - + extension_length; - } - } - - private void processString(final byte [] data, final int index, - final short char_count) - { - byte[] str_data = new byte[ _total_length_bytes ]; - int length = _string_minimal_overhead - + calculateByteCount(char_count); - byte[] bstring = new byte[ length ]; - - System.arraycopy(data, index, str_data, 0, str_data.length); - int offset = 0; - - LittleEndian.putShort(bstring, offset, char_count); - offset += LittleEndianConsts.SHORT_SIZE; - bstring[ offset ] = str_data[ offset ]; - System.arraycopy(str_data, _string_data_offset, bstring, - _string_minimal_overhead, - bstring.length - _string_minimal_overhead); - UnicodeString string = new UnicodeString(UnicodeString.sid, - ( short ) bstring.length, - bstring); - - if (getExpectedChars() != 0) - { - _unfinished_string = string.getString(); - } - else - { - Integer integer = new Integer(field_3_strings.size()); - - field_3_strings.put(integer, string); - } - } - - private void setExpectedChars(final int count) - { - __expected_chars = count; - } - - private int calculateByteCount(final int character_count) - { - return character_count * (_wide_char ? LittleEndianConsts.SHORT_SIZE - : LittleEndianConsts.BYTE_SIZE); - } - - private int calculateCharCount(final int byte_count) + public void processContinueRecord( byte[] record ) { - return byte_count / (_wide_char ? LittleEndianConsts.SHORT_SIZE - : LittleEndianConsts.BYTE_SIZE); + deserializer.processContinueRecord( record ); } +} - // we can probably simplify this later...this calculates the size - // w/o serializing but still is a bit slow - public int getRecordSize() - { - _record_lengths = new ArrayList(); - int retval = 0; - int unicodesize = calculateUnicodeSize(); - - if (unicodesize > _max_data_space) - { - UnicodeString unistr = null; - int stringreminant = 0; - int unipos = 0; - boolean lastneedcontinue = false; - int stringbyteswritten = 0; - boolean finished = false; - boolean first_record = true; - int totalWritten = 0; - - while (!finished) - { - int record = 0; - int pos = 0; - - if (first_record) - { - - // writing SST record - record = _max; - pos = 12; - first_record = false; - _record_lengths.add(new Integer(record - - _std_record_overhead)); - } - else - { - - // writing continue record - pos = 0; - int to_be_written = (unicodesize - stringbyteswritten) - + (lastneedcontinue ? 1 - : 0); - int size = Math.min(_max - _std_record_overhead, - to_be_written); - - if (size == to_be_written) - { - finished = true; - } - record = size + _std_record_overhead; - _record_lengths.add(new Integer(size)); - pos = 4; - } - if (lastneedcontinue) - { - int available = _max - pos; - - if (stringreminant <= available) - { - - // write reminant - stringbyteswritten += stringreminant - 1; - pos += stringreminant; - lastneedcontinue = false; - } - else - { - - // write as much of the remnant as possible - int toBeWritten = unistr.maxBrokenLength(available); - - if (available != toBeWritten) - { - int shortrecord = record - - (available - toBeWritten); - - _record_lengths.set( - _record_lengths.size() - 1, - new Integer( - shortrecord - _std_record_overhead)); - record = shortrecord; - } - stringbyteswritten += toBeWritten - 1; - pos += toBeWritten; - stringreminant -= toBeWritten - 1; - lastneedcontinue = true; - } - } - for (; unipos < field_3_strings.size(); unipos++) - { - int available = _max - pos; - Integer intunipos = new Integer(unipos); - - unistr = - (( UnicodeString ) field_3_strings.get(intunipos)); - if (unistr.getRecordSize() <= available) - { - stringbyteswritten += unistr.getRecordSize(); - pos += unistr.getRecordSize(); - } - else - { - if (available >= _string_minimal_overhead) - { - int toBeWritten = - unistr.maxBrokenLength(available); - - stringbyteswritten += toBeWritten; - stringreminant = - (unistr.getRecordSize() - toBeWritten) - + LittleEndianConsts.BYTE_SIZE; - if (available != toBeWritten) - { - int shortrecord = record - - (available - toBeWritten); - - _record_lengths.set( - _record_lengths.size() - 1, - new Integer( - shortrecord - _std_record_overhead)); - record = shortrecord; - } - lastneedcontinue = true; - unipos++; - } - else - { - int shortrecord = record - available; - - _record_lengths.set( - _record_lengths.size() - 1, - new Integer( - shortrecord - _std_record_overhead)); - record = shortrecord; - } - break; - } - } - totalWritten += record; - } - retval = totalWritten; - } - else - { - - // short data: write one simple SST record - retval = _sst_record_overhead + unicodesize; - _record_lengths.add(new Integer(unicodesize)); - } - return retval; - } - - private int calculateUnicodeSize() - { - int retval = 0; - - for (int k = 0; k < field_3_strings.size(); k++) - { - UnicodeString string = - ( UnicodeString ) field_3_strings.get(new Integer(k)); - retval += string.getRecordSize(); - } - return retval; - } -} diff --git a/src/java/org/apache/poi/hssf/record/SSTSerializer.java b/src/java/org/apache/poi/hssf/record/SSTSerializer.java new file mode 100644 index 0000000000..5802279145 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/SSTSerializer.java @@ -0,0 +1,356 @@ +/* ==================================================================== + * 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 + * <http://www.apache.org/>. + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.BinaryTree; +import org.apache.poi.util.LittleEndianConsts; + +import java.util.List; +import java.util.ArrayList; + +/** + * This class handles serialization of SST records. It utilizes the record processor + * class write individual records. This has been refactored from the SSTRecord class. + * + * @author Glen Stampoultzis (glens at apache.org) + */ +class SSTSerializer +{ + + private List recordLengths; + private BinaryTree strings; + private int numStrings; + private int numUniqueStrings; + private SSTRecordHeader sstRecordHeader; + + public SSTSerializer( List recordLengths, BinaryTree strings, int numStrings, int numUniqueStrings ) + { + this.recordLengths = recordLengths; + this.strings = strings; + this.numStrings = numStrings; + this.numUniqueStrings = numUniqueStrings; + this.sstRecordHeader = new SSTRecordHeader(numStrings, numUniqueStrings); + } + + /** + * Create a byte array consisting of an SST record and any + * required Continue records, ready to be written out. + * <p> + * If an SST record and any subsequent Continue records are read + * in to create this instance, this method should produce a byte + * array that is identical to the byte array produced by + * concatenating the input records' data. + * + * @return the byte array + */ + public int serialize( int offset, byte[] data ) + { + int record_size = getRecordSize(); + int record_length_index = 0; + + if ( calculateUnicodeSize() > SSTRecord.MAX_DATA_SPACE ) + serializeLargeRecord( record_size, record_length_index, data, offset ); + else + serializeSingleSSTRecord( data, offset, record_length_index ); + return record_size; + } + + private int calculateUnicodeSize() + { + int retval = 0; + + for ( int k = 0; k < strings.size(); k++ ) + { + retval += getUnicodeString(k).getRecordSize(); + } + return retval; + } + + // we can probably simplify this later...this calculates the size + // w/o serializing but still is a bit slow + public int getRecordSize() + { + recordLengths = new ArrayList(); + int retval = 0; + int unicodesize = calculateUnicodeSize(); + + if ( unicodesize > SSTRecord.MAX_DATA_SPACE ) + { + retval = calcRecordSizesForLongStrings( unicodesize ); + } + else + { + // short data: write one simple SST record + retval = SSTRecord.SST_RECORD_OVERHEAD + unicodesize; + recordLengths.add( new Integer( unicodesize ) ); + } + return retval; + } + + private int calcRecordSizesForLongStrings( int unicodesize ) + { + int retval; + UnicodeString unistr = null; + int stringreminant = 0; + int unipos = 0; + boolean lastneedcontinue = false; + int stringbyteswritten = 0; + boolean finished = false; + boolean first_record = true; + int totalWritten = 0; + + while ( !finished ) + { + int record = 0; + int pos = 0; + + if ( first_record ) + { + + // writing SST record + record = SSTRecord.MAX_RECORD_SIZE; + pos = 12; + first_record = false; + recordLengths.add( new Integer( record - SSTRecord.STD_RECORD_OVERHEAD ) ); + } + else + { + + // writing continue record + pos = 0; + int to_be_written = ( unicodesize - stringbyteswritten ) + ( lastneedcontinue ? 1 : 0 ); + int size = Math.min( SSTRecord.MAX_RECORD_SIZE - SSTRecord.STD_RECORD_OVERHEAD, to_be_written ); + + if ( size == to_be_written ) + { + finished = true; + } + record = size + SSTRecord.STD_RECORD_OVERHEAD; + recordLengths.add( new Integer( size ) ); + pos = 4; + } + if ( lastneedcontinue ) + { + int available = SSTRecord.MAX_RECORD_SIZE - pos; + + if ( stringreminant <= available ) + { + + // write reminant + stringbyteswritten += stringreminant - 1; + pos += stringreminant; + lastneedcontinue = false; + } + else + { + + // write as much of the remnant as possible + int toBeWritten = unistr.maxBrokenLength( available ); + + if ( available != toBeWritten ) + { + int shortrecord = record - ( available - toBeWritten ); + recordLengths.set( recordLengths.size() - 1, + new Integer( shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) ); + record = shortrecord; + } + stringbyteswritten += toBeWritten - 1; + pos += toBeWritten; + stringreminant -= toBeWritten - 1; + lastneedcontinue = true; + } + } + for ( ; unipos < strings.size(); unipos++ ) + { + int available = SSTRecord.MAX_RECORD_SIZE - pos; + Integer intunipos = new Integer( unipos ); + + unistr = ( (UnicodeString) strings.get( intunipos ) ); + if ( unistr.getRecordSize() <= available ) + { + stringbyteswritten += unistr.getRecordSize(); + pos += unistr.getRecordSize(); + } + else + { + if ( available >= SSTRecord.STRING_MINIMAL_OVERHEAD ) + { + int toBeWritten = + unistr.maxBrokenLength( available ); + + stringbyteswritten += toBeWritten; + stringreminant = + ( unistr.getRecordSize() - toBeWritten ) + + LittleEndianConsts.BYTE_SIZE; + if ( available != toBeWritten ) + { + int shortrecord = record + - ( available - toBeWritten ); + + recordLengths.set( + recordLengths.size() - 1, + new Integer( + shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) ); + record = shortrecord; + } + lastneedcontinue = true; + unipos++; + } + else + { + int shortrecord = record - available; + + recordLengths.set( recordLengths.size() - 1, + new Integer( shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) ); + record = shortrecord; + } + break; + } + } + totalWritten += record; + } + retval = totalWritten; + + return retval; + } + + + private void serializeSingleSSTRecord( byte[] data, int offset, int record_length_index ) + { + // short data: write one simple SST record + + int len = ( (Integer) recordLengths.get( record_length_index++ ) ).intValue(); + int recordSize = SSTRecord.SST_RECORD_OVERHEAD + len - SSTRecord.STD_RECORD_OVERHEAD; + sstRecordHeader.writeSSTHeader( data, 0 + offset, recordSize ); + int pos = SSTRecord.SST_RECORD_OVERHEAD; + + for ( int k = 0; k < strings.size(); k++ ) + { +// UnicodeString unistr = ( (UnicodeString) strings.get( new Integer( k ) ) ); + System.arraycopy( getUnicodeString(k).serialize(), 0, data, pos + offset, getUnicodeString(k).getRecordSize() ); + pos += getUnicodeString(k).getRecordSize(); + } + } + + /** + * Large records are serialized to an SST and to one or more CONTINUE records. Joy. They have the special + * characteristic that they can change the option field when a single string is split across to a + * CONTINUE record. + */ + private void serializeLargeRecord( int record_size, int record_length_index, byte[] buffer, int offset ) + { + + byte[] stringReminant = null; + int stringIndex = 0; + boolean lastneedcontinue = false; + boolean first_record = true; + int totalWritten = 0; + + while ( totalWritten != record_size ) + { + int recordLength = ( (Integer) recordLengths.get( record_length_index++ ) ).intValue(); + RecordProcessor recordProcessor = new RecordProcessor( buffer, + recordLength, numStrings, numUniqueStrings ); + + // write the appropriate header + recordProcessor.writeRecordHeader( offset, totalWritten, recordLength, first_record ); + first_record = false; + + // now, write the rest of the data into the current + // record space + if ( lastneedcontinue ) + { + lastneedcontinue = stringReminant.length > recordProcessor.getAvailable(); + // the last string in the previous record was not written out completely + stringReminant = recordProcessor.writeStringRemainder( lastneedcontinue, + stringReminant, offset, totalWritten ); + } + + // last string's remnant, if any, is cleaned up as best as can be done ... now let's try and write + // some more strings + for ( ; stringIndex < strings.size(); stringIndex++ ) + { + UnicodeString unistr = getUnicodeString( stringIndex ); + + if ( unistr.getRecordSize() <= recordProcessor.getAvailable() ) + { + recordProcessor.writeWholeString( unistr, offset, totalWritten ); + } + else + { + + // can't write the entire string out + if ( recordProcessor.getAvailable() >= SSTRecord.STRING_MINIMAL_OVERHEAD ) + { + + // we can write some of it + stringReminant = recordProcessor.writePartString( unistr, offset, totalWritten ); + lastneedcontinue = true; + stringIndex++; + } + break; + } + } + totalWritten += recordLength + SSTRecord.STD_RECORD_OVERHEAD; + } + } + + private UnicodeString getUnicodeString( int index ) + { + Integer intunipos = new Integer( index ); + return ( (UnicodeString) strings.get( intunipos ) ); + } + +} diff --git a/src/java/org/apache/poi/hssf/record/UnicodeString.java b/src/java/org/apache/poi/hssf/record/UnicodeString.java index 097be19b1c..d56b660d43 100644 --- a/src/java/org/apache/poi/hssf/record/UnicodeString.java +++ b/src/java/org/apache/poi/hssf/record/UnicodeString.java @@ -66,6 +66,7 @@ import org.apache.poi.util.StringUtil; * REFERENCE: PG 264 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> * @author Andrew C. Oliver * @author Marc Johnson (mjohnson at apache dot org) + * @author Glen Stampoultzis (glens at apache.org) * @version 2.0-pre */ @@ -77,12 +78,29 @@ public class UnicodeString private short field_1_charCount; // = 0; private byte field_2_optionflags; // = 0; private String field_3_string; // = null; + private final int RICH_TEXT_BIT = 8; + private final int EXT_BIT = 4; + + public UnicodeString() + { + } + public int hashCode() { - return field_1_charCount; + int stringHash = 0; + if (field_3_string != null) + stringHash = field_3_string.hashCode(); + return field_1_charCount + stringHash; } + /** + * Our handling of equals is inconsistent with compareTo. The trouble is because we don't truely understand + * rich text fields yet it's difficult to make a sound comparison. + * + * @param o The object to compare. + * @return true if the object is actually equal. + */ public boolean equals(Object o) { if ((o == null) || (o.getClass() != this.getClass())) @@ -96,10 +114,6 @@ public class UnicodeString && field_3_string.equals(other.field_3_string)); } - public UnicodeString() - { - } - /** * construct a unicode string record and fill its fields, ID is ignored * @param id - ignored @@ -278,19 +292,10 @@ public class UnicodeString public int serialize(int offset, byte [] data) { - int charsize = 1; - - if (getOptionFlags() == 1) - { - charsize = 2; - } - - // byte[] retval = new byte[ 3 + (getString().length() * charsize) ]; LittleEndian.putShort(data, 0 + offset, getCharCount()); data[ 2 + offset ] = getOptionFlags(); -// System.out.println("Unicode: We've got "+retval[2]+" for our option flag"); - if (getOptionFlags() == 0) + if (!isUncompressedUnicode()) { StringUtil.putCompressedUnicode(getString(), data, 0x3 + offset); } @@ -302,14 +307,14 @@ public class UnicodeString return getRecordSize(); } - public int getRecordSize() + private boolean isUncompressedUnicode() { - int charsize = 1; + return (getOptionFlags() & 0x01) == 1; + } - if (getOptionFlags() == 1) - { - charsize = 2; - } + public int getRecordSize() + { + int charsize = isUncompressedUnicode() ? 2 : 1; return 3 + (getString().length() * charsize); } @@ -338,11 +343,16 @@ public class UnicodeString return this.getString().compareTo(str.getString()); } + public boolean isRichText() + { + return (getOptionFlags() & RICH_TEXT_BIT) != 0; + } + int maxBrokenLength(final int proposedBrokenLength) { int rval = proposedBrokenLength; - if ((field_2_optionflags & 1) == 1) + if (isUncompressedUnicode()) { int proposedStringLength = proposedBrokenLength - 3; @@ -355,12 +365,9 @@ public class UnicodeString return rval; } -// public boolean equals(Object obj) { -// if (!(obj instanceof UnicodeString)) return false; -// -// UnicodeString str = (UnicodeString)obj; -// -// -// return this.getString().equals(str.getString()); -// } + public boolean isExtendedText() + { + return (getOptionFlags() & EXT_BIT) != 0; + } + } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java b/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java index 39da13e42c..e9209800e3 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java @@ -126,8 +126,8 @@ public class HSSFRow this.sheet = sheet; row = new RowRecord(); row.setHeight((short) 0xff); - row.setLastCol((short)-1); - row.setFirstCol((short)-1); + row.setLastCol((short) -1); + row.setFirstCol((short) -1); // row.setRowNumber(rowNum); setRowNum(rowNum); @@ -213,11 +213,11 @@ public class HSSFRow if (cell.getCellNum() == row.getLastCol()) { - row.setLastCol( findLastCell(row.getLastCol()) ); + row.setLastCol(findLastCell(row.getLastCol())); } if (cell.getCellNum() == row.getFirstCol()) { - row.setFirstCol( findFirstCell(row.getFirstCol()) ); + row.setFirstCol(findFirstCell(row.getFirstCol())); } } @@ -270,11 +270,11 @@ public class HSSFRow { if (row.getFirstCol() == -1) { - row.setFirstCol( cell.getCellNum() ); + row.setFirstCol(cell.getCellNum()); } if (row.getLastCol() == -1) { - row.setLastCol( cell.getCellNum() ); + row.setLastCol(cell.getCellNum()); } cells.put(new Integer(cell.getCellNum()), cell); @@ -292,8 +292,8 @@ public class HSSFRow * get the hssfcell representing a given column (logical cell) 0-based. If you * ask for a cell that is not defined....you get a null. * - * @param cellnum - 0 based column number - * @returns HSSFCell representing that column or null if undefined. + * @param cellnum 0 based column number + * @return HSSFCell representing that column or null if undefined. */ public HSSFCell getCell(short cellnum) @@ -318,7 +318,10 @@ public class HSSFRow public short getFirstCellNum() { - return row.getFirstCol(); + if (getPhysicalNumberOfCells() == 0) + return -1; + else + return row.getFirstCol(); } /** @@ -328,7 +331,10 @@ public class HSSFRow public short getLastCellNum() { - return row.getLastCol(); + if (getPhysicalNumberOfCells() == 0) + return -1; + else + return row.getLastCol(); } @@ -441,7 +447,7 @@ public class HSSFRow } /** - * @returns cell iterator of the physically defined cells. Note element 4 may + * @return cell iterator of the physically defined cells. Note element 4 may * actually be row cell depending on how many are defined! */ diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index ddb5dc8a65..c6cb967622 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -1,4 +1,3 @@ - /* ==================================================================== * The Apache Software License, Version 1.1 * @@ -60,11 +59,14 @@ */ package org.apache.poi.hssf.usermodel; -import org.apache.poi.util.POILogFactory; import org.apache.poi.hssf.model.Sheet; import org.apache.poi.hssf.model.Workbook; -import org.apache.poi.hssf.record.*; +import org.apache.poi.hssf.record.CellValueRecordInterface; +import org.apache.poi.hssf.record.RowRecord; +import org.apache.poi.hssf.record.VCenterRecord; +import org.apache.poi.hssf.record.WSBoolRecord; import org.apache.poi.hssf.util.Region; +import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import java.util.Iterator; @@ -74,12 +76,12 @@ import java.util.TreeMap; * High level representation of a worksheet. * @author Andrew C. Oliver (acoliver at apache dot org) * @author Glen Stampoultzis (glens at apache.org) - * @version 1.0-pre + * @author Libin Roman (romal at vistaportal.com) */ public class HSSFSheet { - private static final int DEBUG = POILogger.DEBUG; + private static final int DEBUG = POILogger.DEBUG; /** * Used for compile-time optimization. This is the initial size for the collection of @@ -87,17 +89,17 @@ public class HSSFSheet * by setting this to a higher number and recompiling a custom edition of HSSFSheet. */ - public final static int INITIAL_CAPACITY = 20; + public final static int INITIAL_CAPACITY = 20; /** * reference to the low level Sheet object */ - private Sheet sheet; - private TreeMap rows; - private Workbook book; - private int firstrow; - private int lastrow; + private Sheet sheet; + private TreeMap rows; + private Workbook book; + private int firstrow; + private int lastrow; private static POILogger log = POILogFactory.getLogger(HSSFSheet.class); /** @@ -110,8 +112,8 @@ public class HSSFSheet protected HSSFSheet(Workbook book) { - sheet = Sheet.createSheet(); - rows = new TreeMap(); // new ArrayList(INITIAL_CAPACITY); + sheet = Sheet.createSheet(); + rows = new TreeMap(); // new ArrayList(INITIAL_CAPACITY); this.book = book; } @@ -127,16 +129,11 @@ public class HSSFSheet protected HSSFSheet(Workbook book, Sheet sheet) { this.sheet = sheet; - rows = new TreeMap(); - this.book = book; + rows = new TreeMap(); + this.book = book; setPropertiesFromSheet(sheet); } - /** private default constructor prevents bogus initializationless construction */ - - private HSSFSheet() - { - } /** * used internally to set the properties given a Sheet object @@ -144,8 +141,8 @@ public class HSSFSheet private void setPropertiesFromSheet(Sheet sheet) { - int sloc = sheet.getLoc(); - RowRecord row = sheet.getNextRow(); + int sloc = sheet.getLoc(); + RowRecord row = sheet.getNextRow(); while (row != null) { @@ -154,8 +151,8 @@ public class HSSFSheet row = sheet.getNextRow(); } sheet.setLoc(sloc); - CellValueRecordInterface cval = sheet.getNextValueRecord(); - long timestart = System.currentTimeMillis(); + CellValueRecordInterface cval = sheet.getNextValueRecord(); + long timestart = System.currentTimeMillis(); log.log(DEBUG, "Time at start of cell creating in HSSF sheet = ", new Long(timestart)); @@ -163,8 +160,8 @@ public class HSSFSheet while (cval != null) { - long cellstart = System.currentTimeMillis(); - HSSFRow hrow = lastrow; + long cellstart = System.currentTimeMillis(); + HSSFRow hrow = lastrow; if ((lastrow == null) || (lastrow.getRowNum() != cval.getRow())) { @@ -236,10 +233,10 @@ public class HSSFSheet while (iter.hasNext()) { - HSSFCell cell = ( HSSFCell ) iter.next(); + HSSFCell cell = (HSSFCell) iter.next(); sheet.removeValueRecord(row.getRowNum(), - cell.getCellValueRecord()); + cell.getCellValueRecord()); } sheet.removeRow(row.getRowRecord()); } @@ -251,10 +248,10 @@ public class HSSFSheet private int findLastRow(int lastrow) { - int rownum = lastrow - 1; - HSSFRow r = getRow(rownum); + int rownum = lastrow - 1; + HSSFRow r = getRow(rownum); - while (r == null) + while (r == null && rownum >= 0) { r = getRow(--rownum); } @@ -267,13 +264,17 @@ public class HSSFSheet private int findFirstRow(int firstrow) { - int rownum = firstrow + 1; - HSSFRow r = getRow(rownum); + int rownum = firstrow + 1; + HSSFRow r = getRow(rownum); - while (r == null) + while (r == null && rownum <= getLastRowNum()) { r = getRow(++rownum); } + + if (rownum > getLastRowNum()) + return -1; + return rownum; } @@ -311,8 +312,8 @@ public class HSSFSheet { HSSFRow row = new HSSFRow(); - row.setRowNum(( short ) rownum); - return ( HSSFRow ) rows.get(row); + row.setRowNum((short) rownum); + return (HSSFRow) rows.get(row); } /** @@ -345,26 +346,6 @@ public class HSSFSheet } /** - * Seems to be unused (gjs) - * - * used internally to add cells from a high level row to the low level model - * @param row the row object to represent in low level RowRecord. - */ - private void addCellsFromRow(HSSFRow row) - { - Iterator iter = row.cellIterator(); - - // for (int k = 0; k < row.getPhysicalNumberOfCells(); k++) - while (iter.hasNext()) - { - HSSFCell cell = - ( HSSFCell ) iter.next(); // row.getPhysicalCellAt(k); - - sheet.addValueRecord(row.getRowNum(), cell.getCellValueRecord()); - } - } - - /** * set the width (in units of 1/256th of a character width) * @param column - the column to set (0-based) * @param width - the width in units of 1/256th of a character width @@ -400,7 +381,7 @@ public class HSSFSheet /** * get the default row height for the sheet (if the rows do not define their own height) in * twips (1/20 of a point) - * @retun default row height + * @return default row height */ public short getDefaultRowHeight() @@ -449,7 +430,7 @@ public class HSSFSheet public void setDefaultRowHeightInPoints(float height) { - sheet.setDefaultRowHeight(( short ) (height * 20)); + sheet.setDefaultRowHeight((short) (height * 20)); } /** @@ -480,10 +461,10 @@ public class HSSFSheet public int addMergedRegion(Region region) { - return sheet.addMergedRegion(( short ) region.getRowFrom(), - region.getColumnFrom(), - ( short ) region.getRowTo(), - region.getColumnTo()); + return sheet.addMergedRegion((short) region.getRowFrom(), + region.getColumnFrom(), + (short) region.getRowTo(), + region.getColumnTo()); } /** @@ -494,7 +475,7 @@ public class HSSFSheet public void setVerticallyCenter(boolean value) { VCenterRecord record = - ( VCenterRecord ) sheet.findFirstRecordBySid(VCenterRecord.sid); + (VCenterRecord) sheet.findFirstRecordBySid(VCenterRecord.sid); record.setVCenter(value); } @@ -506,7 +487,7 @@ public class HSSFSheet public boolean getVerticallyCenter(boolean value) { VCenterRecord record = - ( VCenterRecord ) sheet.findFirstRecordBySid(VCenterRecord.sid); + (VCenterRecord) sheet.findFirstRecordBySid(VCenterRecord.sid); return record.getVCenter(); } @@ -543,7 +524,7 @@ public class HSSFSheet } /** - * @returns an iterator of the PHYSICAL rows. Meaning the 3rd element may not + * @return an iterator of the PHYSICAL rows. Meaning the 3rd element may not * be the third row if say for instance the second row is undefined. */ @@ -571,7 +552,7 @@ public class HSSFSheet public void setAlternativeExpression(boolean b) { WSBoolRecord record = - ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + (WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid); record.setAlternateExpression(b); } @@ -584,7 +565,7 @@ public class HSSFSheet public void setAlternativeFormula(boolean b) { WSBoolRecord record = - ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + (WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid); record.setAlternateFormula(b); } @@ -597,7 +578,7 @@ public class HSSFSheet public void setAutobreaks(boolean b) { WSBoolRecord record = - ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + (WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid); record.setAutobreaks(b); } @@ -610,7 +591,7 @@ public class HSSFSheet public void setDialog(boolean b) { WSBoolRecord record = - ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + (WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid); record.setDialog(b); } @@ -624,7 +605,7 @@ public class HSSFSheet public void setDisplayGuts(boolean b) { WSBoolRecord record = - ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + (WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid); record.setDisplayGuts(b); } @@ -637,7 +618,7 @@ public class HSSFSheet public void setFitToPage(boolean b) { WSBoolRecord record = - ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + (WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid); record.setFitToPage(b); } @@ -650,7 +631,7 @@ public class HSSFSheet public void setRowSumsBelow(boolean b) { WSBoolRecord record = - ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + (WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid); record.setRowSumsBelow(b); } @@ -663,7 +644,7 @@ public class HSSFSheet public void setRowSumsRight(boolean b) { WSBoolRecord record = - ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + (WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid); record.setRowSumsRight(b); } @@ -675,8 +656,8 @@ public class HSSFSheet public boolean getAlternateExpression() { - return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) - .getAlternateExpression(); + return ((WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getAlternateExpression(); } /** @@ -686,8 +667,8 @@ public class HSSFSheet public boolean getAlternateFormula() { - return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) - .getAlternateFormula(); + return ((WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getAlternateFormula(); } /** @@ -697,8 +678,8 @@ public class HSSFSheet public boolean getAutobreaks() { - return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) - .getAutobreaks(); + return ((WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getAutobreaks(); } /** @@ -708,8 +689,8 @@ public class HSSFSheet public boolean getDialog() { - return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) - .getDialog(); + return ((WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getDialog(); } /** @@ -720,8 +701,8 @@ public class HSSFSheet public boolean getDisplayGuts() { - return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) - .getDisplayGuts(); + return ((WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getDisplayGuts(); } /** @@ -731,8 +712,8 @@ public class HSSFSheet public boolean getFitToPage() { - return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) - .getFitToPage(); + return ((WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getFitToPage(); } /** @@ -742,8 +723,8 @@ public class HSSFSheet public boolean getRowSumsBelow() { - return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) - .getRowSumsBelow(); + return ((WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getRowSumsBelow(); } /** @@ -753,7 +734,7 @@ public class HSSFSheet public boolean getRowSumsRight() { - return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) - .getRowSumsRight(); + return ((WSBoolRecord) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getRowSumsRight(); } } diff --git a/src/java/org/apache/poi/util/HexDump.java b/src/java/org/apache/poi/util/HexDump.java index 4e0cfd35a3..49bca34ff0 100644 --- a/src/java/org/apache/poi/util/HexDump.java +++ b/src/java/org/apache/poi/util/HexDump.java @@ -81,6 +81,7 @@ public class HexDump * @param stream the OutputStream to which the data is to be * written * @param index initial index into the byte array + * @param length number of characters to output * * @exception IOException is thrown if anything goes wrong writing * the data to stream @@ -89,11 +90,10 @@ public class HexDump * @exception IllegalArgumentException if the output stream is * null */ - public synchronized static void dump(final byte [] data, final long offset, - final OutputStream stream, final int index) - throws IOException, ArrayIndexOutOfBoundsException, - IllegalArgumentException + final OutputStream stream, final int index, final int length) + throws IOException, ArrayIndexOutOfBoundsException, + IllegalArgumentException { if ((index < 0) || (index >= data.length)) { @@ -108,9 +108,11 @@ public class HexDump long display_offset = offset + index; StringBuffer buffer = new StringBuffer(74); - for (int j = index; j < data.length; j += 16) + + int data_length = Math.min(data.length,index+length); + for (int j = index; j < data_length; j += 16) { - int chars_read = data.length - j; + int chars_read = data_length - j; if (chars_read > 16) { @@ -146,6 +148,32 @@ public class HexDump buffer.setLength(0); display_offset += chars_read; } + + } + + /** + * dump an array of bytes to an OutputStream + * + * @param data the byte array to be dumped + * @param offset its offset, whatever that might mean + * @param stream the OutputStream to which the data is to be + * written + * @param index initial index into the byte array + * + * @exception IOException is thrown if anything goes wrong writing + * the data to stream + * @exception ArrayIndexOutOfBoundsException if the index is + * outside the data array's bounds + * @exception IllegalArgumentException if the output stream is + * null + */ + + public synchronized static void dump(final byte [] data, final long offset, + final OutputStream stream, final int index) + throws IOException, ArrayIndexOutOfBoundsException, + IllegalArgumentException + { + dump(data, offset, stream, index, data.length-index); } public static final String EOL = diff --git a/src/java/org/apache/poi/util/HexRead.java b/src/java/org/apache/poi/util/HexRead.java new file mode 100644 index 0000000000..c1bda6f613 --- /dev/null +++ b/src/java/org/apache/poi/util/HexRead.java @@ -0,0 +1,116 @@ +package org.apache.poi.util; + +import java.io.IOException; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.List; +import java.util.ArrayList; + +public class HexRead +{ + public static byte[] readTestData( String filename ) + throws IOException + { + File file = new File( filename ); + FileInputStream stream = new FileInputStream( file ); + int characterCount = 0; + byte b = (byte) 0; + List bytes = new ArrayList(); + boolean done = false; + + while ( !done ) + { + int count = stream.read(); + + switch ( count ) + { + + case '#': + readToEOL(stream); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + b <<= 4; + b += (byte) ( count - '0' ); + characterCount++; + if ( characterCount == 2 ) + { + bytes.add( new Byte( b ) ); + characterCount = 0; + b = (byte) 0; + } + break; + + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + b <<= 4; + b += (byte) ( count + 10 - 'A' ); + characterCount++; + if ( characterCount == 2 ) + { + bytes.add( new Byte( b ) ); + characterCount = 0; + b = (byte) 0; + } + break; + + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + b <<= 4; + b += (byte) ( count + 10 - 'a' ); + characterCount++; + if ( characterCount == 2 ) + { + bytes.add( new Byte( b ) ); + characterCount = 0; + b = (byte) 0; + } + break; + + case -1: + done = true; + break; + + default : + break; + } + } + stream.close(); + Byte[] polished = (Byte[]) bytes.toArray( new Byte[0] ); + byte[] rval = new byte[polished.length]; + + for ( int j = 0; j < polished.length; j++ ) + { + rval[j] = polished[j].byteValue(); + } + return rval; + } + + static private void readToEOL( InputStream stream ) throws IOException + { + int c = stream.read(); + while ( c != -1 && c != '\n' && c != '\r') + { + c = stream.read(); + } + } + + +} diff --git a/src/java/org/apache/poi/util/LittleEndian.java b/src/java/org/apache/poi/util/LittleEndian.java index 6c7a4f4d23..21b0c69ead 100644 --- a/src/java/org/apache/poi/util/LittleEndian.java +++ b/src/java/org/apache/poi/util/LittleEndian.java @@ -236,7 +236,6 @@ public class LittleEndian * * @exception ArrayIndexOutOfBoundsException may be thrown */ - public static void putShort(final byte[] data, final int offset, final short value) { @@ -244,6 +243,21 @@ public class LittleEndian } /** + * put an unsigned short value into a byte array + * + * @param data the byte array + * @param offset a starting offset into the byte array + * @param value the short (16-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + public static void putUShort(final byte[] data, final int offset, + final int value) + { + putNumber(data, offset, value, SHORT_SIZE); + } + + /** * put a array of shorts into a byte array * * @param data the byte array @@ -592,4 +606,17 @@ public class LittleEndian return copy; } + /** + * Retrieves and unsigned short. This is converted UP to a int + * so it can fit. + * + * @param data The data to read + * @param offset The offset to read the short from + * @return An integer representation of the short. + */ + public static int getUShort( byte[] data, int offset ) + { + return (int)getNumber(data, offset, SHORT_SIZE); + } + } diff --git a/src/java/org/apache/poi/util/POILogFactory.java b/src/java/org/apache/poi/util/POILogFactory.java index 2378ab86a7..8c52a367a9 100644 --- a/src/java/org/apache/poi/util/POILogFactory.java +++ b/src/java/org/apache/poi/util/POILogFactory.java @@ -1,4 +1,3 @@ - /* * ==================================================================== * The Apache Software License, Version 1.1 @@ -55,12 +54,8 @@ */ package org.apache.poi.util; -import java.io.FileInputStream; -import java.io.IOException; - -import java.util.*; - -import org.apache.commons.logging.*; +import java.util.HashMap; +import java.util.Map; /** * Provides logging without clients having to mess with @@ -73,10 +68,10 @@ import org.apache.commons.logging.*; public class POILogFactory { - private static LogFactory _creator = LogFactory.getFactory(); +// private static LogFactory _creator = LogFactory.getFactory(); // map of POILogger instances, with classes as keys - private static Map _loggers = new HashMap();; + private static Map _loggers = new HashMap();; /** @@ -95,11 +90,11 @@ public class POILogFactory * @return a POILogger for the specified class */ - public static POILogger getLogger(final Class theclass) + public static POILogger getLogger( final Class theclass ) { - return getLogger(theclass.getName()); + return getLogger( theclass.getName() ); } - + /** * Get a logger, based on a String * @@ -108,20 +103,20 @@ public class POILogFactory * @return a POILogger for the specified class */ - public static POILogger getLogger(final String cat) + public static POILogger getLogger( final String cat ) { POILogger logger = null; - if (_loggers.containsKey(cat)) + if ( _loggers.containsKey( cat ) ) { - logger = ( POILogger ) _loggers.get(cat); + logger = (POILogger) _loggers.get( cat ); } else { - logger = new POILogger(_creator.getInstance(cat)); - _loggers.put(cat, logger); + logger = new POILogger( ); + _loggers.put( cat, logger ); } return logger; } - + } // end public class POILogFactory diff --git a/src/java/org/apache/poi/util/POILogger.java b/src/java/org/apache/poi/util/POILogger.java index a6d066c38d..b47a38023e 100644 --- a/src/java/org/apache/poi/util/POILogger.java +++ b/src/java/org/apache/poi/util/POILogger.java @@ -55,8 +55,6 @@ */ package org.apache.poi.util; -import org.apache.commons.logging.Log; - import java.util.*; /** @@ -72,7 +70,7 @@ import java.util.*; public class POILogger { - private Log log = null; +// private Log log = null; public static final int DEBUG = 1; public static final int INFO = 3; public static final int WARN = 5; @@ -82,13 +80,10 @@ public class POILogger /** * package scope so it cannot be instantiated outside of the util * package. You need a POILogger? Go to the POILogFactory for one - * - * @param log the object that does the real work of logging */ - POILogger(final Log log) + POILogger() { - this.log = log; } /** @@ -100,91 +95,73 @@ public class POILogger public void log(final int level, final Object obj1) { - if(level==FATAL) - { - if(log.isFatalEnabled()) - { - log.fatal(obj1); - } - } - else if(level==ERROR) - { - if(log.isErrorEnabled()) - { - log.error(obj1); - } - } - else if(level==WARN) - { - if(log.isWarnEnabled()) - { - log.warn(obj1); - } - } - else if(level==INFO) - { - if(log.isInfoEnabled()) - { - log.info(obj1); - } - } - else if(level==DEBUG) - { - if(log.isDebugEnabled()) - { - log.debug(obj1); - } - } - else - { - if(log.isTraceEnabled()) - { - log.trace(obj1); - } - } + if (check(level)) + System.out.println( obj1 ); + } + private boolean isDebugEnabled() + { + return System.getProperty("poi.logging") != null; + } + + private boolean isInfoEnabled() + { + return false; + } + + private boolean isWarnEnabled() + { + return System.getProperty("poi.logging") != null; + } + + private boolean isErrorEnabled() + { + return System.getProperty("poi.logging") != null; + } + + private boolean isFatalEnabled() + { + return System.getProperty("poi.logging") != null; } /** * Check if a logger is enabled to log at the specified level * * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 The logger to check. */ - - public boolean check(final Log log, final int level) + public boolean check(final int level) { if(level==FATAL) { - if(log.isFatalEnabled()) + if(isFatalEnabled()) { return true; } } else if(level==ERROR) { - if(log.isErrorEnabled()) + if(isErrorEnabled()) { return true; } } else if(level==WARN) { - if(log.isWarnEnabled()) + if(isWarnEnabled()) { return true; } } else if(level==INFO) { - if(log.isInfoEnabled()) + if(isInfoEnabled()) { return true; } } else if(level==DEBUG) { - if(log.isDebugEnabled()) + if(isDebugEnabled()) { return true; } @@ -204,7 +181,7 @@ public class POILogger public void log(final int level, final Object obj1, final Object obj2) { - if (check(log, level)) + if (check( level)) { log(level, new StringBuffer(32).append(obj1).append(obj2)); } @@ -222,13 +199,9 @@ public class POILogger public void log(final int level, final Object obj1, final Object obj2, final Object obj3) { - - - if (check(log, level)) + if (check( level)) { - log(level, - new StringBuffer(48).append(obj1).append(obj2) - .append(obj3)); + log(level, new StringBuffer(48).append(obj1).append(obj2 ).append(obj3)); } } @@ -247,7 +220,7 @@ public class POILogger { - if (check(log, level)) + if (check( level)) { log(level, new StringBuffer(64).append(obj1).append(obj2) @@ -271,7 +244,7 @@ public class POILogger { - if (check(log, level)) + if (check( level)) { log(level, new StringBuffer(80).append(obj1).append(obj2) @@ -297,7 +270,7 @@ public class POILogger { - if (check(log, level)) + if (check( level)) { log(level , new StringBuffer(96).append(obj1).append(obj2) @@ -324,7 +297,7 @@ public class POILogger { - if (check(log, level)) + if (check( level)) { log(level, new StringBuffer(112).append(obj1).append(obj2) @@ -353,7 +326,7 @@ public class POILogger { - if (check(log, level)) + if (check( level)) { log(level, new StringBuffer(128).append(obj1).append(obj2) @@ -390,7 +363,7 @@ public class POILogger { - if (check(log, level)) + if (check( level)) { log(level, new StringBuffer(32).append(obj1).append(obj2), exception); @@ -412,7 +385,7 @@ public class POILogger { - if (check(log, level)) + if (check( level)) { log(level, new StringBuffer(48).append(obj1).append(obj2) .append(obj3), exception); @@ -436,7 +409,7 @@ public class POILogger { - if (check(log, level)) + if (check( level)) { log(level, new StringBuffer(64).append(obj1).append(obj2) .append(obj3).append(obj4), exception); @@ -461,7 +434,7 @@ public class POILogger { - if (check(log, level)) + if (check( level)) { log(level, new StringBuffer(80).append(obj1).append(obj2) .append(obj3).append(obj4).append(obj5), exception); @@ -487,7 +460,7 @@ public class POILogger { - if (check(log, level)) + if (check( level)) { log(level , new StringBuffer(96).append(obj1) .append(obj2).append(obj3).append(obj4).append(obj5) @@ -516,7 +489,7 @@ public class POILogger { - if (check(log, level)) + if (check( level)) { log(level, new StringBuffer(112).append(obj1).append(obj2) .append(obj3).append(obj4).append(obj5).append(obj6) @@ -546,7 +519,7 @@ public class POILogger { - if (check(log, level)) + if (check( level)) { log(level, new StringBuffer(128).append(obj1).append(obj2) .append(obj3).append(obj4).append(obj5).append(obj6) @@ -703,7 +676,7 @@ public class POILogger { - if (check(log, level)) + if (check( level)) { Object[] params = flattenArrays(unflatParams); diff --git a/src/testcases/org/apache/poi/hssf/data/BigSSTRecord b/src/testcases/org/apache/poi/hssf/data/BigSSTRecord index 6cebff51ba..3dd8f9ebd9 100755 --- a/src/testcases/org/apache/poi/hssf/data/BigSSTRecord +++ b/src/testcases/org/apache/poi/hssf/data/BigSSTRecord @@ -1,516 +1,516 @@ -FC 00 20 -20 B8 05 00 00 B0 02 00 00 0C 00 00 4D 61 6E 75 -66 61 63 74 75 72 65 72 0B 00 00 50 61 72 74 20 -4E 75 6D 62 65 72 05 00 00 53 63 61 6C 65 04 00 -00 54 79 70 65 04 00 00 4E 61 6D 65 08 00 00 43 -6F 6D 6D 65 6E 74 73 08 00 00 41 4D 54 2D 45 52 -54 4C 07 00 00 48 6F 74 20 52 6F 64 10 00 00 33 -32 20 46 6F 72 64 20 52 6F 61 64 73 74 65 72 08 -00 00 4D 6F 6E 6F 67 72 61 6D 08 00 00 53 68 6F -77 20 52 6F 64 07 00 00 48 61 6E 67 6D 61 6E 11 -00 00 50 65 74 65 72 62 69 6C 74 20 57 72 65 63 -6B 65 72 15 00 00 45 61 73 74 65 72 6E 20 41 69 -72 6C 69 6E 65 73 20 44 43 2D 33 11 00 00 4D 61 -73 65 72 61 74 69 20 4D 65 72 61 6B 20 53 53 1A -00 00 44 6F 75 67 6C 61 73 20 50 2D 37 30 20 4E -69 67 68 74 20 46 69 67 68 74 65 72 17 00 00 35 -35 20 43 68 65 76 79 20 53 74 72 65 65 74 20 4D -61 63 68 69 6E 65 0C 00 00 54 77 65 65 64 79 20 -50 69 65 20 32 13 00 00 48 75 65 79 20 52 65 73 -63 75 65 20 43 68 6F 70 70 65 72 10 00 00 4D 61 -7A 64 61 20 4D 58 2D 35 20 4D 69 61 74 61 0A 00 -00 53 70 6F 72 74 73 20 43 61 72 05 00 00 54 72 -75 63 6B 06 00 00 52 6F 63 6B 65 74 09 00 00 50 -61 72 74 73 20 4B 69 74 0E 00 00 43 69 76 69 6C -69 61 6E 20 50 6C 61 6E 65 0E 00 00 4D 69 6C 69 -74 61 72 79 20 50 6C 61 6E 65 0F 00 00 53 63 69 -65 6E 63 65 20 46 69 63 74 69 6F 6E 1A 00 00 44 -6F 6E 20 47 61 72 6C 69 74 73 20 57 79 6E 6E 27 -73 20 43 68 61 72 67 65 72 19 00 00 44 6F 6E 20 -47 61 72 6C 69 74 73 20 57 79 6E 6E 27 73 20 4A -61 6D 6D 65 72 1A 00 00 50 61 63 6B 61 72 64 20 -42 6F 61 74 74 61 69 6C 20 53 70 65 65 64 73 74 -65 72 0E 00 00 52 65 76 65 6C 6C 20 47 65 72 6D -61 6E 79 05 00 00 30 34 31 34 36 04 00 00 31 2F -32 34 04 00 00 31 2F 37 32 0E 00 00 4D 65 20 32 -36 32 20 41 2D 31 61 2F 55 33 09 00 00 53 54 43 -20 53 74 61 72 74 04 00 00 34 63 2D 39 05 00 00 -31 2F 32 38 38 0C 00 00 50 72 6F 74 6F 6E 2D 4B -20 4D 69 72 04 00 00 34 63 2D 37 0E 00 00 50 72 -6F 74 6F 6E 2D 4B 20 41 73 74 72 61 05 00 00 34 -63 2D 31 37 0E 00 00 50 72 6F 74 6F 6E 2D 4B 20 -5A 61 72 79 61 13 00 00 41 63 63 75 72 61 74 65 -20 4D 69 6E 69 61 74 75 72 65 73 04 00 00 33 34 -32 30 04 00 00 31 2F 34 38 0F 00 00 53 42 44 2D -31 20 44 61 75 6E 74 6C 65 73 73 1B 00 00 77 2F -56 65 72 6C 69 6E 64 65 6E 20 31 33 37 38 20 44 -65 74 61 69 6C 20 53 65 74 04 00 00 38 32 38 33 -0C 00 00 54 72 6F 75 62 6C 65 6D 61 6B 65 72 04 -00 00 32 37 33 37 0E 00 00 44 61 79 74 6F 6E 61 -20 53 70 69 64 65 72 04 00 00 38 31 32 36 04 00 -00 31 2F 32 35 06 00 00 48 65 6C 6C 65 72 05 00 -00 38 30 34 34 33 05 00 00 31 2F 31 34 34 12 00 -00 42 72 65 69 74 6C 69 6E 20 4F 72 62 69 74 65 -72 20 33 0F 00 00 53 68 61 6E 67 68 61 69 20 44 -72 61 67 6F 6E 04 00 00 31 39 39 38 04 00 00 31 -2F 39 36 0F 00 00 41 72 69 61 6E 65 20 35 20 52 -6F 63 6B 65 74 0F 00 00 52 65 76 65 6C 6C 2D 4D -6F 6E 6F 67 72 61 6D 07 00 00 38 35 2D 35 39 33 -34 0F 00 00 50 42 59 2D 35 41 20 43 61 74 61 6C -69 6E 61 0A 00 00 50 72 6F 4D 6F 64 65 6C 65 72 -07 00 00 47 6C 65 6E 63 6F 65 05 00 00 30 35 32 -30 32 04 00 00 31 2F 33 35 16 00 00 50 69 61 73 -65 63 6B 69 20 5A 56 2D 38 50 20 41 69 72 67 65 -65 70 08 00 00 48 61 73 65 67 61 77 61 05 00 00 -30 39 31 36 39 20 00 00 53 42 44 2D 33 20 44 61 -75 6E 74 6C 65 73 73 20 27 55 53 53 20 45 6E 74 -65 72 70 72 69 73 65 27 0C 00 00 53 69 6C 76 65 -72 20 43 6C 6F 75 64 06 00 00 53 43 34 38 30 31 -19 00 00 53 75 70 65 72 6D 61 72 69 6E 65 20 53 -70 69 74 65 66 75 6C 20 46 2E 31 34 06 00 00 52 -65 76 65 6C 6C 07 00 00 38 35 2D 31 36 35 34 0D -00 00 50 2D 35 31 42 20 4D 75 73 74 61 6E 67 09 -00 00 50 72 6F 46 69 6E 69 73 68 06 00 00 44 72 -61 67 6F 6E 04 00 00 35 39 30 31 0B 00 00 46 6F -6B 6B 65 72 20 44 72 2E 31 07 00 00 49 74 61 6C -65 72 69 03 00 00 38 34 36 25 00 00 43 2D 31 33 -30 4A 20 48 65 72 63 75 6C 65 73 20 48 65 61 76 -79 20 54 72 61 6E 73 70 6F 72 74 20 50 6C 61 6E -65 04 00 00 37 36 31 30 15 00 00 46 65 72 72 61 -72 69 20 46 35 30 20 42 61 72 63 68 65 74 74 61 -03 00 00 41 4D 54 08 00 00 54 33 37 34 2D 32 32 -35 0D 00 00 43 6F 72 76 61 69 72 20 4D 6F 6E 7A -61 04 00 00 35 30 30 33 0B 00 00 4D 63 4C 61 72 -65 6E 20 4D 38 42 0D 00 00 52 65 76 65 6C 6C 20 -4C 6F 64 65 6C 61 05 00 00 48 2D 32 36 33 03 00 -00 75 6E 6B 23 00 00 42 6F 65 69 6E 67 20 53 53 -54 20 50 61 6E 41 6D 20 43 6C 69 70 70 65 72 20 -53 75 70 65 72 73 6F 6E 69 63 05 00 00 30 35 39 -30 39 05 00 00 31 2F 33 30 30 1D 00 00 4E 75 63 -6C 65 61 72 20 50 6F 77 65 72 65 64 20 53 70 61 -63 65 20 53 74 61 74 69 6F 6E 04 00 00 38 37 36 -34 06 00 00 31 2F 32 35 30 30 19 00 00 53 74 61 -72 20 54 72 65 6B 20 44 65 65 70 20 53 70 61 63 -65 20 4E 69 6E 65 23 00 00 46 69 62 65 72 2D 6F -70 74 69 63 20 4C 69 67 68 74 69 6E 67 2C 20 73 -6B 69 6C 6C 20 6C 65 76 65 6C 20 33 0D 00 00 53 -6B 69 6C 6C 20 6C 65 76 65 6C 20 33 04 00 00 38 -31 35 38 16 00 00 42 6C 75 65 70 72 69 6E 74 65 -72 20 50 61 72 74 73 20 50 61 63 6B 13 00 00 45 -6E 67 69 6E 65 73 20 61 6E 64 20 67 72 69 6C 6C -65 73 05 00 00 33 30 30 33 37 05 00 00 31 2F 32 -30 30 1E 00 00 4D 61 6E 20 49 6E 20 53 70 61 63 -65 20 52 6F 63 6B 65 74 20 43 6F 6C 6C 65 63 74 -69 6F 6E 53 00 00 4D 65 72 63 75 72 79 20 41 74 -6C 61 73 2C 20 4D 65 72 63 75 72 79 20 52 65 64 -73 74 6F 6E 65 2C 20 47 65 6D 69 6E 69 20 54 69 -74 61 6E 20 49 49 2C 20 53 61 74 75 72 6E 20 31 -42 20 41 70 6F 6C 6C 6F 2C 20 53 61 74 75 72 6E -20 56 20 41 70 6F 6C 6C 6F 04 00 00 35 30 38 33 -04 00 00 31 2F 33 32 11 00 00 41 70 6F 6C 6C 6F -20 53 70 61 63 65 63 72 61 66 74 09 00 00 4D 69 -6E 69 63 72 61 66 74 05 00 00 31 31 32 32 30 04 -00 00 31 2F 31 36 24 00 00 31 39 35 35 20 4D 65 -72 63 65 64 65 73 20 33 30 30 53 4C 20 22 47 75 -6C 6C 77 69 6E 67 22 20 43 6F 75 70 65 07 00 00 -38 35 2D 36 38 35 39 24 00 00 4D 75 73 74 61 6E -67 20 4D 75 73 63 6C 65 20 54 72 69 6F 20 27 36 -30 73 2C 20 27 37 30 73 2C 20 27 38 30 73 35 00 -00 31 39 36 34 20 31 2F 32 20 43 6F 6E 76 65 72 -74 69 62 6C 65 2C 20 31 39 37 30 20 42 6F 73 73 -20 33 30 32 2C 20 31 39 38 39 20 43 6F 6E 76 65 -72 74 69 62 6C 65 06 00 00 54 61 6D 69 79 61 05 -00 00 32 34 31 37 30 0A 00 00 4D 6F 72 67 61 6E -20 34 2F 34 07 00 00 38 35 2D 32 34 39 31 11 00 -00 36 37 20 43 6F 72 76 65 74 74 65 20 43 6F 75 -70 65 07 00 00 38 35 2D 32 35 33 34 0F 00 00 53 -68 65 6C 62 79 20 53 65 72 69 65 73 20 31 03 00 -00 35 36 32 11 00 00 41 73 74 6F 6E 20 4D 61 72 -74 69 6E 20 44 42 20 34 05 00 00 30 37 33 32 30 -13 00 00 50 6F 72 73 63 68 65 20 39 31 31 20 43 -61 72 72 65 72 61 07 00 00 54 65 73 74 6F 72 73 -03 00 00 33 38 36 04 00 00 32 39 37 32 16 00 00 -4D 65 72 63 65 64 65 73 20 33 30 30 20 53 4C 52 -20 22 37 32 32 22 08 00 00 4C 69 6E 64 62 65 72 -67 05 00 00 37 30 39 35 36 19 00 00 48 65 6C 6C -63 61 74 73 20 76 73 2E 20 42 65 74 74 79 20 42 -6F 6D 62 65 72 0C 00 00 48 65 6C 6C 63 61 74 20 -6F 6E 6C 79 05 00 00 30 34 36 30 39 18 00 00 45 -6B 72 61 6E 6F 70 6C 61 6E 20 41 2D 39 30 20 4F -72 6C 6A 6F 6E 6F 6B 05 00 00 31 31 36 32 36 18 -00 00 47 72 75 6D 6D 61 6E 20 58 46 35 46 2D 31 -20 53 6B 79 72 6F 63 6B 65 74 04 00 00 35 34 32 -30 0E 00 00 48 61 77 6B 65 72 20 48 61 72 72 69 -65 72 05 00 00 41 56 2D 38 41 06 00 00 65 64 75 -61 72 64 04 00 00 38 30 36 31 0F 00 00 50 2D 34 -30 30 20 41 69 72 61 63 6F 62 72 61 0B 00 00 43 -7A 65 63 68 20 4D 6F 64 65 6C 04 00 00 34 38 30 -36 16 00 00 43 75 72 74 69 73 73 20 58 50 2D 35 -35 20 41 73 63 65 6E 64 65 72 05 00 00 36 31 30 -37 34 14 00 00 44 6F 72 6E 69 65 72 20 44 6F 33 -33 35 41 20 50 66 69 65 6C 13 00 00 4B 79 75 73 -68 75 20 4A 37 57 31 20 53 68 69 6E 64 65 6E 0D -00 00 50 6C 61 6E 65 74 20 4D 6F 64 65 6C 73 03 -00 00 30 34 33 0F 00 00 48 65 6E 73 63 68 65 6C -20 48 73 20 50 38 37 05 00 00 52 65 73 69 6E 0D -00 00 53 70 65 63 69 61 6C 20 48 6F 62 62 79 08 -00 00 53 48 20 34 38 30 30 33 16 00 00 4D 63 44 -6F 6E 6E 65 6C 6C 20 58 46 2D 38 35 20 47 6F 62 -6C 69 6E 2A 00 00 4D 65 73 73 65 72 73 63 68 6D -69 74 74 20 42 66 31 30 39 45 20 27 42 75 6C 67 -61 72 69 61 6E 20 41 69 72 20 46 6F 72 63 65 27 -05 00 00 30 34 32 30 36 2D 00 00 41 69 72 62 75 -73 20 53 75 70 65 72 20 54 72 61 6E 73 70 6F 72 -74 65 72 20 41 33 30 30 2D 36 30 30 20 53 54 20 -22 42 65 6C 75 67 61 22 05 00 00 33 30 30 38 37 -0C 00 00 33 39 20 57 61 67 6F 6E 20 52 6F 64 04 -00 00 37 31 32 31 1A 00 00 31 39 33 32 20 46 6F -72 64 20 48 69 67 68 62 6F 79 20 52 6F 61 64 73 -74 65 72 2E 00 00 4C 69 6E 63 6F 6C 6E 20 4D 69 -6E 74 20 55 6C 74 72 61 20 4D 65 74 61 6C 20 53 -65 72 69 65 73 2C 20 53 6B 69 6C 6C 20 6C 65 76 -65 6C 20 33 0C 00 00 50 6F 6C 61 72 20 4C 69 67 -68 74 73 04 00 00 35 30 31 34 21 00 00 43 61 72 -6C 20 43 61 73 70 65 72 27 73 20 55 6E 64 65 72 -74 61 6B 65 72 20 44 72 61 67 73 74 65 72 07 00 -00 38 35 2D 32 35 39 32 20 00 00 33 39 20 43 68 -65 76 79 20 53 65 64 61 6E 20 44 65 6C 69 76 65 -72 79 20 4C 6F 77 72 69 64 65 72 07 00 00 38 35 -2D 35 39 30 34 12 00 00 4E 41 53 41 20 53 70 61 -63 65 20 53 68 75 74 74 6C 65 04 00 00 32 34 30 -30 1C 00 00 31 39 32 36 20 4D 61 63 6B 20 42 75 -6C 6C 64 6F 67 20 44 75 6D 70 20 54 72 75 63 6B -05 00 00 43 31 31 32 38 13 00 00 32 33 20 54 20 -52 6F 61 64 73 74 65 72 20 46 72 61 6D 65 05 00 -00 33 31 32 31 36 11 00 00 44 6F 64 67 65 20 56 -69 70 65 72 20 52 54 2D 31 30 07 00 00 50 72 6F -53 68 6F 70 04 00 00 32 33 30 31 05 00 00 31 31 -32 31 32 26 00 00 31 39 33 35 20 4D 6F 72 67 61 -6E 20 53 75 70 65 72 20 53 70 6F 72 74 73 20 54 -68 72 65 65 20 57 68 65 65 6C 65 72 0C 00 00 47 -75 6E 7A 65 20 53 61 6E 67 79 6F 13 00 00 54 72 -69 75 6D 70 68 20 54 52 32 20 4C 65 20 4D 61 6E -73 07 00 00 38 35 2D 31 39 31 31 0F 00 00 33 34 -20 46 6F 72 64 20 48 69 67 68 62 6F 79 17 00 00 -57 68 65 65 6C 73 20 6F 66 20 46 69 72 65 20 53 -6E 61 70 54 69 74 65 06 00 00 4A 6F 2D 48 61 6E -06 00 00 47 43 2D 33 30 30 20 00 00 43 68 72 79 -73 6C 65 72 20 43 6F 72 70 6F 72 61 74 69 6F 6E -20 54 75 72 62 69 6E 65 20 43 61 72 09 00 00 48 -31 32 38 35 3A 31 39 38 2B 00 00 54 6F 6D 6D 79 -20 49 76 6F 27 73 20 46 6F 75 72 20 45 6E 67 69 -6E 65 20 44 72 61 67 73 74 65 72 20 22 53 68 6F -77 62 6F 61 74 22 09 00 00 48 31 32 32 34 3A 32 -30 30 17 00 00 32 32 20 4A 52 20 52 6F 61 64 73 -74 65 72 20 44 72 61 67 73 74 65 72 0F 00 00 32 -20 63 6F 6D 70 6C 65 74 65 20 63 61 72 73 04 00 -00 36 34 33 35 04 00 00 36 34 33 38 07 00 00 38 -35 2D 37 36 36 38 0F 00 00 34 31 20 43 68 65 76 -79 20 50 69 63 6B 75 70 04 00 00 36 35 38 35 17 -00 00 42 61 62 79 6C 6F 6E 20 35 20 53 74 61 72 -66 75 72 79 20 4D 6B 2E 31 1C 00 00 4D 65 73 73 -65 72 73 63 68 6D 69 74 74 20 42 66 31 30 39 45 -20 47 61 6C 6C 61 6E 64 05 00 00 36 31 30 36 37 -1B 00 00 42 72 69 73 74 6F 6C 20 42 65 61 75 66 -69 67 68 74 65 72 20 54 46 2E 4D 6B 2E 58 12 00 -00 48 65 6E 73 63 68 65 6C 20 48 73 20 31 32 39 -42 2D 32 04 00 00 33 34 31 39 0D 00 00 50 2D 35 -31 43 20 4D 75 73 74 61 6E 67 07 00 00 38 35 2D -35 35 30 39 1B 00 00 48 65 69 6E 6B 65 6C 20 48 -65 31 31 31 20 47 65 72 6D 61 6E 20 42 6F 6D 62 -65 72 11 00 00 41 63 61 64 65 6D 79 20 4D 69 6E -69 63 72 61 66 74 04 00 00 32 31 34 35 1E 00 00 -4C 6F 63 6B 68 65 65 64 20 50 2D 33 38 4D 20 4E -69 67 68 74 20 4C 69 67 68 74 6E 69 6E 67 07 00 -00 38 35 2D 30 31 33 35 11 00 00 4F 53 32 55 2D -33 20 4B 69 6E 67 66 69 73 68 65 72 3B 00 00 41 -69 63 68 69 20 42 37 41 32 20 41 74 74 61 63 6B -20 42 6F 6D 62 65 72 20 20 52 79 75 73 65 69 20 -4B 61 69 20 28 47 72 61 63 65 29 20 27 46 6F 6C -64 69 6E 67 20 57 69 6E 67 27 15 00 00 58 46 35 -55 2D 31 20 46 6C 79 69 6E 67 20 50 61 6E 63 61 -6B 65 04 00 00 36 37 35 37 07 00 00 49 63 65 20 -27 54 27 07 00 00 38 35 2D 35 31 30 32 04 00 00 -53 68 69 70 15 00 00 55 2E 53 2E 53 2E 20 4E 6F -72 74 68 20 43 61 72 6F 6C 69 6E 61 0E 00 00 50 -61 72 74 73 20 62 79 20 50 61 72 6B 73 04 00 00 -31 30 30 34 0F 00 00 44 69 73 74 72 69 62 75 74 -6F 72 20 4B 69 74 12 00 00 50 53 46 20 4D 6F 64 -65 6C 20 53 75 70 70 6C 69 65 73 07 00 00 45 4B -44 31 30 30 30 1B 00 00 4D 6F 64 65 6C 20 43 61 -72 20 45 6E 67 69 6E 65 20 44 65 74 61 69 6C 20 -4B 69 74 04 00 00 38 34 33 35 1F 00 00 43 75 73 -74 6F 6D 20 26 20 43 6F 6D 70 65 74 69 74 69 6F -6E 20 50 61 72 74 73 20 50 61 63 6B 04 00 00 54 -36 34 32 27 00 00 22 57 69 6E 6E 69 65 20 4D 61 -65 22 20 57 69 6C 65 79 20 50 6F 73 74 27 73 20 -4C 6F 63 6B 68 65 65 64 20 56 65 67 61 06 00 00 -41 69 72 66 69 78 05 00 00 30 34 31 37 36 0C 00 -00 44 48 20 43 6F 6D 65 74 20 34 20 42 07 00 00 -38 35 2D 34 31 36 32 1B 00 00 4F 72 61 6E 67 65 -20 43 72 61 74 65 20 27 33 32 20 46 6F 72 64 20 -53 65 64 61 6E 06 00 00 38 36 30 35 50 4F 14 00 -00 46 69 61 74 20 44 6F 75 62 6C 65 20 44 72 61 -67 73 74 65 72 0B 00 00 42 6C 75 65 70 72 69 6E -74 65 72 06 00 00 48 2D 31 33 32 31 0C 00 00 47 -72 61 6E 20 54 75 72 69 73 6D 6F 07 00 00 38 35 -2D 37 36 33 37 15 00 00 33 31 20 46 6F 72 64 20 -4D 6F 64 65 6C 20 41 20 57 6F 6F 64 79 03 00 00 -4D 50 43 07 00 00 32 30 30 2D 32 30 30 16 00 00 -47 61 6E 67 62 75 73 74 65 72 73 20 32 38 20 4C -69 6E 63 6F 6C 6E 07 00 00 38 35 2D 32 35 36 39 -19 00 00 43 68 65 76 79 20 53 2D 31 30 20 4C 6F -77 72 69 64 65 72 20 33 27 6E 20 31 04 00 00 32 -32 31 31 04 00 00 35 35 30 35 1C 00 00 48 6F 72 -74 65 6E 20 48 6F 20 32 32 39 41 2D 31 20 46 6C -79 69 6E 67 20 57 69 6E 67 05 00 00 30 35 32 30 -31 1C 00 00 4D 63 44 6F 6E 6E 65 6C 6C 20 58 56 -2D 31 20 43 6F 6E 76 65 72 74 69 70 6C 61 6E 65 -07 00 00 38 35 2D 35 38 31 30 0F 00 00 53 52 2D -37 31 20 42 6C 61 63 6B 62 69 72 64 04 00 00 34 -35 32 32 19 00 00 4D 65 73 73 65 72 73 63 68 6D -69 74 74 20 42 66 2D 31 30 39 20 47 2D 31 30 16 -00 00 50 72 65 6D 69 75 6D 2C 20 73 6B 69 6C 6C -20 6C 65 76 65 6C 20 34 04 00 00 38 36 34 36 0B -00 00 48 6F 62 62 79 20 43 72 61 66 74 06 00 00 -48 43 31 35 34 39 16 00 00 56 61 6D 70 69 72 65 -20 46 33 20 4A 65 74 20 46 69 67 68 74 65 72 04 -00 00 33 34 30 31 0B 00 00 41 2D 33 36 20 41 70 -61 63 68 65 05 00 00 30 34 33 33 35 15 00 00 42 -6C 6F 68 6D 20 26 20 56 6F 73 73 20 42 56 20 50 -2D 31 39 34 09 00 00 30 31 33 30 4D 30 31 30 30 -34 00 00 43 6F 72 64 20 50 68 61 65 74 6F 6E 20 -53 65 64 61 6E 20 31 39 33 37 20 38 31 32 20 53 -75 70 65 72 63 68 61 72 67 65 64 20 43 6F 6E 76 -65 72 74 69 62 6C 65 07 00 00 38 35 2D 32 35 37 -39 15 00 00 56 57 20 42 65 65 74 6C 65 20 43 6F -6E 76 65 72 74 69 62 6C 65 04 00 00 37 34 33 38 -10 00 00 42 4D 57 20 5A 2D 31 20 52 6F 61 64 73 -74 65 72 04 00 00 36 31 34 38 0B 00 00 44 69 61 -62 6C 6F 20 41 65 72 6F 0B 00 00 55 6E 69 6F 6E -20 4D 6F 64 65 6C 2B 00 00 50 65 74 65 20 42 72 -6F 63 6B 27 73 20 53 43 43 41 20 43 68 61 6D 70 -69 6F 6E 20 42 52 45 2F 44 61 74 73 75 6E 20 32 -34 30 2D 5A 05 00 00 32 34 31 32 39 0D 00 00 4A -61 67 75 61 72 20 58 4A 20 32 32 30 05 00 00 30 -33 31 30 31 13 00 00 53 70 69 72 69 74 20 6F 66 -20 53 74 2E 20 4C 6F 75 69 73 05 00 00 30 36 31 -37 31 15 00 00 4F 72 69 6F 6E 20 32 30 30 31 20 -53 70 61 63 65 63 72 61 66 74 04 00 00 38 37 36 -36 05 00 00 31 2F 36 35 30 18 00 00 53 74 61 72 -20 54 72 65 6B 20 55 2E 53 2E 53 2E 20 52 65 6C -69 61 6E 74 07 00 00 38 35 2D 31 38 33 35 15 00 -00 4E 41 53 41 2F 4D 63 44 6F 6E 6E 65 6C 6C 20 -47 65 6D 69 6E 69 04 00 00 31 39 39 37 24 00 00 -43 68 61 6E 67 20 5A 68 65 6E 67 20 32 20 28 43 -5A 2D 32 45 29 20 4C 61 75 6E 63 68 20 56 65 68 -69 63 6C 65 05 00 00 31 31 32 31 30 04 00 00 31 -2F 32 30 13 00 00 4D 61 6B 6F 20 53 68 61 72 6B -20 53 68 6F 77 20 43 61 72 08 00 00 44 72 61 67 -73 74 65 72 08 00 00 4C 6F 77 72 69 64 65 72 04 -00 00 36 30 36 36 2F 00 00 57 69 6C 64 20 57 69 -6C 6C 69 65 20 42 6F 72 73 63 68 20 22 57 69 6E -67 65 64 20 45 78 70 72 65 73 73 22 20 41 6C 74 -65 72 65 64 20 52 6F 64 04 00 00 36 31 38 32 0F -00 00 31 39 33 33 20 57 69 6C 6C 79 73 20 56 61 -6E 07 00 00 38 35 2D 30 35 34 30 34 00 00 49 6E -61 75 67 75 72 61 6C 20 4D 41 54 43 4F 20 54 6F -6F 6C 73 20 53 75 70 65 72 6E 61 74 69 6F 6E 61 -6C 73 20 4E 69 74 72 6F 20 46 75 6E 6E 79 20 43 -61 72 04 00 00 36 33 35 35 1E 00 00 31 39 35 37 -20 43 68 65 76 72 6F 6C 65 74 20 43 6F 72 76 65 -74 74 65 20 47 61 73 73 65 72 07 00 00 38 35 2D -37 36 37 35 04 00 00 50 43 36 31 2A 00 00 47 72 -65 65 6E 20 48 6F 72 6E 65 74 20 46 6F 72 64 20 -22 54 22 20 53 68 6F 77 20 61 6E 64 20 47 6F 20 -52 6F 61 64 73 74 65 72 04 00 00 38 32 31 35 18 -00 00 31 39 34 30 20 46 6F 72 64 20 53 65 64 61 -6E 20 44 65 6C 69 76 65 72 79 07 00 00 38 35 2D -37 36 32 38 16 00 00 33 37 20 46 6F 72 64 20 50 -61 6E 65 6C 20 44 65 6C 69 76 65 72 79 04 00 00 -31 32 39 34 10 00 00 47 79 70 73 79 20 44 75 6E -65 20 42 75 67 67 79 06 00 00 48 2D 31 32 33 31 -23 00 00 43 68 72 79 73 6C 65 72 20 4E 65 77 20 -59 6F 72 6B 65 72 20 43 75 73 74 6F 6D 69 7A 69 -6E 67 20 4B 69 74 05 00 00 33 30 30 38 31 0E 00 -00 36 32 20 54 68 75 6E 64 65 72 62 69 72 64 04 -00 00 36 38 39 39 11 00 00 31 39 33 32 20 46 6F -72 64 20 50 68 61 65 74 6F 6E 05 00 00 33 30 32 -37 30 0D 00 00 31 39 36 38 20 50 6C 79 6D 6F 75 -74 68 04 00 00 38 38 34 32 17 00 00 47 72 75 6D -6D 61 6E 20 46 37 46 2D 33 4E 20 54 69 67 65 72 -63 61 74 04 00 00 48 32 34 34 14 00 00 4D 61 72 -74 69 6E 20 50 36 4D 20 53 65 61 6D 61 73 74 65 -72 04 00 00 35 35 30 30 0E 00 00 42 2D 32 35 48 -20 4D 69 74 63 68 65 6C 6C 04 00 00 33 34 30 32 -0D 00 00 50 2D 35 31 41 20 4D 75 73 74 61 6E 67 -04 00 00 36 34 32 31 3E 00 00 44 61 6D 62 75 73 -74 65 72 20 47 72 61 6E 64 20 53 6C 61 6D 20 42 -6F 6D 62 65 72 20 4C 61 6E 63 61 73 74 65 72 20 -42 49 20 53 70 65 63 69 61 6C 20 32 32 30 30 30 -6C 62 2E 20 42 6F 6D 62 05 00 00 31 34 34 34 33 -1E 00 00 4C 6F 63 6B 68 65 65 64 20 53 75 70 65 -72 2D 47 20 43 6F 6E 73 74 65 6C 6C 61 74 69 6F -6E 04 00 00 35 36 31 30 13 00 00 57 69 6C 6C 69 -61 6D 73 20 42 72 6F 73 2E 20 49 6E 63 2E 07 00 -00 34 38 2D 33 31 39 31 10 00 00 43 6F 72 62 65 -6E 20 53 75 70 65 72 2D 41 63 65 05 00 00 30 35 -30 30 32 10 00 00 52 65 74 72 69 65 76 65 72 20 -52 6F 63 6B 65 74 03 00 00 43 61 72 04 00 00 38 -35 38 38 1D 00 00 50 6C 79 6D 6F 75 74 68 20 50 -72 6F 77 6C 65 72 20 77 69 74 68 20 54 72 61 69 -6C 65 72 04 00 00 35 30 30 31 14 00 00 43 6F 72 -76 65 74 74 65 20 47 72 61 6E 64 20 53 70 6F 72 -74 04 00 00 37 31 30 38 1D 00 00 43 6F 72 76 65 -74 74 65 20 49 6E 64 79 20 22 44 72 65 61 6D 20 -4D 61 63 68 69 6E 65 22 04 00 00 38 30 35 39 0C -00 00 54 68 65 20 4D 75 6E 73 74 65 72 73 20 00 -00 42 6C 75 65 70 72 69 6E 74 65 72 3B 20 4D 75 -6E 73 74 65 72 73 20 4B 6F 61 63 68 20 6F 6E 6C -79 07 00 00 38 35 2D 34 31 36 36 05 00 00 43 6F -75 6E 74 3C 00 00 77 2F 43 75 74 74 69 6E 67 20 -45 64 67 65 20 43 45 43 34 38 30 38 36 20 48 65 -31 31 31 5A 20 22 5A 77 69 6C 6C 69 6E 67 22 20 -6B 69 74 2C 20 73 6B 69 6C 6C 20 6C 65 76 65 6C -20 33 07 00 00 38 35 2D 37 36 36 36 23 00 00 43 -75 73 74 6F 6D 20 53 69 6C 76 65 72 61 64 6F 20 -61 6E 64 20 57 61 76 65 72 69 64 65 72 20 42 6F -61 74 07 00 00 38 35 2D 36 38 35 38 16 00 00 53 -6E 61 6B 65 20 26 20 4D 6F 6E 67 6F 6F 73 65 20 -43 6F 6D 62 6F 07 00 00 38 35 2D 34 31 35 39 24 -00 00 4A 6F 65 20 41 6D 61 74 6F 20 53 75 70 65 -72 6D 61 6E 20 54 6F 70 20 46 75 65 6C 20 44 72 -61 67 73 74 65 72 04 00 00 37 35 34 31 0D 00 00 -53 6B 69 6C 6C 20 6C 65 76 65 6C 20 35 09 00 00 -48 38 32 35 2D 31 30 44 30 28 00 00 43 6F 63 61 -20 43 6F 6C 61 20 46 6F 72 64 20 4C 6F 75 69 73 -76 69 6C 6C 65 20 44 65 6C 69 76 65 72 79 20 54 -72 75 63 6B 07 00 00 38 35 2D 32 31 35 36 04 00 -00 32 39 35 34 0B 00 00 50 6F 72 73 63 68 65 20 -39 30 34 04 00 00 32 39 33 35 25 00 00 4C 61 6D -62 6F 72 67 68 69 6E 69 20 43 6F 75 6E 74 61 63 -68 20 32 35 74 68 20 41 6E 6E 69 76 65 72 73 61 -72 79 07 00 00 38 35 2D 37 36 31 36 1F 00 00 41 -6D 65 72 69 63 61 6E 20 49 6E 74 65 72 6E 61 74 -69 6F 6E 61 6C 20 44 72 61 67 73 74 65 72 07 00 -00 38 35 2D 35 32 34 31 0D 00 00 50 2D 35 31 44 -20 4D 75 73 74 61 6E 67 07 00 00 38 35 2D 35 37 -31 30 11 00 00 52 42 2D 33 36 48 20 50 65 61 63 -65 6D 61 6B 65 72 05 00 00 30 35 31 30 34 14 00 -00 52 65 70 75 62 6C 69 63 20 52 43 2E 33 20 53 -65 61 62 65 65 05 00 00 50 41 31 35 32 05 00 00 -36 31 30 36 36 25 00 00 44 65 48 61 76 69 6C 6C -61 6E 64 20 4D 6F 73 71 75 69 74 6F 20 42 20 4D -6B 2E 49 56 2F 50 52 20 4D 6B 2E 49 56 07 00 00 -38 35 2D 37 35 34 36 10 00 00 50 2D 36 31 20 42 -6C 61 63 6B 20 57 69 64 6F 77 07 00 00 38 35 2D -36 36 35 32 25 00 00 42 2D 31 37 46 20 46 6C 79 -69 6E 67 20 46 6F 72 74 72 65 73 73 20 22 4D 65 -6D 70 68 69 73 20 42 65 6C 6C 65 22 04 00 00 37 -35 30 30 0D 00 00 47 61 74 65 73 20 4C 65 61 72 -6A 65 74 03 00 00 35 31 39 15 00 00 47 72 75 6D -6D 61 6E 20 46 38 46 2D 32 20 42 65 61 72 63 61 -74 04 00 00 37 35 32 33 12 00 00 46 2D 31 30 34 -43 20 53 74 61 72 66 69 67 68 74 65 72 05 00 00 -36 31 30 37 30 15 00 00 56 6F 75 67 68 74 20 46 -34 55 2D 31 41 20 43 6F 72 73 61 69 72 07 00 00 -38 35 2D 37 36 36 34 19 00 00 42 61 6C 64 77 69 -6E 2D 4D 6F 74 69 6F 6E 20 44 72 61 67 20 43 6F -62 72 61 04 00 00 38 34 35 35 14 00 00 35 37 20 -43 68 65 76 72 6F 6C 65 74 20 42 65 6C 20 41 69 -72 16 00 00 50 72 6F 53 68 6F 70 2C 20 73 6B 69 -6C 6C 20 6C 65 76 65 6C 20 33 05 00 00 33 30 30 -35 32 0D 00 00 34 31 20 46 6F 72 64 20 57 6F 6F -64 79 07 00 00 38 35 2D 32 35 35 37 19 00 00 36 -30 20 43 68 65 76 79 20 48 61 72 64 74 6F 70 20 -4C 6F 77 72 69 64 65 72 07 00 00 38 35 2D 37 36 -33 38 09 00 00 41 65 72 6F 76 65 74 74 65 07 00 -00 38 35 2D 30 30 39 34 1B 00 00 4C 69 27 6C 20 -43 6F 66 66 69 6E 20 43 75 73 74 6F 6D 20 53 68 -6F 77 20 52 6F 64 04 00 00 38 32 39 30 0A 00 00 -53 27 43 6F 6F 6C 20 42 75 73 07 00 00 38 35 2D -32 35 39 37 12 00 00 53 74 72 65 65 74 20 46 69 -67 68 74 65 72 20 54 77 6F 04 00 00 37 36 30 39 -12 00 00 54 68 61 6D 65 73 20 50 61 6E 65 6C 20 -54 72 75 63 6B 07 00 00 38 35 2D 37 36 30 36 15 -00 00 44 61 6E 20 46 69 6E 6B 27 73 20 53 70 65 -65 64 77 61 67 6F 6E 05 00 00 30 35 35 30 35 1A -00 00 4D 61 72 74 69 6E 20 4D 2D 31 33 30 20 43 -68 69 6E 61 20 43 6C 69 70 70 65 72 07 00 00 38 -35 2D 30 30 31 35 0E 00 00 46 6F 72 64 20 54 72 -69 2D 4D 6F 74 6F 72 04 00 00 50 41 33 30 1A 00 -00 57 72 69 67 68 74 20 42 72 6F 74 68 65 72 73 -20 4B 69 74 74 79 20 48 61 77 6B 07 00 00 38 35 -2D 35 30 38 31 13 00 00 46 69 72 73 74 20 4C 75 -6E 61 72 20 4C 61 6E 64 69 6E 67 07 00 00 38 35 -2D 35 38 33 39 18 00 00 4D 65 73 73 65 72 73 63 -68 6D 69 74 74 20 42 66 20 31 31 30 20 47 2D 32 -04 00 00 43 48 34 31 04 00 00 4A 30 30 34 05 00 -00 4A 54 31 32 33 04 00 00 4A 54 32 32 04 00 00 -4A 54 37 31 04 00 00 53 50 36 33 04 00 00 42 54 -31 36 0C 00 00 4F 56 2D 31 42 20 4D 6F 68 61 77 -6B 03 00 00 30 36 38 0B 00 00 56 2D 32 32 20 4F -73 70 72 65 79 04 00 00 38 36 31 35 13 00 00 58 -2F 59 42 2D 33 35 20 46 6C 79 69 6E 67 20 57 69 -6E 67 05 00 00 31 31 32 30 38 1B 00 00 31 39 33 -33 20 43 61 64 69 6C 6C 61 63 20 56 2D 31 36 20 -54 6F 77 6E 20 43 61 72 04 00 00 36 36 31 38 27 -00 00 53 74 61 72 20 54 72 65 6B 20 33 20 50 69 -65 63 65 20 55 2E 53 2E 53 2E 20 45 6E 74 65 72 -70 72 69 73 65 20 53 65 74 12 00 00 4D 69 73 73 -69 6E 67 20 54 56 20 76 65 72 73 69 6F 6E 04 00 -00 38 39 31 35 0E 00 00 53 74 61 72 20 44 65 73 -74 72 6F 79 65 72 04 00 00 38 31 39 33 0A 00 00 -44 65 61 74 68 20 53 74 61 72 08 00 00 53 6E 61 -70 54 69 74 65 07 00 00 38 35 2D 33 36 32 31 07 -00 00 38 35 2D 33 36 32 32 17 00 00 42 61 62 79 -6C 6F 6E 20 35 20 53 70 61 63 65 20 53 74 61 74 -69 6F 6E 04 00 00 36 38 35 38 1F 00 00 53 74 61 -72 20 54 72 65 6B 20 33 20 50 69 65 63 65 20 41 -64 76 65 72 73 61 72 79 20 53 65 74 04 00 00 38 -37 36 32 06 00 00 31 2F 31 30 30 30 29 00 00 53 -74 61 72 20 54 72 65 6B 20 47 65 6E 65 72 61 74 -69 6F 6E 73 20 55 2E 53 2E 53 2E 20 45 6E 74 65 -72 70 72 69 73 65 20 42 04 00 00 38 38 38 33 03 -00 00 31 2F 34 05 00 00 4F 74 68 65 72 12 00 00 -56 69 73 69 62 6C 65 20 56 2D 38 20 45 6E 67 69 -6E 65 04 00 00 37 31 32 30 1C 00 00 31 39 36 39 -20 50 6F 6E 74 69 61 63 20 47 54 4F 20 22 54 68 -65 20 4A 75 64 67 65 22 09 00 00 31 2F 32 34 2D -31 2F 32 35 05 00 00 31 2F 31 33 30 05 00 00 31 -2F 35 37 30 05 00 00 54 6F 20 64 6F 33 00 00 47 -75 73 20 47 72 69 73 73 6F 6D 20 4D 65 6D 6F 72 -69 61 6C 20 43 6F 6D 62 6F 20 77 2F 54 77 6F 20 -43 6F 6C 6C 65 63 74 6F 72 73 20 50 61 74 63 68 -65 73 09 00 00 46 69 72 65 20 49 72 6F 6E 0C 00 -00 77 2F 64 65 74 61 69 6C 20 73 65 74 2C 00 00 -77 2F 64 65 74 61 69 6C 20 73 65 74 20 61 6E 64 -20 69 6E 74 65 72 69 6F 72 20 73 65 74 2C 20 72 -65 73 69 6E 20 65 6E 67 69 6E 65 73 03 00 00 49 -43 4D 0E 00 00 53 70 69 74 66 69 72 65 20 4D 6B -2E 49 58 1A 00 00 4D 65 73 73 65 72 73 63 68 6D -69 74 74 20 4D 65 20 34 31 30 42 2D 32 2F 55 34 -0A 00 00 4D 6F 64 65 6C 63 72 61 66 74 12 00 00 -46 2D 38 32 42 20 54 77 69 6E 20 4D 75 73 74 61 -6E 67 1F 00 00 31 39 35 33 20 53 74 75 64 65 62 -61 6B 65 72 20 53 74 61 72 6C 69 6E 65 72 20 43 -6F 75 70 65 04 00 00 32 34 33 36 0E 00 00 42 75 -67 61 74 74 69 20 45 42 20 31 31 30 2D 00 00 53 -74 61 72 20 54 72 65 6B 20 4B 6C 69 6E 67 6F 6E -20 42 69 72 64 20 6F 66 20 50 72 65 79 20 46 6C -69 67 68 74 20 44 69 73 70 6C 61 79 16 00 00 50 -6F 72 73 63 68 65 20 39 31 31 20 53 6C 61 6E 74 -20 4E 6F 73 65 05 00 00 36 31 30 37 33 25 00 00 -44 6F 75 67 6C 61 73 20 41 2D 31 4A 20 53 6B 79 -72 61 69 64 65 72 20 55 2E 53 2E 20 41 69 72 20 -46 6F 72 63 65 04 00 00 36 33 33 39 04 00 00 36 -39 35 35 04 00 00 37 35 33 30 06 00 00 34 38 2D -30 32 30 05 00 00 31 2F 34 35 30 0F 00 00 55 2E -53 2E 53 2E 20 4D 69 73 73 6F 75 72 69 05 00 00 -36 31 30 35 37 15 00 00 48 65 69 6E 6B 65 6C 20 -48 65 32 31 39 20 41 2D 37 20 55 48 55 05 00 00 -36 31 30 34 31 05 00 00 31 31 36 32 34 32 00 00 -43 6F 6E 73 6F 6C 69 64 61 74 65 64 20 42 2D 32 -34 4A 20 4C 69 62 65 72 61 74 6F 72 20 54 68 65 -20 44 72 61 67 6F 6E 20 26 20 48 69 73 20 54 61 -69 +FC 00 20
+20 B8 05 00 00 B0 02 00 00 0C 00 00 4D 61 6E 75
+66 61 63 74 75 72 65 72 0B 00 00 50 61 72 74 20
+4E 75 6D 62 65 72 05 00 00 53 63 61 6C 65 04 00
+00 54 79 70 65 04 00 00 4E 61 6D 65 08 00 00 43
+6F 6D 6D 65 6E 74 73 08 00 00 41 4D 54 2D 45 52
+54 4C 07 00 00 48 6F 74 20 52 6F 64 10 00 00 33
+32 20 46 6F 72 64 20 52 6F 61 64 73 74 65 72 08
+00 00 4D 6F 6E 6F 67 72 61 6D 08 00 00 53 68 6F
+77 20 52 6F 64 07 00 00 48 61 6E 67 6D 61 6E 11
+00 00 50 65 74 65 72 62 69 6C 74 20 57 72 65 63
+6B 65 72 15 00 00 45 61 73 74 65 72 6E 20 41 69
+72 6C 69 6E 65 73 20 44 43 2D 33 11 00 00 4D 61
+73 65 72 61 74 69 20 4D 65 72 61 6B 20 53 53 1A
+00 00 44 6F 75 67 6C 61 73 20 50 2D 37 30 20 4E
+69 67 68 74 20 46 69 67 68 74 65 72 17 00 00 35
+35 20 43 68 65 76 79 20 53 74 72 65 65 74 20 4D
+61 63 68 69 6E 65 0C 00 00 54 77 65 65 64 79 20
+50 69 65 20 32 13 00 00 48 75 65 79 20 52 65 73
+63 75 65 20 43 68 6F 70 70 65 72 10 00 00 4D 61
+7A 64 61 20 4D 58 2D 35 20 4D 69 61 74 61 0A 00
+00 53 70 6F 72 74 73 20 43 61 72 05 00 00 54 72
+75 63 6B 06 00 00 52 6F 63 6B 65 74 09 00 00 50
+61 72 74 73 20 4B 69 74 0E 00 00 43 69 76 69 6C
+69 61 6E 20 50 6C 61 6E 65 0E 00 00 4D 69 6C 69
+74 61 72 79 20 50 6C 61 6E 65 0F 00 00 53 63 69
+65 6E 63 65 20 46 69 63 74 69 6F 6E 1A 00 00 44
+6F 6E 20 47 61 72 6C 69 74 73 20 57 79 6E 6E 27
+73 20 43 68 61 72 67 65 72 19 00 00 44 6F 6E 20
+47 61 72 6C 69 74 73 20 57 79 6E 6E 27 73 20 4A
+61 6D 6D 65 72 1A 00 00 50 61 63 6B 61 72 64 20
+42 6F 61 74 74 61 69 6C 20 53 70 65 65 64 73 74
+65 72 0E 00 00 52 65 76 65 6C 6C 20 47 65 72 6D
+61 6E 79 05 00 00 30 34 31 34 36 04 00 00 31 2F
+32 34 04 00 00 31 2F 37 32 0E 00 00 4D 65 20 32
+36 32 20 41 2D 31 61 2F 55 33 09 00 00 53 54 43
+20 53 74 61 72 74 04 00 00 34 63 2D 39 05 00 00
+31 2F 32 38 38 0C 00 00 50 72 6F 74 6F 6E 2D 4B
+20 4D 69 72 04 00 00 34 63 2D 37 0E 00 00 50 72
+6F 74 6F 6E 2D 4B 20 41 73 74 72 61 05 00 00 34
+63 2D 31 37 0E 00 00 50 72 6F 74 6F 6E 2D 4B 20
+5A 61 72 79 61 13 00 00 41 63 63 75 72 61 74 65
+20 4D 69 6E 69 61 74 75 72 65 73 04 00 00 33 34
+32 30 04 00 00 31 2F 34 38 0F 00 00 53 42 44 2D
+31 20 44 61 75 6E 74 6C 65 73 73 1B 00 00 77 2F
+56 65 72 6C 69 6E 64 65 6E 20 31 33 37 38 20 44
+65 74 61 69 6C 20 53 65 74 04 00 00 38 32 38 33
+0C 00 00 54 72 6F 75 62 6C 65 6D 61 6B 65 72 04
+00 00 32 37 33 37 0E 00 00 44 61 79 74 6F 6E 61
+20 53 70 69 64 65 72 04 00 00 38 31 32 36 04 00
+00 31 2F 32 35 06 00 00 48 65 6C 6C 65 72 05 00
+00 38 30 34 34 33 05 00 00 31 2F 31 34 34 12 00
+00 42 72 65 69 74 6C 69 6E 20 4F 72 62 69 74 65
+72 20 33 0F 00 00 53 68 61 6E 67 68 61 69 20 44
+72 61 67 6F 6E 04 00 00 31 39 39 38 04 00 00 31
+2F 39 36 0F 00 00 41 72 69 61 6E 65 20 35 20 52
+6F 63 6B 65 74 0F 00 00 52 65 76 65 6C 6C 2D 4D
+6F 6E 6F 67 72 61 6D 07 00 00 38 35 2D 35 39 33
+34 0F 00 00 50 42 59 2D 35 41 20 43 61 74 61 6C
+69 6E 61 0A 00 00 50 72 6F 4D 6F 64 65 6C 65 72
+07 00 00 47 6C 65 6E 63 6F 65 05 00 00 30 35 32
+30 32 04 00 00 31 2F 33 35 16 00 00 50 69 61 73
+65 63 6B 69 20 5A 56 2D 38 50 20 41 69 72 67 65
+65 70 08 00 00 48 61 73 65 67 61 77 61 05 00 00
+30 39 31 36 39 20 00 00 53 42 44 2D 33 20 44 61
+75 6E 74 6C 65 73 73 20 27 55 53 53 20 45 6E 74
+65 72 70 72 69 73 65 27 0C 00 00 53 69 6C 76 65
+72 20 43 6C 6F 75 64 06 00 00 53 43 34 38 30 31
+19 00 00 53 75 70 65 72 6D 61 72 69 6E 65 20 53
+70 69 74 65 66 75 6C 20 46 2E 31 34 06 00 00 52
+65 76 65 6C 6C 07 00 00 38 35 2D 31 36 35 34 0D
+00 00 50 2D 35 31 42 20 4D 75 73 74 61 6E 67 09
+00 00 50 72 6F 46 69 6E 69 73 68 06 00 00 44 72
+61 67 6F 6E 04 00 00 35 39 30 31 0B 00 00 46 6F
+6B 6B 65 72 20 44 72 2E 31 07 00 00 49 74 61 6C
+65 72 69 03 00 00 38 34 36 25 00 00 43 2D 31 33
+30 4A 20 48 65 72 63 75 6C 65 73 20 48 65 61 76
+79 20 54 72 61 6E 73 70 6F 72 74 20 50 6C 61 6E
+65 04 00 00 37 36 31 30 15 00 00 46 65 72 72 61
+72 69 20 46 35 30 20 42 61 72 63 68 65 74 74 61
+03 00 00 41 4D 54 08 00 00 54 33 37 34 2D 32 32
+35 0D 00 00 43 6F 72 76 61 69 72 20 4D 6F 6E 7A
+61 04 00 00 35 30 30 33 0B 00 00 4D 63 4C 61 72
+65 6E 20 4D 38 42 0D 00 00 52 65 76 65 6C 6C 20
+4C 6F 64 65 6C 61 05 00 00 48 2D 32 36 33 03 00
+00 75 6E 6B 23 00 00 42 6F 65 69 6E 67 20 53 53
+54 20 50 61 6E 41 6D 20 43 6C 69 70 70 65 72 20
+53 75 70 65 72 73 6F 6E 69 63 05 00 00 30 35 39
+30 39 05 00 00 31 2F 33 30 30 1D 00 00 4E 75 63
+6C 65 61 72 20 50 6F 77 65 72 65 64 20 53 70 61
+63 65 20 53 74 61 74 69 6F 6E 04 00 00 38 37 36
+34 06 00 00 31 2F 32 35 30 30 19 00 00 53 74 61
+72 20 54 72 65 6B 20 44 65 65 70 20 53 70 61 63
+65 20 4E 69 6E 65 23 00 00 46 69 62 65 72 2D 6F
+70 74 69 63 20 4C 69 67 68 74 69 6E 67 2C 20 73
+6B 69 6C 6C 20 6C 65 76 65 6C 20 33 0D 00 00 53
+6B 69 6C 6C 20 6C 65 76 65 6C 20 33 04 00 00 38
+31 35 38 16 00 00 42 6C 75 65 70 72 69 6E 74 65
+72 20 50 61 72 74 73 20 50 61 63 6B 13 00 00 45
+6E 67 69 6E 65 73 20 61 6E 64 20 67 72 69 6C 6C
+65 73 05 00 00 33 30 30 33 37 05 00 00 31 2F 32
+30 30 1E 00 00 4D 61 6E 20 49 6E 20 53 70 61 63
+65 20 52 6F 63 6B 65 74 20 43 6F 6C 6C 65 63 74
+69 6F 6E 53 00 00 4D 65 72 63 75 72 79 20 41 74
+6C 61 73 2C 20 4D 65 72 63 75 72 79 20 52 65 64
+73 74 6F 6E 65 2C 20 47 65 6D 69 6E 69 20 54 69
+74 61 6E 20 49 49 2C 20 53 61 74 75 72 6E 20 31
+42 20 41 70 6F 6C 6C 6F 2C 20 53 61 74 75 72 6E
+20 56 20 41 70 6F 6C 6C 6F 04 00 00 35 30 38 33
+04 00 00 31 2F 33 32 11 00 00 41 70 6F 6C 6C 6F
+20 53 70 61 63 65 63 72 61 66 74 09 00 00 4D 69
+6E 69 63 72 61 66 74 05 00 00 31 31 32 32 30 04
+00 00 31 2F 31 36 24 00 00 31 39 35 35 20 4D 65
+72 63 65 64 65 73 20 33 30 30 53 4C 20 22 47 75
+6C 6C 77 69 6E 67 22 20 43 6F 75 70 65 07 00 00
+38 35 2D 36 38 35 39 24 00 00 4D 75 73 74 61 6E
+67 20 4D 75 73 63 6C 65 20 54 72 69 6F 20 27 36
+30 73 2C 20 27 37 30 73 2C 20 27 38 30 73 35 00
+00 31 39 36 34 20 31 2F 32 20 43 6F 6E 76 65 72
+74 69 62 6C 65 2C 20 31 39 37 30 20 42 6F 73 73
+20 33 30 32 2C 20 31 39 38 39 20 43 6F 6E 76 65
+72 74 69 62 6C 65 06 00 00 54 61 6D 69 79 61 05
+00 00 32 34 31 37 30 0A 00 00 4D 6F 72 67 61 6E
+20 34 2F 34 07 00 00 38 35 2D 32 34 39 31 11 00
+00 36 37 20 43 6F 72 76 65 74 74 65 20 43 6F 75
+70 65 07 00 00 38 35 2D 32 35 33 34 0F 00 00 53
+68 65 6C 62 79 20 53 65 72 69 65 73 20 31 03 00
+00 35 36 32 11 00 00 41 73 74 6F 6E 20 4D 61 72
+74 69 6E 20 44 42 20 34 05 00 00 30 37 33 32 30
+13 00 00 50 6F 72 73 63 68 65 20 39 31 31 20 43
+61 72 72 65 72 61 07 00 00 54 65 73 74 6F 72 73
+03 00 00 33 38 36 04 00 00 32 39 37 32 16 00 00
+4D 65 72 63 65 64 65 73 20 33 30 30 20 53 4C 52
+20 22 37 32 32 22 08 00 00 4C 69 6E 64 62 65 72
+67 05 00 00 37 30 39 35 36 19 00 00 48 65 6C 6C
+63 61 74 73 20 76 73 2E 20 42 65 74 74 79 20 42
+6F 6D 62 65 72 0C 00 00 48 65 6C 6C 63 61 74 20
+6F 6E 6C 79 05 00 00 30 34 36 30 39 18 00 00 45
+6B 72 61 6E 6F 70 6C 61 6E 20 41 2D 39 30 20 4F
+72 6C 6A 6F 6E 6F 6B 05 00 00 31 31 36 32 36 18
+00 00 47 72 75 6D 6D 61 6E 20 58 46 35 46 2D 31
+20 53 6B 79 72 6F 63 6B 65 74 04 00 00 35 34 32
+30 0E 00 00 48 61 77 6B 65 72 20 48 61 72 72 69
+65 72 05 00 00 41 56 2D 38 41 06 00 00 65 64 75
+61 72 64 04 00 00 38 30 36 31 0F 00 00 50 2D 34
+30 30 20 41 69 72 61 63 6F 62 72 61 0B 00 00 43
+7A 65 63 68 20 4D 6F 64 65 6C 04 00 00 34 38 30
+36 16 00 00 43 75 72 74 69 73 73 20 58 50 2D 35
+35 20 41 73 63 65 6E 64 65 72 05 00 00 36 31 30
+37 34 14 00 00 44 6F 72 6E 69 65 72 20 44 6F 33
+33 35 41 20 50 66 69 65 6C 13 00 00 4B 79 75 73
+68 75 20 4A 37 57 31 20 53 68 69 6E 64 65 6E 0D
+00 00 50 6C 61 6E 65 74 20 4D 6F 64 65 6C 73 03
+00 00 30 34 33 0F 00 00 48 65 6E 73 63 68 65 6C
+20 48 73 20 50 38 37 05 00 00 52 65 73 69 6E 0D
+00 00 53 70 65 63 69 61 6C 20 48 6F 62 62 79 08
+00 00 53 48 20 34 38 30 30 33 16 00 00 4D 63 44
+6F 6E 6E 65 6C 6C 20 58 46 2D 38 35 20 47 6F 62
+6C 69 6E 2A 00 00 4D 65 73 73 65 72 73 63 68 6D
+69 74 74 20 42 66 31 30 39 45 20 27 42 75 6C 67
+61 72 69 61 6E 20 41 69 72 20 46 6F 72 63 65 27
+05 00 00 30 34 32 30 36 2D 00 00 41 69 72 62 75
+73 20 53 75 70 65 72 20 54 72 61 6E 73 70 6F 72
+74 65 72 20 41 33 30 30 2D 36 30 30 20 53 54 20
+22 42 65 6C 75 67 61 22 05 00 00 33 30 30 38 37
+0C 00 00 33 39 20 57 61 67 6F 6E 20 52 6F 64 04
+00 00 37 31 32 31 1A 00 00 31 39 33 32 20 46 6F
+72 64 20 48 69 67 68 62 6F 79 20 52 6F 61 64 73
+74 65 72 2E 00 00 4C 69 6E 63 6F 6C 6E 20 4D 69
+6E 74 20 55 6C 74 72 61 20 4D 65 74 61 6C 20 53
+65 72 69 65 73 2C 20 53 6B 69 6C 6C 20 6C 65 76
+65 6C 20 33 0C 00 00 50 6F 6C 61 72 20 4C 69 67
+68 74 73 04 00 00 35 30 31 34 21 00 00 43 61 72
+6C 20 43 61 73 70 65 72 27 73 20 55 6E 64 65 72
+74 61 6B 65 72 20 44 72 61 67 73 74 65 72 07 00
+00 38 35 2D 32 35 39 32 20 00 00 33 39 20 43 68
+65 76 79 20 53 65 64 61 6E 20 44 65 6C 69 76 65
+72 79 20 4C 6F 77 72 69 64 65 72 07 00 00 38 35
+2D 35 39 30 34 12 00 00 4E 41 53 41 20 53 70 61
+63 65 20 53 68 75 74 74 6C 65 04 00 00 32 34 30
+30 1C 00 00 31 39 32 36 20 4D 61 63 6B 20 42 75
+6C 6C 64 6F 67 20 44 75 6D 70 20 54 72 75 63 6B
+05 00 00 43 31 31 32 38 13 00 00 32 33 20 54 20
+52 6F 61 64 73 74 65 72 20 46 72 61 6D 65 05 00
+00 33 31 32 31 36 11 00 00 44 6F 64 67 65 20 56
+69 70 65 72 20 52 54 2D 31 30 07 00 00 50 72 6F
+53 68 6F 70 04 00 00 32 33 30 31 05 00 00 31 31
+32 31 32 26 00 00 31 39 33 35 20 4D 6F 72 67 61
+6E 20 53 75 70 65 72 20 53 70 6F 72 74 73 20 54
+68 72 65 65 20 57 68 65 65 6C 65 72 0C 00 00 47
+75 6E 7A 65 20 53 61 6E 67 79 6F 13 00 00 54 72
+69 75 6D 70 68 20 54 52 32 20 4C 65 20 4D 61 6E
+73 07 00 00 38 35 2D 31 39 31 31 0F 00 00 33 34
+20 46 6F 72 64 20 48 69 67 68 62 6F 79 17 00 00
+57 68 65 65 6C 73 20 6F 66 20 46 69 72 65 20 53
+6E 61 70 54 69 74 65 06 00 00 4A 6F 2D 48 61 6E
+06 00 00 47 43 2D 33 30 30 20 00 00 43 68 72 79
+73 6C 65 72 20 43 6F 72 70 6F 72 61 74 69 6F 6E
+20 54 75 72 62 69 6E 65 20 43 61 72 09 00 00 48
+31 32 38 35 3A 31 39 38 2B 00 00 54 6F 6D 6D 79
+20 49 76 6F 27 73 20 46 6F 75 72 20 45 6E 67 69
+6E 65 20 44 72 61 67 73 74 65 72 20 22 53 68 6F
+77 62 6F 61 74 22 09 00 00 48 31 32 32 34 3A 32
+30 30 17 00 00 32 32 20 4A 52 20 52 6F 61 64 73
+74 65 72 20 44 72 61 67 73 74 65 72 0F 00 00 32
+20 63 6F 6D 70 6C 65 74 65 20 63 61 72 73 04 00
+00 36 34 33 35 04 00 00 36 34 33 38 07 00 00 38
+35 2D 37 36 36 38 0F 00 00 34 31 20 43 68 65 76
+79 20 50 69 63 6B 75 70 04 00 00 36 35 38 35 17
+00 00 42 61 62 79 6C 6F 6E 20 35 20 53 74 61 72
+66 75 72 79 20 4D 6B 2E 31 1C 00 00 4D 65 73 73
+65 72 73 63 68 6D 69 74 74 20 42 66 31 30 39 45
+20 47 61 6C 6C 61 6E 64 05 00 00 36 31 30 36 37
+1B 00 00 42 72 69 73 74 6F 6C 20 42 65 61 75 66
+69 67 68 74 65 72 20 54 46 2E 4D 6B 2E 58 12 00
+00 48 65 6E 73 63 68 65 6C 20 48 73 20 31 32 39
+42 2D 32 04 00 00 33 34 31 39 0D 00 00 50 2D 35
+31 43 20 4D 75 73 74 61 6E 67 07 00 00 38 35 2D
+35 35 30 39 1B 00 00 48 65 69 6E 6B 65 6C 20 48
+65 31 31 31 20 47 65 72 6D 61 6E 20 42 6F 6D 62
+65 72 11 00 00 41 63 61 64 65 6D 79 20 4D 69 6E
+69 63 72 61 66 74 04 00 00 32 31 34 35 1E 00 00
+4C 6F 63 6B 68 65 65 64 20 50 2D 33 38 4D 20 4E
+69 67 68 74 20 4C 69 67 68 74 6E 69 6E 67 07 00
+00 38 35 2D 30 31 33 35 11 00 00 4F 53 32 55 2D
+33 20 4B 69 6E 67 66 69 73 68 65 72 3B 00 00 41
+69 63 68 69 20 42 37 41 32 20 41 74 74 61 63 6B
+20 42 6F 6D 62 65 72 20 20 52 79 75 73 65 69 20
+4B 61 69 20 28 47 72 61 63 65 29 20 27 46 6F 6C
+64 69 6E 67 20 57 69 6E 67 27 15 00 00 58 46 35
+55 2D 31 20 46 6C 79 69 6E 67 20 50 61 6E 63 61
+6B 65 04 00 00 36 37 35 37 07 00 00 49 63 65 20
+27 54 27 07 00 00 38 35 2D 35 31 30 32 04 00 00
+53 68 69 70 15 00 00 55 2E 53 2E 53 2E 20 4E 6F
+72 74 68 20 43 61 72 6F 6C 69 6E 61 0E 00 00 50
+61 72 74 73 20 62 79 20 50 61 72 6B 73 04 00 00
+31 30 30 34 0F 00 00 44 69 73 74 72 69 62 75 74
+6F 72 20 4B 69 74 12 00 00 50 53 46 20 4D 6F 64
+65 6C 20 53 75 70 70 6C 69 65 73 07 00 00 45 4B
+44 31 30 30 30 1B 00 00 4D 6F 64 65 6C 20 43 61
+72 20 45 6E 67 69 6E 65 20 44 65 74 61 69 6C 20
+4B 69 74 04 00 00 38 34 33 35 1F 00 00 43 75 73
+74 6F 6D 20 26 20 43 6F 6D 70 65 74 69 74 69 6F
+6E 20 50 61 72 74 73 20 50 61 63 6B 04 00 00 54
+36 34 32 27 00 00 22 57 69 6E 6E 69 65 20 4D 61
+65 22 20 57 69 6C 65 79 20 50 6F 73 74 27 73 20
+4C 6F 63 6B 68 65 65 64 20 56 65 67 61 06 00 00
+41 69 72 66 69 78 05 00 00 30 34 31 37 36 0C 00
+00 44 48 20 43 6F 6D 65 74 20 34 20 42 07 00 00
+38 35 2D 34 31 36 32 1B 00 00 4F 72 61 6E 67 65
+20 43 72 61 74 65 20 27 33 32 20 46 6F 72 64 20
+53 65 64 61 6E 06 00 00 38 36 30 35 50 4F 14 00
+00 46 69 61 74 20 44 6F 75 62 6C 65 20 44 72 61
+67 73 74 65 72 0B 00 00 42 6C 75 65 70 72 69 6E
+74 65 72 06 00 00 48 2D 31 33 32 31 0C 00 00 47
+72 61 6E 20 54 75 72 69 73 6D 6F 07 00 00 38 35
+2D 37 36 33 37 15 00 00 33 31 20 46 6F 72 64 20
+4D 6F 64 65 6C 20 41 20 57 6F 6F 64 79 03 00 00
+4D 50 43 07 00 00 32 30 30 2D 32 30 30 16 00 00
+47 61 6E 67 62 75 73 74 65 72 73 20 32 38 20 4C
+69 6E 63 6F 6C 6E 07 00 00 38 35 2D 32 35 36 39
+19 00 00 43 68 65 76 79 20 53 2D 31 30 20 4C 6F
+77 72 69 64 65 72 20 33 27 6E 20 31 04 00 00 32
+32 31 31 04 00 00 35 35 30 35 1C 00 00 48 6F 72
+74 65 6E 20 48 6F 20 32 32 39 41 2D 31 20 46 6C
+79 69 6E 67 20 57 69 6E 67 05 00 00 30 35 32 30
+31 1C 00 00 4D 63 44 6F 6E 6E 65 6C 6C 20 58 56
+2D 31 20 43 6F 6E 76 65 72 74 69 70 6C 61 6E 65
+07 00 00 38 35 2D 35 38 31 30 0F 00 00 53 52 2D
+37 31 20 42 6C 61 63 6B 62 69 72 64 04 00 00 34
+35 32 32 19 00 00 4D 65 73 73 65 72 73 63 68 6D
+69 74 74 20 42 66 2D 31 30 39 20 47 2D 31 30 16
+00 00 50 72 65 6D 69 75 6D 2C 20 73 6B 69 6C 6C
+20 6C 65 76 65 6C 20 34 04 00 00 38 36 34 36 0B
+00 00 48 6F 62 62 79 20 43 72 61 66 74 06 00 00
+48 43 31 35 34 39 16 00 00 56 61 6D 70 69 72 65
+20 46 33 20 4A 65 74 20 46 69 67 68 74 65 72 04
+00 00 33 34 30 31 0B 00 00 41 2D 33 36 20 41 70
+61 63 68 65 05 00 00 30 34 33 33 35 15 00 00 42
+6C 6F 68 6D 20 26 20 56 6F 73 73 20 42 56 20 50
+2D 31 39 34 09 00 00 30 31 33 30 4D 30 31 30 30
+34 00 00 43 6F 72 64 20 50 68 61 65 74 6F 6E 20
+53 65 64 61 6E 20 31 39 33 37 20 38 31 32 20 53
+75 70 65 72 63 68 61 72 67 65 64 20 43 6F 6E 76
+65 72 74 69 62 6C 65 07 00 00 38 35 2D 32 35 37
+39 15 00 00 56 57 20 42 65 65 74 6C 65 20 43 6F
+6E 76 65 72 74 69 62 6C 65 04 00 00 37 34 33 38
+10 00 00 42 4D 57 20 5A 2D 31 20 52 6F 61 64 73
+74 65 72 04 00 00 36 31 34 38 0B 00 00 44 69 61
+62 6C 6F 20 41 65 72 6F 0B 00 00 55 6E 69 6F 6E
+20 4D 6F 64 65 6C 2B 00 00 50 65 74 65 20 42 72
+6F 63 6B 27 73 20 53 43 43 41 20 43 68 61 6D 70
+69 6F 6E 20 42 52 45 2F 44 61 74 73 75 6E 20 32
+34 30 2D 5A 05 00 00 32 34 31 32 39 0D 00 00 4A
+61 67 75 61 72 20 58 4A 20 32 32 30 05 00 00 30
+33 31 30 31 13 00 00 53 70 69 72 69 74 20 6F 66
+20 53 74 2E 20 4C 6F 75 69 73 05 00 00 30 36 31
+37 31 15 00 00 4F 72 69 6F 6E 20 32 30 30 31 20
+53 70 61 63 65 63 72 61 66 74 04 00 00 38 37 36
+36 05 00 00 31 2F 36 35 30 18 00 00 53 74 61 72
+20 54 72 65 6B 20 55 2E 53 2E 53 2E 20 52 65 6C
+69 61 6E 74 07 00 00 38 35 2D 31 38 33 35 15 00
+00 4E 41 53 41 2F 4D 63 44 6F 6E 6E 65 6C 6C 20
+47 65 6D 69 6E 69 04 00 00 31 39 39 37 24 00 00
+43 68 61 6E 67 20 5A 68 65 6E 67 20 32 20 28 43
+5A 2D 32 45 29 20 4C 61 75 6E 63 68 20 56 65 68
+69 63 6C 65 05 00 00 31 31 32 31 30 04 00 00 31
+2F 32 30 13 00 00 4D 61 6B 6F 20 53 68 61 72 6B
+20 53 68 6F 77 20 43 61 72 08 00 00 44 72 61 67
+73 74 65 72 08 00 00 4C 6F 77 72 69 64 65 72 04
+00 00 36 30 36 36 2F 00 00 57 69 6C 64 20 57 69
+6C 6C 69 65 20 42 6F 72 73 63 68 20 22 57 69 6E
+67 65 64 20 45 78 70 72 65 73 73 22 20 41 6C 74
+65 72 65 64 20 52 6F 64 04 00 00 36 31 38 32 0F
+00 00 31 39 33 33 20 57 69 6C 6C 79 73 20 56 61
+6E 07 00 00 38 35 2D 30 35 34 30 34 00 00 49 6E
+61 75 67 75 72 61 6C 20 4D 41 54 43 4F 20 54 6F
+6F 6C 73 20 53 75 70 65 72 6E 61 74 69 6F 6E 61
+6C 73 20 4E 69 74 72 6F 20 46 75 6E 6E 79 20 43
+61 72 04 00 00 36 33 35 35 1E 00 00 31 39 35 37
+20 43 68 65 76 72 6F 6C 65 74 20 43 6F 72 76 65
+74 74 65 20 47 61 73 73 65 72 07 00 00 38 35 2D
+37 36 37 35 04 00 00 50 43 36 31 2A 00 00 47 72
+65 65 6E 20 48 6F 72 6E 65 74 20 46 6F 72 64 20
+22 54 22 20 53 68 6F 77 20 61 6E 64 20 47 6F 20
+52 6F 61 64 73 74 65 72 04 00 00 38 32 31 35 18
+00 00 31 39 34 30 20 46 6F 72 64 20 53 65 64 61
+6E 20 44 65 6C 69 76 65 72 79 07 00 00 38 35 2D
+37 36 32 38 16 00 00 33 37 20 46 6F 72 64 20 50
+61 6E 65 6C 20 44 65 6C 69 76 65 72 79 04 00 00
+31 32 39 34 10 00 00 47 79 70 73 79 20 44 75 6E
+65 20 42 75 67 67 79 06 00 00 48 2D 31 32 33 31
+23 00 00 43 68 72 79 73 6C 65 72 20 4E 65 77 20
+59 6F 72 6B 65 72 20 43 75 73 74 6F 6D 69 7A 69
+6E 67 20 4B 69 74 05 00 00 33 30 30 38 31 0E 00
+00 36 32 20 54 68 75 6E 64 65 72 62 69 72 64 04
+00 00 36 38 39 39 11 00 00 31 39 33 32 20 46 6F
+72 64 20 50 68 61 65 74 6F 6E 05 00 00 33 30 32
+37 30 0D 00 00 31 39 36 38 20 50 6C 79 6D 6F 75
+74 68 04 00 00 38 38 34 32 17 00 00 47 72 75 6D
+6D 61 6E 20 46 37 46 2D 33 4E 20 54 69 67 65 72
+63 61 74 04 00 00 48 32 34 34 14 00 00 4D 61 72
+74 69 6E 20 50 36 4D 20 53 65 61 6D 61 73 74 65
+72 04 00 00 35 35 30 30 0E 00 00 42 2D 32 35 48
+20 4D 69 74 63 68 65 6C 6C 04 00 00 33 34 30 32
+0D 00 00 50 2D 35 31 41 20 4D 75 73 74 61 6E 67
+04 00 00 36 34 32 31 3E 00 00 44 61 6D 62 75 73
+74 65 72 20 47 72 61 6E 64 20 53 6C 61 6D 20 42
+6F 6D 62 65 72 20 4C 61 6E 63 61 73 74 65 72 20
+42 49 20 53 70 65 63 69 61 6C 20 32 32 30 30 30
+6C 62 2E 20 42 6F 6D 62 05 00 00 31 34 34 34 33
+1E 00 00 4C 6F 63 6B 68 65 65 64 20 53 75 70 65
+72 2D 47 20 43 6F 6E 73 74 65 6C 6C 61 74 69 6F
+6E 04 00 00 35 36 31 30 13 00 00 57 69 6C 6C 69
+61 6D 73 20 42 72 6F 73 2E 20 49 6E 63 2E 07 00
+00 34 38 2D 33 31 39 31 10 00 00 43 6F 72 62 65
+6E 20 53 75 70 65 72 2D 41 63 65 05 00 00 30 35
+30 30 32 10 00 00 52 65 74 72 69 65 76 65 72 20
+52 6F 63 6B 65 74 03 00 00 43 61 72 04 00 00 38
+35 38 38 1D 00 00 50 6C 79 6D 6F 75 74 68 20 50
+72 6F 77 6C 65 72 20 77 69 74 68 20 54 72 61 69
+6C 65 72 04 00 00 35 30 30 31 14 00 00 43 6F 72
+76 65 74 74 65 20 47 72 61 6E 64 20 53 70 6F 72
+74 04 00 00 37 31 30 38 1D 00 00 43 6F 72 76 65
+74 74 65 20 49 6E 64 79 20 22 44 72 65 61 6D 20
+4D 61 63 68 69 6E 65 22 04 00 00 38 30 35 39 0C
+00 00 54 68 65 20 4D 75 6E 73 74 65 72 73 20 00
+00 42 6C 75 65 70 72 69 6E 74 65 72 3B 20 4D 75
+6E 73 74 65 72 73 20 4B 6F 61 63 68 20 6F 6E 6C
+79 07 00 00 38 35 2D 34 31 36 36 05 00 00 43 6F
+75 6E 74 3C 00 00 77 2F 43 75 74 74 69 6E 67 20
+45 64 67 65 20 43 45 43 34 38 30 38 36 20 48 65
+31 31 31 5A 20 22 5A 77 69 6C 6C 69 6E 67 22 20
+6B 69 74 2C 20 73 6B 69 6C 6C 20 6C 65 76 65 6C
+20 33 07 00 00 38 35 2D 37 36 36 36 23 00 00 43
+75 73 74 6F 6D 20 53 69 6C 76 65 72 61 64 6F 20
+61 6E 64 20 57 61 76 65 72 69 64 65 72 20 42 6F
+61 74 07 00 00 38 35 2D 36 38 35 38 16 00 00 53
+6E 61 6B 65 20 26 20 4D 6F 6E 67 6F 6F 73 65 20
+43 6F 6D 62 6F 07 00 00 38 35 2D 34 31 35 39 24
+00 00 4A 6F 65 20 41 6D 61 74 6F 20 53 75 70 65
+72 6D 61 6E 20 54 6F 70 20 46 75 65 6C 20 44 72
+61 67 73 74 65 72 04 00 00 37 35 34 31 0D 00 00
+53 6B 69 6C 6C 20 6C 65 76 65 6C 20 35 09 00 00
+48 38 32 35 2D 31 30 44 30 28 00 00 43 6F 63 61
+20 43 6F 6C 61 20 46 6F 72 64 20 4C 6F 75 69 73
+76 69 6C 6C 65 20 44 65 6C 69 76 65 72 79 20 54
+72 75 63 6B 07 00 00 38 35 2D 32 31 35 36 04 00
+00 32 39 35 34 0B 00 00 50 6F 72 73 63 68 65 20
+39 30 34 04 00 00 32 39 33 35 25 00 00 4C 61 6D
+62 6F 72 67 68 69 6E 69 20 43 6F 75 6E 74 61 63
+68 20 32 35 74 68 20 41 6E 6E 69 76 65 72 73 61
+72 79 07 00 00 38 35 2D 37 36 31 36 1F 00 00 41
+6D 65 72 69 63 61 6E 20 49 6E 74 65 72 6E 61 74
+69 6F 6E 61 6C 20 44 72 61 67 73 74 65 72 07 00
+00 38 35 2D 35 32 34 31 0D 00 00 50 2D 35 31 44
+20 4D 75 73 74 61 6E 67 07 00 00 38 35 2D 35 37
+31 30 11 00 00 52 42 2D 33 36 48 20 50 65 61 63
+65 6D 61 6B 65 72 05 00 00 30 35 31 30 34 14 00
+00 52 65 70 75 62 6C 69 63 20 52 43 2E 33 20 53
+65 61 62 65 65 05 00 00 50 41 31 35 32 05 00 00
+36 31 30 36 36 25 00 00 44 65 48 61 76 69 6C 6C
+61 6E 64 20 4D 6F 73 71 75 69 74 6F 20 42 20 4D
+6B 2E 49 56 2F 50 52 20 4D 6B 2E 49 56 07 00 00
+38 35 2D 37 35 34 36 10 00 00 50 2D 36 31 20 42
+6C 61 63 6B 20 57 69 64 6F 77 07 00 00 38 35 2D
+36 36 35 32 25 00 00 42 2D 31 37 46 20 46 6C 79
+69 6E 67 20 46 6F 72 74 72 65 73 73 20 22 4D 65
+6D 70 68 69 73 20 42 65 6C 6C 65 22 04 00 00 37
+35 30 30 0D 00 00 47 61 74 65 73 20 4C 65 61 72
+6A 65 74 03 00 00 35 31 39 15 00 00 47 72 75 6D
+6D 61 6E 20 46 38 46 2D 32 20 42 65 61 72 63 61
+74 04 00 00 37 35 32 33 12 00 00 46 2D 31 30 34
+43 20 53 74 61 72 66 69 67 68 74 65 72 05 00 00
+36 31 30 37 30 15 00 00 56 6F 75 67 68 74 20 46
+34 55 2D 31 41 20 43 6F 72 73 61 69 72 07 00 00
+38 35 2D 37 36 36 34 19 00 00 42 61 6C 64 77 69
+6E 2D 4D 6F 74 69 6F 6E 20 44 72 61 67 20 43 6F
+62 72 61 04 00 00 38 34 35 35 14 00 00 35 37 20
+43 68 65 76 72 6F 6C 65 74 20 42 65 6C 20 41 69
+72 16 00 00 50 72 6F 53 68 6F 70 2C 20 73 6B 69
+6C 6C 20 6C 65 76 65 6C 20 33 05 00 00 33 30 30
+35 32 0D 00 00 34 31 20 46 6F 72 64 20 57 6F 6F
+64 79 07 00 00 38 35 2D 32 35 35 37 19 00 00 36
+30 20 43 68 65 76 79 20 48 61 72 64 74 6F 70 20
+4C 6F 77 72 69 64 65 72 07 00 00 38 35 2D 37 36
+33 38 09 00 00 41 65 72 6F 76 65 74 74 65 07 00
+00 38 35 2D 30 30 39 34 1B 00 00 4C 69 27 6C 20
+43 6F 66 66 69 6E 20 43 75 73 74 6F 6D 20 53 68
+6F 77 20 52 6F 64 04 00 00 38 32 39 30 0A 00 00
+53 27 43 6F 6F 6C 20 42 75 73 07 00 00 38 35 2D
+32 35 39 37 12 00 00 53 74 72 65 65 74 20 46 69
+67 68 74 65 72 20 54 77 6F 04 00 00 37 36 30 39
+12 00 00 54 68 61 6D 65 73 20 50 61 6E 65 6C 20
+54 72 75 63 6B 07 00 00 38 35 2D 37 36 30 36 15
+00 00 44 61 6E 20 46 69 6E 6B 27 73 20 53 70 65
+65 64 77 61 67 6F 6E 05 00 00 30 35 35 30 35 1A
+00 00 4D 61 72 74 69 6E 20 4D 2D 31 33 30 20 43
+68 69 6E 61 20 43 6C 69 70 70 65 72 07 00 00 38
+35 2D 30 30 31 35 0E 00 00 46 6F 72 64 20 54 72
+69 2D 4D 6F 74 6F 72 04 00 00 50 41 33 30 1A 00
+00 57 72 69 67 68 74 20 42 72 6F 74 68 65 72 73
+20 4B 69 74 74 79 20 48 61 77 6B 07 00 00 38 35
+2D 35 30 38 31 13 00 00 46 69 72 73 74 20 4C 75
+6E 61 72 20 4C 61 6E 64 69 6E 67 07 00 00 38 35
+2D 35 38 33 39 18 00 00 4D 65 73 73 65 72 73 63
+68 6D 69 74 74 20 42 66 20 31 31 30 20 47 2D 32
+04 00 00 43 48 34 31 04 00 00 4A 30 30 34 05 00
+00 4A 54 31 32 33 04 00 00 4A 54 32 32 04 00 00
+4A 54 37 31 04 00 00 53 50 36 33 04 00 00 42 54
+31 36 0C 00 00 4F 56 2D 31 42 20 4D 6F 68 61 77
+6B 03 00 00 30 36 38 0B 00 00 56 2D 32 32 20 4F
+73 70 72 65 79 04 00 00 38 36 31 35 13 00 00 58
+2F 59 42 2D 33 35 20 46 6C 79 69 6E 67 20 57 69
+6E 67 05 00 00 31 31 32 30 38 1B 00 00 31 39 33
+33 20 43 61 64 69 6C 6C 61 63 20 56 2D 31 36 20
+54 6F 77 6E 20 43 61 72 04 00 00 36 36 31 38 27
+00 00 53 74 61 72 20 54 72 65 6B 20 33 20 50 69
+65 63 65 20 55 2E 53 2E 53 2E 20 45 6E 74 65 72
+70 72 69 73 65 20 53 65 74 12 00 00 4D 69 73 73
+69 6E 67 20 54 56 20 76 65 72 73 69 6F 6E 04 00
+00 38 39 31 35 0E 00 00 53 74 61 72 20 44 65 73
+74 72 6F 79 65 72 04 00 00 38 31 39 33 0A 00 00
+44 65 61 74 68 20 53 74 61 72 08 00 00 53 6E 61
+70 54 69 74 65 07 00 00 38 35 2D 33 36 32 31 07
+00 00 38 35 2D 33 36 32 32 17 00 00 42 61 62 79
+6C 6F 6E 20 35 20 53 70 61 63 65 20 53 74 61 74
+69 6F 6E 04 00 00 36 38 35 38 1F 00 00 53 74 61
+72 20 54 72 65 6B 20 33 20 50 69 65 63 65 20 41
+64 76 65 72 73 61 72 79 20 53 65 74 04 00 00 38
+37 36 32 06 00 00 31 2F 31 30 30 30 29 00 00 53
+74 61 72 20 54 72 65 6B 20 47 65 6E 65 72 61 74
+69 6F 6E 73 20 55 2E 53 2E 53 2E 20 45 6E 74 65
+72 70 72 69 73 65 20 42 04 00 00 38 38 38 33 03
+00 00 31 2F 34 05 00 00 4F 74 68 65 72 12 00 00
+56 69 73 69 62 6C 65 20 56 2D 38 20 45 6E 67 69
+6E 65 04 00 00 37 31 32 30 1C 00 00 31 39 36 39
+20 50 6F 6E 74 69 61 63 20 47 54 4F 20 22 54 68
+65 20 4A 75 64 67 65 22 09 00 00 31 2F 32 34 2D
+31 2F 32 35 05 00 00 31 2F 31 33 30 05 00 00 31
+2F 35 37 30 05 00 00 54 6F 20 64 6F 33 00 00 47
+75 73 20 47 72 69 73 73 6F 6D 20 4D 65 6D 6F 72
+69 61 6C 20 43 6F 6D 62 6F 20 77 2F 54 77 6F 20
+43 6F 6C 6C 65 63 74 6F 72 73 20 50 61 74 63 68
+65 73 09 00 00 46 69 72 65 20 49 72 6F 6E 0C 00
+00 77 2F 64 65 74 61 69 6C 20 73 65 74 2C 00 00
+77 2F 64 65 74 61 69 6C 20 73 65 74 20 61 6E 64
+20 69 6E 74 65 72 69 6F 72 20 73 65 74 2C 20 72
+65 73 69 6E 20 65 6E 67 69 6E 65 73 03 00 00 49
+43 4D 0E 00 00 53 70 69 74 66 69 72 65 20 4D 6B
+2E 49 58 1A 00 00 4D 65 73 73 65 72 73 63 68 6D
+69 74 74 20 4D 65 20 34 31 30 42 2D 32 2F 55 34
+0A 00 00 4D 6F 64 65 6C 63 72 61 66 74 12 00 00
+46 2D 38 32 42 20 54 77 69 6E 20 4D 75 73 74 61
+6E 67 1F 00 00 31 39 35 33 20 53 74 75 64 65 62
+61 6B 65 72 20 53 74 61 72 6C 69 6E 65 72 20 43
+6F 75 70 65 04 00 00 32 34 33 36 0E 00 00 42 75
+67 61 74 74 69 20 45 42 20 31 31 30 2D 00 00 53
+74 61 72 20 54 72 65 6B 20 4B 6C 69 6E 67 6F 6E
+20 42 69 72 64 20 6F 66 20 50 72 65 79 20 46 6C
+69 67 68 74 20 44 69 73 70 6C 61 79 16 00 00 50
+6F 72 73 63 68 65 20 39 31 31 20 53 6C 61 6E 74
+20 4E 6F 73 65 05 00 00 36 31 30 37 33 25 00 00
+44 6F 75 67 6C 61 73 20 41 2D 31 4A 20 53 6B 79
+72 61 69 64 65 72 20 55 2E 53 2E 20 41 69 72 20
+46 6F 72 63 65 04 00 00 36 33 33 39 04 00 00 36
+39 35 35 04 00 00 37 35 33 30 06 00 00 34 38 2D
+30 32 30 05 00 00 31 2F 34 35 30 0F 00 00 55 2E
+53 2E 53 2E 20 4D 69 73 73 6F 75 72 69 05 00 00
+36 31 30 35 37 15 00 00 48 65 69 6E 6B 65 6C 20
+48 65 32 31 39 20 41 2D 37 20 55 48 55 05 00 00
+36 31 30 34 31 05 00 00 31 31 36 32 34 32 00 00
+43 6F 6E 73 6F 6C 69 64 61 74 65 64 20 42 2D 32
+34 4A 20 4C 69 62 65 72 61 74 6F 72 20 54 68 65
+20 44 72 61 67 6F 6E 20 26 20 48 69 73 20 54 61
+69
diff --git a/src/testcases/org/apache/poi/hssf/data/duprich1.xls b/src/testcases/org/apache/poi/hssf/data/duprich1.xls Binary files differnew file mode 100644 index 0000000000..3fddbedd27 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/data/duprich1.xls diff --git a/src/testcases/org/apache/poi/hssf/data/duprich2.xls b/src/testcases/org/apache/poi/hssf/data/duprich2.xls Binary files differnew file mode 100644 index 0000000000..57af63b3d4 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/data/duprich2.xls diff --git a/src/testcases/org/apache/poi/hssf/data/evencontinuation.txt b/src/testcases/org/apache/poi/hssf/data/evencontinuation.txt new file mode 100644 index 0000000000..4740b27472 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/data/evencontinuation.txt @@ -0,0 +1,16 @@ +14 00 # String length 0x14=20 +01 # Option flag, 16bit +# String: At a dinner party or +41 00 74 00 20 00 61 00 20 00 +64 00 69 00 6E 00 6E 00 65 00 +72 00 20 00 70 00 61 00 72 00 +74 00 79 00 20 00 6F 00 72 00 + +# Continuation record (new string on the boundry) +11 00 # String length 0x11=17 +00 # Option flag, 8bit +# String: At a dinner party +41 74 20 61 20 +64 69 6E 6E 65 +72 20 70 61 72 +74 79 diff --git a/src/testcases/org/apache/poi/hssf/data/richtextdata.txt b/src/testcases/org/apache/poi/hssf/data/richtextdata.txt new file mode 100644 index 0000000000..a345595831 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/data/richtextdata.txt @@ -0,0 +1,21 @@ +1D 00 # String length 0x1b=29 +09 # Option flag, rich text + 16bit +02 00 # Formatting runs +# String: At a dinner party or +41 00 74 00 20 00 61 00 20 00 +64 00 69 00 6E 00 6E 00 65 00 +72 00 20 00 70 00 61 00 72 00 +74 00 79 00 20 00 6F 00 72 00 + +# Continuation record +00 # option flag + +# string:at at at +41 74 20 +41 74 20 +41 74 20 + +00 00 # Formatting run 1, first formated char at 0 +00 00 # Formatting run 1, Index to font record +02 00 # Formatting run 2, first formated char at 2 +00 00 # Formatting run 2, Index to font record diff --git a/src/testcases/org/apache/poi/hssf/data/stringacross2continuations.txt b/src/testcases/org/apache/poi/hssf/data/stringacross2continuations.txt new file mode 100644 index 0000000000..c9bc332e56 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/data/stringacross2continuations.txt @@ -0,0 +1,7 @@ +14 00 # String length 0x14=20 +01 # Option flag, 16bit +# String: At a dinner party or +41 00 74 00 20 00 61 00 20 00 +64 00 69 00 6E 00 6E 00 65 00 +72 00 20 00 70 00 61 00 72 00 +74 00 79 00 20 00 6F 00 72 00 diff --git a/src/testcases/org/apache/poi/hssf/data/stringacross2continuationsCR1.txt b/src/testcases/org/apache/poi/hssf/data/stringacross2continuationsCR1.txt new file mode 100644 index 0000000000..821142adec --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/data/stringacross2continuationsCR1.txt @@ -0,0 +1,9 @@ + +# Continuation record +22 00 # String length 0x11=17 +00 # Option flag, 8bit +# String: At a dinner party +41 74 20 61 20 +64 69 6E 6E 65 +72 20 70 61 72 +74 79 diff --git a/src/testcases/org/apache/poi/hssf/data/stringacross2continuationsCR2.txt b/src/testcases/org/apache/poi/hssf/data/stringacross2continuationsCR2.txt new file mode 100644 index 0000000000..f4eb4c3c3c --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/data/stringacross2continuationsCR2.txt @@ -0,0 +1,7 @@ +# Continuation record +00 # option flag +# String: At a dinner party +41 74 20 61 20 +64 69 6E 6E 65 +72 20 70 61 72 +74 79 diff --git a/src/testcases/org/apache/poi/hssf/record/TestSSTRecord.java b/src/testcases/org/apache/poi/hssf/record/TestSSTRecord.java index 56e6fec764..b574a34263 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestSSTRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestSSTRecord.java @@ -1,4 +1,3 @@ - /* ==================================================================== * The Apache Software License, Version 1.1 * @@ -55,24 +54,29 @@ package org.apache.poi.hssf.record; -import org.apache.poi.util.*; - -import junit.framework.*; +import junit.framework.TestCase; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.util.BinaryTree; +import org.apache.poi.util.HexRead; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; import java.io.*; - -import java.util.*; +import java.util.Arrays; +import java.util.Iterator; /** * @author Marc Johnson (mjohnson at apache dot org) + * @author Glen Stampoultzis (glens at apache.org) */ public class TestSSTRecord - extends TestCase + extends TestCase { - private String _test_file_path; + private String _test_file_path; private static final String _test_file_path_property = - "HSSF.testdata.path"; + "HSSF.testdata.path"; /** * Creates new TestSSTRecord @@ -80,10 +84,10 @@ public class TestSSTRecord * @param name */ - public TestSSTRecord(String name) + public TestSSTRecord( String name ) { - super(name); - _test_file_path = System.getProperty(_test_file_path_property); + super( name ); + _test_file_path = System.getProperty( _test_file_path_property ); } /** @@ -93,118 +97,119 @@ public class TestSSTRecord */ public void testProcessContinueRecord() - throws IOException + throws IOException { - byte[] testdata = readTestData("BigSSTRecord"); - byte[] input = new byte[ testdata.length - 4 ]; - - System.arraycopy(testdata, 4, input, 0, input.length); - SSTRecord record = - new SSTRecord(LittleEndian.getShort(testdata, 0), - LittleEndian.getShort(testdata, 2), input); - byte[] continueRecord = readTestData("BigSSTRecordCR"); - - input = new byte[ continueRecord.length - 4 ]; - System.arraycopy(continueRecord, 4, input, 0, input.length); - record.processContinueRecord(input); - assertEquals(1464, record.getNumStrings()); - assertEquals(688, record.getNumUniqueStrings()); - assertEquals(688, record.countStrings()); + byte[] testdata = HexRead.readTestData( _test_file_path + File.separator + "BigSSTRecord" ); + byte[] input = new byte[testdata.length - 4]; + + System.arraycopy( testdata, 4, input, 0, input.length ); + SSTRecord record = + new SSTRecord( LittleEndian.getShort( testdata, 0 ), + LittleEndian.getShort( testdata, 2 ), input ); + byte[] continueRecord = HexRead.readTestData( _test_file_path + File.separator + "BigSSTRecordCR" ); + + input = new byte[continueRecord.length - 4]; + System.arraycopy( continueRecord, 4, input, 0, input.length ); + record.processContinueRecord( input ); + assertEquals( 1464, record.getNumStrings() ); + assertEquals( 688, record.getNumUniqueStrings() ); + assertEquals( 688, record.countStrings() ); byte[] ser_output = record.serialize(); - int offset = 0; - short type = LittleEndian.getShort(ser_output, offset); + int offset = 0; + short type = LittleEndian.getShort( ser_output, offset ); offset += LittleEndianConsts.SHORT_SIZE; - short length = LittleEndian.getShort(ser_output, offset); + short length = LittleEndian.getShort( ser_output, offset ); offset += LittleEndianConsts.SHORT_SIZE; - byte[] recordData = new byte[ length ]; + byte[] recordData = new byte[length]; - System.arraycopy(ser_output, offset, recordData, 0, length); + System.arraycopy( ser_output, offset, recordData, 0, length ); offset += length; - SSTRecord testRecord = new SSTRecord(type, length, recordData); + SSTRecord testRecord = new SSTRecord( type, length, recordData ); - assertEquals(ContinueRecord.sid, - LittleEndian.getShort(ser_output, offset)); + assertEquals( ContinueRecord.sid, + LittleEndian.getShort( ser_output, offset ) ); offset += LittleEndianConsts.SHORT_SIZE; - length = LittleEndian.getShort(ser_output, offset); + length = LittleEndian.getShort( ser_output, offset ); offset += LittleEndianConsts.SHORT_SIZE; - byte[] cr = new byte[ length ]; + byte[] cr = new byte[length]; - System.arraycopy(ser_output, offset, cr, 0, length); + System.arraycopy( ser_output, offset, cr, 0, length ); offset += length; - assertEquals(offset, ser_output.length); - testRecord.processContinueRecord(cr); - assertEquals(record, testRecord); + assertEquals( offset, ser_output.length ); + testRecord.processContinueRecord( cr ); + assertEquals( record, testRecord ); // testing based on new bug report - testdata = readTestData("BigSSTRecord2"); - input = new byte[ testdata.length - 4 ]; - System.arraycopy(testdata, 4, input, 0, input.length); - record = new SSTRecord(LittleEndian.getShort(testdata, 0), - LittleEndian.getShort(testdata, 2), input); - byte[] continueRecord1 = readTestData("BigSSTRecord2CR1"); - - input = new byte[ continueRecord1.length - 4 ]; - System.arraycopy(continueRecord1, 4, input, 0, input.length); - record.processContinueRecord(input); - byte[] continueRecord2 = readTestData("BigSSTRecord2CR2"); - - input = new byte[ continueRecord2.length - 4 ]; - System.arraycopy(continueRecord2, 4, input, 0, input.length); - record.processContinueRecord(input); - byte[] continueRecord3 = readTestData("BigSSTRecord2CR3"); - - input = new byte[ continueRecord3.length - 4 ]; - System.arraycopy(continueRecord3, 4, input, 0, input.length); - record.processContinueRecord(input); - byte[] continueRecord4 = readTestData("BigSSTRecord2CR4"); - - input = new byte[ continueRecord4.length - 4 ]; - System.arraycopy(continueRecord4, 4, input, 0, input.length); - record.processContinueRecord(input); - byte[] continueRecord5 = readTestData("BigSSTRecord2CR5"); - - input = new byte[ continueRecord5.length - 4 ]; - System.arraycopy(continueRecord5, 4, input, 0, input.length); - record.processContinueRecord(input); - byte[] continueRecord6 = readTestData("BigSSTRecord2CR6"); - - input = new byte[ continueRecord6.length - 4 ]; - System.arraycopy(continueRecord6, 4, input, 0, input.length); - record.processContinueRecord(input); - byte[] continueRecord7 = readTestData("BigSSTRecord2CR7"); - - input = new byte[ continueRecord7.length - 4 ]; - System.arraycopy(continueRecord7, 4, input, 0, input.length); - record.processContinueRecord(input); - assertEquals(158642, record.getNumStrings()); - assertEquals(5249, record.getNumUniqueStrings()); - assertEquals(5249, record.countStrings()); + testdata = HexRead.readTestData( _test_file_path + File.separator + "BigSSTRecord2" ); + input = new byte[testdata.length - 4]; + System.arraycopy( testdata, 4, input, 0, input.length ); + record = new SSTRecord( LittleEndian.getShort( testdata, 0 ), + LittleEndian.getShort( testdata, 2 ), input ); + byte[] continueRecord1 = HexRead.readTestData( _test_file_path + File.separator + "BigSSTRecord2CR1" ); + + input = new byte[continueRecord1.length - 4]; + System.arraycopy( continueRecord1, 4, input, 0, input.length ); + record.processContinueRecord( input ); + byte[] continueRecord2 = HexRead.readTestData( _test_file_path + File.separator + "BigSSTRecord2CR2" ); + + input = new byte[continueRecord2.length - 4]; + System.arraycopy( continueRecord2, 4, input, 0, input.length ); + record.processContinueRecord( input ); + byte[] continueRecord3 = HexRead.readTestData( _test_file_path + File.separator + "BigSSTRecord2CR3" ); + + input = new byte[continueRecord3.length - 4]; + System.arraycopy( continueRecord3, 4, input, 0, input.length ); + record.processContinueRecord( input ); + byte[] continueRecord4 = HexRead.readTestData( _test_file_path + File.separator + "BigSSTRecord2CR4" ); + + input = new byte[continueRecord4.length - 4]; + System.arraycopy( continueRecord4, 4, input, 0, input.length ); + record.processContinueRecord( input ); + byte[] continueRecord5 = HexRead.readTestData( _test_file_path + File.separator + "BigSSTRecord2CR5" ); + + input = new byte[continueRecord5.length - 4]; + System.arraycopy( continueRecord5, 4, input, 0, input.length ); + record.processContinueRecord( input ); + byte[] continueRecord6 = HexRead.readTestData( _test_file_path + File.separator + "BigSSTRecord2CR6" ); + + input = new byte[continueRecord6.length - 4]; + System.arraycopy( continueRecord6, 4, input, 0, input.length ); + record.processContinueRecord( input ); + byte[] continueRecord7 = HexRead.readTestData( _test_file_path + File.separator + "BigSSTRecord2CR7" ); + + input = new byte[continueRecord7.length - 4]; + System.arraycopy( continueRecord7, 4, input, 0, input.length ); + record.processContinueRecord( input ); + assertEquals( 158642, record.getNumStrings() ); + assertEquals( 5249, record.getNumUniqueStrings() ); + assertEquals( 5249, record.countStrings() ); ser_output = record.serialize(); - offset = 0; - type = LittleEndian.getShort(ser_output, offset); - offset += LittleEndianConsts.SHORT_SIZE; - length = LittleEndian.getShort(ser_output, offset); - offset += LittleEndianConsts.SHORT_SIZE; - recordData = new byte[ length ]; - System.arraycopy(ser_output, offset, recordData, 0, length); - offset += length; - testRecord = new SSTRecord(type, length, recordData); - for (int count = 0; count < 7; count++) + offset = 0; + type = LittleEndian.getShort( ser_output, offset ); + offset += LittleEndianConsts.SHORT_SIZE; + length = LittleEndian.getShort( ser_output, offset ); + offset += LittleEndianConsts.SHORT_SIZE; + recordData = new byte[length]; + System.arraycopy( ser_output, offset, recordData, 0, length ); + offset += length; + testRecord = new SSTRecord( type, length, recordData ); + for ( int count = 0; count < 7; count++ ) { - assertEquals(ContinueRecord.sid, - LittleEndian.getShort(ser_output, offset)); + assertEquals( ContinueRecord.sid, + LittleEndian.getShort( ser_output, offset ) ); offset += LittleEndianConsts.SHORT_SIZE; - length = LittleEndian.getShort(ser_output, offset); + length = LittleEndian.getShort( ser_output, offset ); offset += LittleEndianConsts.SHORT_SIZE; - cr = new byte[ length ]; - System.arraycopy(ser_output, offset, cr, 0, length); - testRecord.processContinueRecord(cr); + cr = new byte[length]; + System.arraycopy( ser_output, offset, cr, 0, length ); + testRecord.processContinueRecord( cr ); offset += length; } - assertEquals(offset, ser_output.length); - assertEquals(record, testRecord); + assertEquals( offset, ser_output.length ); + assertEquals( record, testRecord ); + assertEquals( record.countStrings(), testRecord.countStrings() ); } /** @@ -214,23 +219,23 @@ public class TestSSTRecord */ public void testHugeStrings() - throws IOException + throws IOException { - SSTRecord record = new SSTRecord(); - byte[][] bstrings = - { - new byte[ 9000 ], new byte[ 7433 ], new byte[ 9002 ], - new byte[ 16998 ] - }; - String[] strings = new String[ bstrings.length ]; - int total_length = 0; - - for (int k = 0; k < bstrings.length; k++) + SSTRecord record = new SSTRecord(); + byte[][] bstrings = + { + new byte[9000], new byte[7433], new byte[9002], + new byte[16998] + }; + String[] strings = new String[bstrings.length]; + int total_length = 0; + + for ( int k = 0; k < bstrings.length; k++ ) { - Arrays.fill(bstrings[ k ], ( byte ) ('a' + k)); - strings[ k ] = new String(bstrings[ k ]); - record.addString(strings[ k ]); - total_length += 3 + bstrings[ k ].length; + Arrays.fill( bstrings[k], (byte) ( 'a' + k ) ); + strings[k] = new String( bstrings[k] ); + record.addString( strings[k] ); + total_length += 3 + bstrings[k].length; } // add overhead of SST record @@ -240,88 +245,88 @@ public class TestSSTRecord total_length += 4; // add overhead of six records - total_length += (6 * 4); - byte[] content = new byte[ record.getRecordSize() ]; + total_length += ( 6 * 4 ); + byte[] content = new byte[record.getRecordSize()]; - record.serialize(0, content); - assertEquals(total_length, content.length); - for (int index = 0; index != content.length; ) + record.serialize( 0, content ); + assertEquals( total_length, content.length ); + for ( int index = 0; index != content.length; ) { - short record_type = LittleEndian.getShort(content, index); + short record_type = LittleEndian.getShort( content, index ); index += LittleEndianConsts.SHORT_SIZE; - short record_length = LittleEndian.getShort(content, index); + short record_length = LittleEndian.getShort( content, index ); index += LittleEndianConsts.SHORT_SIZE; - byte[] data = new byte[ record_length ]; + byte[] data = new byte[record_length]; - System.arraycopy(content, index, data, 0, record_length); + System.arraycopy( content, index, data, 0, record_length ); index += record_length; - if (record_type == SSTRecord.sid) + if ( record_type == SSTRecord.sid ) { - record = new SSTRecord(record_type, record_length, data); + record = new SSTRecord( record_type, record_length, data ); } else { - record.processContinueRecord(data); + record.processContinueRecord( data ); } } - assertEquals(strings.length, record.getNumStrings()); - assertEquals(strings.length, record.getNumUniqueStrings()); - assertEquals(strings.length, record.countStrings()); - for (int k = 0; k < strings.length; k++) + assertEquals( strings.length, record.getNumStrings() ); + assertEquals( strings.length, record.getNumUniqueStrings() ); + assertEquals( strings.length, record.countStrings() ); + for ( int k = 0; k < strings.length; k++ ) { - assertEquals(strings[ k ], record.getString(k)); + assertEquals( strings[k], record.getString( k ) ); } - record = new SSTRecord(); - bstrings[ 1 ] = new byte[ bstrings[ 1 ].length - 1 ]; - for (int k = 0; k < bstrings.length; k++) + record = new SSTRecord(); + bstrings[1] = new byte[bstrings[1].length - 1]; + for ( int k = 0; k < bstrings.length; k++ ) { - if ((bstrings[ k ].length % 2) == 1) + if ( ( bstrings[k].length % 2 ) == 1 ) { - Arrays.fill(bstrings[ k ], ( byte ) ('a' + k)); - strings[ k ] = new String(bstrings[ k ]); + Arrays.fill( bstrings[k], (byte) ( 'a' + k ) ); + strings[k] = new String( bstrings[k] ); } else { - char[] data = new char[ bstrings[ k ].length / 2 ]; + char[] data = new char[bstrings[k].length / 2]; - Arrays.fill(data, ( char ) ('\u2122' + k)); - strings[ k ] = new String(data); + Arrays.fill( data, (char) ( '\u2122' + k ) ); + strings[k] = new String( data ); } - record.addString(strings[ k ]); + record.addString( strings[k] ); } - content = new byte[ record.getRecordSize() ]; - record.serialize(0, content); + content = new byte[record.getRecordSize()]; + record.serialize( 0, content ); total_length--; - assertEquals(total_length, content.length); - for (int index = 0; index != content.length; ) + assertEquals( total_length, content.length ); + for ( int index = 0; index != content.length; ) { - short record_type = LittleEndian.getShort(content, index); + short record_type = LittleEndian.getShort( content, index ); index += LittleEndianConsts.SHORT_SIZE; - short record_length = LittleEndian.getShort(content, index); + short record_length = LittleEndian.getShort( content, index ); index += LittleEndianConsts.SHORT_SIZE; - byte[] data = new byte[ record_length ]; + byte[] data = new byte[record_length]; - System.arraycopy(content, index, data, 0, record_length); + System.arraycopy( content, index, data, 0, record_length ); index += record_length; - if (record_type == SSTRecord.sid) + if ( record_type == SSTRecord.sid ) { - record = new SSTRecord(record_type, record_length, data); + record = new SSTRecord( record_type, record_length, data ); } else { - record.processContinueRecord(data); + record.processContinueRecord( data ); } } - assertEquals(strings.length, record.getNumStrings()); - assertEquals(strings.length, record.getNumUniqueStrings()); - assertEquals(strings.length, record.countStrings()); - for (int k = 0; k < strings.length; k++) + assertEquals( strings.length, record.getNumStrings() ); + assertEquals( strings.length, record.getNumUniqueStrings() ); + assertEquals( strings.length, record.countStrings() ); + for ( int k = 0; k < strings.length; k++ ) { - assertEquals(strings[ k ], record.getString(k)); + assertEquals( strings[k], record.getString( k ) ); } } @@ -330,9 +335,8 @@ public class TestSSTRecord * * @exception IOException */ - public void testSSTRecordBug() - throws IOException + throws IOException { // create an SSTRecord and write a certain pattern of strings @@ -342,68 +346,67 @@ public class TestSSTRecord // the record will start with two integers, then this string // ... that will eat up 16 of the 8224 bytes that the record // can hold - record.addString("Hello"); + record.addString( "Hello" ); // now we have an additional 8208 bytes, which is an exact // multiple of 16 bytes long testvalue = 1000000000000L; - for (int k = 0; k < 2000; k++) + for ( int k = 0; k < 2000; k++ ) { - record.addString(String.valueOf(testvalue++)); + record.addString( String.valueOf( testvalue++ ) ); } - byte[] content = new byte[ record.getRecordSize() ]; + byte[] content = new byte[record.getRecordSize()]; - record.serialize(0, content); - assertEquals(( byte ) 13, content[ 4 + 8228 ]); - assertEquals(( byte ) 13, content[ 4 + 8228 * 2 ]); - assertEquals(( byte ) 13, content[ 4 + 8228 * 3 ]); + record.serialize( 0, content ); + assertEquals( (byte) 13, content[4 + 8228] ); + assertEquals( (byte) 13, content[4 + 8228 * 2] ); + assertEquals( (byte) 13, content[4 + 8228 * 3] ); } /** * test simple addString */ - public void testSimpleAddString() { SSTRecord record = new SSTRecord(); - String s1 = "Hello world"; + String s1 = "Hello world"; // \u2122 is the encoding of the trademark symbol ... - String s2 = "Hello world\u2122"; - - assertEquals(0, record.addString(s1)); - assertEquals(s1, record.getString(0)); - assertEquals(1, record.countStrings()); - assertEquals(1, record.getNumStrings()); - assertEquals(1, record.getNumUniqueStrings()); - assertEquals(0, record.addString(s1)); - assertEquals(s1, record.getString(0)); - assertEquals(1, record.countStrings()); - assertEquals(2, record.getNumStrings()); - assertEquals(1, record.getNumUniqueStrings()); - assertEquals(1, record.addString(s2)); - assertEquals(s2, record.getString(1)); - assertEquals(2, record.countStrings()); - assertEquals(3, record.getNumStrings()); - assertEquals(2, record.getNumUniqueStrings()); + String s2 = "Hello world\u2122"; + + assertEquals( 0, record.addString( s1 ) ); + assertEquals( s1, record.getString( 0 ) ); + assertEquals( 1, record.countStrings() ); + assertEquals( 1, record.getNumStrings() ); + assertEquals( 1, record.getNumUniqueStrings() ); + assertEquals( 0, record.addString( s1 ) ); + assertEquals( s1, record.getString( 0 ) ); + assertEquals( 1, record.countStrings() ); + assertEquals( 2, record.getNumStrings() ); + assertEquals( 1, record.getNumUniqueStrings() ); + assertEquals( 1, record.addString( s2 ) ); + assertEquals( s2, record.getString( 1 ) ); + assertEquals( 2, record.countStrings() ); + assertEquals( 3, record.getNumStrings() ); + assertEquals( 2, record.getNumUniqueStrings() ); Iterator iter = record.getStrings(); - while (iter.hasNext()) + while ( iter.hasNext() ) { - UnicodeString ucs = ( UnicodeString ) iter.next(); + UnicodeString ucs = (UnicodeString) iter.next(); - if (ucs.getString().equals(s1)) + if ( ucs.getString().equals( s1 ) ) { - assertEquals(( byte ) 0, ucs.getOptionFlags()); + assertEquals( (byte) 0, ucs.getOptionFlags() ); } - else if (ucs.getString().equals(s2)) + else if ( ucs.getString().equals( s2 ) ) { - assertEquals(( byte ) 1, ucs.getOptionFlags()); + assertEquals( (byte) 1, ucs.getOptionFlags() ); } else { - fail("cannot match string: " + ucs.getString()); + fail( "cannot match string: " + ucs.getString() ); } } } @@ -415,25 +418,25 @@ public class TestSSTRecord */ public void testReaderConstructor() - throws IOException + throws IOException { - byte[] testdata = readTestData("BigSSTRecord"); - byte[] input = new byte[ testdata.length - 4 ]; - - System.arraycopy(testdata, 4, input, 0, input.length); - SSTRecord record = new SSTRecord(LittleEndian.getShort(testdata, 0), - LittleEndian.getShort(testdata, 2), - input); - - assertEquals(1464, record.getNumStrings()); - assertEquals(688, record.getNumUniqueStrings()); - assertEquals(492, record.countStrings()); - assertEquals(1, record.getExpectedChars()); - assertEquals("Consolidated B-24J Liberator The Dragon & His Tai", - record.getUnfinishedString()); - assertEquals(52, record.getTotalLength()); - assertEquals(3, record.getStringDataOffset()); - assertTrue(!record.isWideChar()); + byte[] testdata = HexRead.readTestData( _test_file_path + File.separator + "BigSSTRecord" ); + byte[] input = new byte[testdata.length - 4]; + + System.arraycopy( testdata, 4, input, 0, input.length ); + SSTRecord record = new SSTRecord( LittleEndian.getShort( testdata, 0 ), + LittleEndian.getShort( testdata, 2 ), + input ); + + assertEquals( 1464, record.getNumStrings() ); + assertEquals( 688, record.getNumUniqueStrings() ); + assertEquals( 492, record.countStrings() ); + assertEquals( 1, record.getDeserializer().getContinuationExpectedChars() ); + assertEquals( "Consolidated B-24J Liberator The Dragon & His Tai", + record.getDeserializer().getUnfinishedString() ); +// assertEquals( 52, record.getDeserializer().getTotalLength() ); +// assertEquals( 3, record.getDeserializer().getStringDataOffset() ); + assertTrue( !record.getDeserializer().isWideChar() ); } /** @@ -444,26 +447,26 @@ public class TestSSTRecord { SSTRecord record = new SSTRecord(); - assertEquals(0, record.getNumStrings()); - assertEquals(0, record.getNumUniqueStrings()); - assertEquals(0, record.countStrings()); - assertEquals(0, record.getExpectedChars()); - assertEquals("", record.getUnfinishedString()); - assertEquals(0, record.getTotalLength()); - assertEquals(0, record.getStringDataOffset()); - assertTrue(!record.isWideChar()); - byte[] output = record.serialize(); + assertEquals( 0, record.getNumStrings() ); + assertEquals( 0, record.getNumUniqueStrings() ); + assertEquals( 0, record.countStrings() ); + assertEquals( 0, record.getDeserializer().getContinuationExpectedChars() ); + assertEquals( "", record.getDeserializer().getUnfinishedString() ); +// assertEquals( 0, record.getDeserializer().getTotalLength() ); +// assertEquals( 0, record.getDeserializer().getStringDataOffset() ); + assertTrue( !record.getDeserializer().isWideChar() ); + byte[] output = record.serialize(); byte[] expected = + { + (byte) record.getSid(), (byte) ( record.getSid() >> 8 ), + (byte) 8, (byte) 0, (byte) 0, (byte) 0, (byte) 0, + (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 + }; + + assertEquals( expected.length, output.length ); + for ( int k = 0; k < expected.length; k++ ) { - ( byte ) record.getSid(), ( byte ) (record.getSid() >> 8), - ( byte ) 8, ( byte ) 0, ( byte ) 0, ( byte ) 0, ( byte ) 0, - ( byte ) 0, ( byte ) 0, ( byte ) 0, ( byte ) 0, ( byte ) 0 - }; - - assertEquals(expected.length, output.length); - for (int k = 0; k < expected.length; k++) - { - assertEquals(String.valueOf(k), expected[ k ], output[ k ]); + assertEquals( String.valueOf( k ), expected[k], output[k] ); } } @@ -473,102 +476,99 @@ public class TestSSTRecord * @param ignored_args */ - public static void main(String [] ignored_args) + public static void main( String[] ignored_args ) { - System.out.println("Testing hssf.record.SSTRecord functionality"); - junit.textui.TestRunner.run(TestSSTRecord.class); + System.out.println( "Testing hssf.record.SSTRecord functionality" ); + junit.textui.TestRunner.run( TestSSTRecord.class ); } - private byte [] readTestData(String filename) - throws IOException + /** + * Tests that workbooks with rich text that duplicates a non rich text cell can be read and written. + */ + public void testReadWriteDuplicatedRichText1() + throws Exception { - File file = new File(_test_file_path - + File.separator - + filename); - FileInputStream stream = new FileInputStream(file); - int characterCount = 0; - byte b = ( byte ) 0; - List bytes = new ArrayList(); - boolean done = false; - - while (!done) - { - int count = stream.read(); + File file = new File( _test_file_path + File.separator + "duprich1.xls" ); + InputStream stream = new FileInputStream( file ); + HSSFWorkbook wb = new HSSFWorkbook( stream ); + stream.close(); + HSSFSheet sheet = wb.getSheetAt( 1 ); + assertEquals( "01/05 (Wed) ", sheet.getRow( 0 ).getCell( (short) 8 ).getStringCellValue() ); + assertEquals( "01/05 (Wed)", sheet.getRow( 1 ).getCell( (short) 8 ).getStringCellValue() ); + + file = File.createTempFile( "testout", "xls" ); + FileOutputStream outStream = new FileOutputStream( file ); + wb.write( outStream ); + outStream.close(); + file.delete(); + + // test the second file. + file = new File( _test_file_path + File.separator + "duprich2.xls" ); + stream = new FileInputStream( file ); + wb = new HSSFWorkbook( stream ); + stream.close(); + sheet = wb.getSheetAt( 0 ); + int row = 0; + assertEquals( "Testing ", sheet.getRow( row++ ).getCell( (short) 0 ).getStringCellValue() ); + assertEquals( "rich", sheet.getRow( row++ ).getCell( (short) 0 ).getStringCellValue() ); + assertEquals( "text", sheet.getRow( row++ ).getCell( (short) 0 ).getStringCellValue() ); + assertEquals( "strings", sheet.getRow( row++ ).getCell( (short) 0 ).getStringCellValue() ); + assertEquals( "Testing ", sheet.getRow( row++ ).getCell( (short) 0 ).getStringCellValue() ); + assertEquals( "Testing", sheet.getRow( row++ ).getCell( (short) 0 ).getStringCellValue() ); + +// file = new File("/tryme.xls"); + file = File.createTempFile( "testout", ".xls" ); + outStream = new FileOutputStream( file ); + wb.write( outStream ); + outStream.close(); + file.delete(); + } - switch (count) - { + public void testSpanRichTextToPlainText() + throws Exception + { + byte[] bytes = HexRead.readTestData( _test_file_path + File.separator + "richtextdata.txt" ); + BinaryTree strings = new BinaryTree(); + SSTDeserializer deserializer = new SSTDeserializer( strings ); + deserializer.manufactureStrings( bytes, 0, (short) 45 ); + byte[] continueBytes = new byte[bytes.length - 45]; + System.arraycopy( bytes, 45, continueBytes, 0, bytes.length - 45 ); + deserializer.processContinueRecord( continueBytes ); +// System.out.println( "strings.getKeyForValue(new Integer(0)) = " + strings.get( new Integer( 0 ) ) ); + + assertEquals( "At a dinner party orAt At At ", strings.get( new Integer( 0 ) ) + "" ); + } - case '0' : - case '1' : - case '2' : - case '3' : - case '4' : - case '5' : - case '6' : - case '7' : - case '8' : - case '9' : - b <<= 4; - b += ( byte ) (count - '0'); - characterCount++; - if (characterCount == 2) - { - bytes.add(new Byte(b)); - characterCount = 0; - b = ( byte ) 0; - } - break; - - case 'A' : - case 'B' : - case 'C' : - case 'D' : - case 'E' : - case 'F' : - b <<= 4; - b += ( byte ) (count + 10 - 'A'); - characterCount++; - if (characterCount == 2) - { - bytes.add(new Byte(b)); - characterCount = 0; - b = ( byte ) 0; - } - break; - - case 'a' : - case 'b' : - case 'c' : - case 'd' : - case 'e' : - case 'f' : - b <<= 4; - b += ( byte ) (count + 10 - 'a'); - characterCount++; - if (characterCount == 2) - { - bytes.add(new Byte(b)); - characterCount = 0; - b = ( byte ) 0; - } - break; - - case -1 : - done = true; - break; - - default : - break; - } - } - stream.close(); - Byte[] polished = ( Byte [] ) bytes.toArray(new Byte[ 0 ]); - byte[] rval = new byte[ polished.length ]; + public void testContinuationWithNoOverlap() + throws Exception + { + byte[] bytes = HexRead.readTestData( _test_file_path + File.separator + "evencontinuation.txt" ); + BinaryTree strings = new BinaryTree(); + SSTDeserializer deserializer = new SSTDeserializer( strings ); + deserializer.manufactureStrings( bytes, 0, (short) 43 ); + byte[] continueBytes = new byte[bytes.length - 43]; + System.arraycopy( bytes, 43, continueBytes, 0, bytes.length - 43 ); + deserializer.processContinueRecord( continueBytes ); + + assertEquals( "At a dinner party or", strings.get( new Integer( 0 ) ) + "" ); + assertEquals( "At a dinner party", strings.get( new Integer( 1 ) ) + "" ); + + } + + public void testStringAcross2Continuations() + throws Exception + { + byte[] bytes = HexRead.readTestData( _test_file_path + File.separator + "stringacross2continuations.txt" ); + BinaryTree strings = new BinaryTree(); + SSTDeserializer deserializer = new SSTDeserializer( strings ); + deserializer.manufactureStrings( bytes, 0, (short) 43 ); + bytes = HexRead.readTestData( _test_file_path + File.separator + "stringacross2continuationsCR1.txt" ); + deserializer.processContinueRecord( bytes ); + bytes = HexRead.readTestData( _test_file_path + File.separator + "stringacross2continuationsCR2.txt" ); + deserializer.processContinueRecord( bytes ); + + assertEquals( "At a dinner party or", strings.get( new Integer( 0 ) ) + "" ); + assertEquals( "At a dinner partyAt a dinner party", strings.get( new Integer( 1 ) ) + "" ); - for (int j = 0; j < polished.length; j++) - { - rval[ j ] = polished[ j ].byteValue(); - } - return rval; } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java index f8c584839a..3c7fb51636 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java @@ -55,7 +55,10 @@ package org.apache.poi.hssf.usermodel; import junit.framework.TestCase; -import org.apache.poi.hssf.record.RowRecord; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; /** * Test HSSFRow is okay. @@ -87,33 +90,47 @@ public class TestHSSFRow assertEquals(1, row.getFirstCellNum()); assertEquals(2, row.getLastCellNum()); - RowRecord rowRecord = new RowRecord(); - rowRecord.setFirstCol((short) 2); - rowRecord.setLastCol((short) 5); - row = new HSSFRow(workbook.getWorkbook(), sheet.getSheet(), rowRecord); - assertEquals(2, row.getFirstCellNum()); - assertEquals(5, row.getLastCellNum()); } public void testRemoveCell() + throws Exception { HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet(); HSSFRow row = sheet.createRow((short) 0); assertEquals(-1, row.getLastCellNum()); assertEquals(-1, row.getFirstCellNum()); - row.createCell((short)1); + row.createCell((short) 1); assertEquals(1, row.getLastCellNum()); assertEquals(1, row.getFirstCellNum()); - row.createCell((short)3); + row.createCell((short) 3); assertEquals(3, row.getLastCellNum()); assertEquals(1, row.getFirstCellNum()); - row.removeCell(row.getCell((short)3)); + row.removeCell(row.getCell((short) 3)); assertEquals(1, row.getLastCellNum()); assertEquals(1, row.getFirstCellNum()); - row.removeCell(row.getCell((short)1)); + row.removeCell(row.getCell((short) 1)); assertEquals(-1, row.getLastCellNum()); assertEquals(-1, row.getFirstCellNum()); + // check the row record actually writes it out as 0's + byte[] data = new byte[100]; + row.getRowRecord().serialize(0, data); + assertEquals(0, data[6]); + assertEquals(0, data[8]); + + File file = File.createTempFile("XXX", "XLS"); + FileOutputStream stream = new FileOutputStream(file); + workbook.write(stream); + stream.close(); + FileInputStream inputStream = new FileInputStream(file); + workbook = new HSSFWorkbook(inputStream); + sheet = workbook.getSheetAt(0); + stream.close(); + file.delete(); + assertEquals(-1, sheet.getRow((short) 0).getLastCellNum()); + assertEquals(-1, sheet.getRow((short) 0).getFirstCellNum()); + + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java index 4868aee042..ddaedd922e 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java @@ -58,7 +58,6 @@ import junit.framework.TestCase; import org.apache.poi.hssf.model.Sheet; import org.apache.poi.hssf.record.VCenterRecord; import org.apache.poi.hssf.record.WSBoolRecord; -import org.apache.poi.hssf.dev.BiffViewer; import java.io.File; import java.io.FileInputStream; @@ -190,7 +189,14 @@ public class TestHSSFSheet tempFile.delete(); assertNotNull(row); assertEquals(2, row.getPhysicalNumberOfCells()); + } - + public void testRemoveRow() + { + HSSFWorkbook workbook = new HSSFWorkbook(); + HSSFSheet sheet = workbook.createSheet("Test boolean"); + HSSFRow row = sheet.createRow((short) 2); + sheet.removeRow(row); } + } diff --git a/src/testcases/org/apache/poi/util/TestLittleEndian.java b/src/testcases/org/apache/poi/util/TestLittleEndian.java index 1f2780d897..f9f2df2382 100644 --- a/src/testcases/org/apache/poi/util/TestLittleEndian.java +++ b/src/testcases/org/apache/poi/util/TestLittleEndian.java @@ -437,6 +437,12 @@ public class TestLittleEndian return result; } + public void testUnsignedShort() + throws Exception + { + assertEquals(0xffff, LittleEndian.getUShort(new byte[] { (byte)0xff, (byte)0xff }, 0)); + } + /** * main method to run the unit tests * diff --git a/src/testcases/org/apache/poi/util/TestPOILogFactory.java b/src/testcases/org/apache/poi/util/TestPOILogFactory.java index 82aef5d5c1..2e27e6a9ba 100644 --- a/src/testcases/org/apache/poi/util/TestPOILogFactory.java +++ b/src/testcases/org/apache/poi/util/TestPOILogFactory.java @@ -1,4 +1,3 @@ - /* ==================================================================== * The Apache Software License, Version 1.1 * @@ -55,11 +54,9 @@ package org.apache.poi.util; -import org.apache.log4j.Category; - -import junit.framework.*; +import junit.framework.TestCase; -import java.io.*; +import java.io.IOException; /** * @author Marc Johnson (mjohnson at apache dot org) @@ -68,7 +65,7 @@ import java.io.*; */ public class TestPOILogFactory - extends TestCase + extends TestCase { /** * Creates new TestPOILogFactory @@ -76,9 +73,9 @@ public class TestPOILogFactory * @param name */ - public TestPOILogFactory(String name) + public TestPOILogFactory( String name ) { - super(name); + super( name ); } /** @@ -88,26 +85,26 @@ public class TestPOILogFactory */ public void testLog() - throws IOException + throws IOException { //NKB Testing only that logging classes use gives no exception // Since logging can be disabled, no checking of logging // output is done. - - POILogger l1 = POILogFactory.getLogger("org.apache.poi.hssf.test"); - POILogger l2 = POILogFactory.getLogger("org.apache.poi.hdf.test"); - l1.log(POILogger.FATAL, "testing cat org.apache.poi.hssf.*:FATAL"); - l1.log(POILogger.ERROR, "testing cat org.apache.poi.hssf.*:ERROR"); - l1.log(POILogger.WARN, "testing cat org.apache.poi.hssf.*:WARN"); - l1.log(POILogger.INFO, "testing cat org.apache.poi.hssf.*:INFO"); - l1.log(POILogger.DEBUG, "testing cat org.apache.poi.hssf.*:DEBUG"); + POILogger l1 = POILogFactory.getLogger( "org.apache.poi.hssf.test" ); + POILogger l2 = POILogFactory.getLogger( "org.apache.poi.hdf.test" ); + + l1.log( POILogger.FATAL, "testing cat org.apache.poi.hssf.*:FATAL" ); + l1.log( POILogger.ERROR, "testing cat org.apache.poi.hssf.*:ERROR" ); + l1.log( POILogger.WARN, "testing cat org.apache.poi.hssf.*:WARN" ); + l1.log( POILogger.INFO, "testing cat org.apache.poi.hssf.*:INFO" ); + l1.log( POILogger.DEBUG, "testing cat org.apache.poi.hssf.*:DEBUG" ); - l2.log(POILogger.FATAL, "testing cat org.apache.poi.hdf.*:FATAL"); - l2.log(POILogger.ERROR, "testing cat org.apache.poi.hdf.*:ERROR"); - l2.log(POILogger.WARN, "testing cat org.apache.poi.hdf.*:WARN"); - l2.log(POILogger.INFO, "testing cat org.apache.poi.hdf.*:INFO"); - l2.log(POILogger.DEBUG, "testing cat org.apache.poi.hdf.*:DEBUG"); + l2.log( POILogger.FATAL, "testing cat org.apache.poi.hdf.*:FATAL" ); + l2.log( POILogger.ERROR, "testing cat org.apache.poi.hdf.*:ERROR" ); + l2.log( POILogger.WARN, "testing cat org.apache.poi.hdf.*:WARN" ); + l2.log( POILogger.INFO, "testing cat org.apache.poi.hdf.*:INFO" ); + l2.log( POILogger.DEBUG, "testing cat org.apache.poi.hdf.*:DEBUG" ); } @@ -117,9 +114,9 @@ public class TestPOILogFactory * @param ignored_args */ - public static void main(String [] ignored_args) + public static void main( String[] ignored_args ) { - System.out.println("Testing basic util.POILogFactory functionality"); - junit.textui.TestRunner.run(TestPOILogFactory.class); + System.out.println( "Testing basic util.POILogFactory functionality" ); + junit.textui.TestRunner.run( TestPOILogFactory.class ); } } diff --git a/src/testcases/org/apache/poi/util/TestPOILogger.java b/src/testcases/org/apache/poi/util/TestPOILogger.java index 62b47a24a4..46248b5e21 100644 --- a/src/testcases/org/apache/poi/util/TestPOILogger.java +++ b/src/testcases/org/apache/poi/util/TestPOILogger.java @@ -1,4 +1,3 @@ - /* ==================================================================== * The Apache Software License, Version 1.1 * @@ -57,19 +56,16 @@ package org.apache.poi.util; import junit.framework.TestCase; -import java.io.File; -import java.io.FileInputStream; - /** * Tests the log class. * * @author Glen Stampoultzis (glens at apache.org) * @author Marc Johnson (mjohnson at apache dot org) - * @author Nicola Ken Barozzi (nicolaken at apache.org) + * @author Nicola Ken Barozzi (nicolaken at apache.org) */ public class TestPOILogger - extends TestCase + extends TestCase { /** * Constructor TestPOILogger @@ -79,23 +75,9 @@ public class TestPOILogger * */ - public TestPOILogger(String s) - { - super(s); - } - - /** - * Method setUp - * - * - * @exception Exception - * - */ - - protected void setUp() - throws Exception + public TestPOILogger( String s ) { - super.setUp(); + super( s ); } /** @@ -103,29 +85,20 @@ public class TestPOILogger * * @exception Exception */ - public void testVariousLogTypes() - throws Exception + throws Exception { //NKB Testing only that logging classes use gives no exception // Since logging can be disabled, no checking of logging // output is done. - - POILogger log = POILogFactory.getLogger("foo"); - log.log(POILogger.WARN, "Test = ", new Integer(1)); - log.logFormatted(POILogger.ERROR, "Test param 1 = %, param 2 = %", - "2", new Integer(3)); - log.logFormatted(POILogger.ERROR, "Test param 1 = %, param 2 = %", - new int[] - { - 4, 5 - }); - log.logFormatted(POILogger.ERROR, - "Test param 1 = %1.1, param 2 = %0.1", new double[] - { - 4, 5.23 - }); + POILogger log = POILogFactory.getLogger( "foo" ); + + log.log( POILogger.WARN, "Test = ", new Integer( 1 ) ); + log.logFormatted( POILogger.ERROR, "Test param 1 = %, param 2 = %", "2", new Integer( 3 ) ); + log.logFormatted( POILogger.ERROR, "Test param 1 = %, param 2 = %", new int[]{4, 5} ); + log.logFormatted( POILogger.ERROR, + "Test param 1 = %1.1, param 2 = %0.1", new double[]{4, 5.23} ); } } |