From 895297512d580247385d2563af76f43a000f6050 Mon Sep 17 00:00:00 2001 From: "Andrew C. Oliver" Date: Thu, 31 Jan 2002 02:22:28 +0000 Subject: [PATCH] Initial revision git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@352063 13f79535-47bb-0310-9956-ffa450edef68 --- .cvsignore | 13 + README.txt | 49 + build.bat | 23 + build.sh | 24 + build.xml | 1022 + legal/LICENSE | 53 + legal/LICENSE.apache | 50 + legal/LICENSE.resolver | 153 + lib/optional/avalon-excalibur-20020114.jar | Bin 0 -> 190018 bytes lib/optional/avalon-framework-20020114.jar | Bin 0 -> 47467 bytes .../cocoon-dev-20020129-nooptional.jar | Bin 0 -> 714767 bytes lib/optional/commons-collections-1.0.jar | Bin 0 -> 58798 bytes lib/optional/commons-httpclient-20011012.jar | Bin 0 -> 64553 bytes lib/optional/jakarta-regexp-1.2.jar | Bin 0 -> 29871 bytes lib/optional/jtidy-04aug2000r7-dev.jar | Bin 0 -> 161826 bytes lib/optional/logkit-20011212.jar | Bin 0 -> 71719 bytes lib/optional/resolver.jar | Bin 0 -> 72154 bytes lib/optional/xalan-2.2.0.jar | Bin 0 -> 923866 bytes lib/optional/xerces-1.4.4.jar | Bin 0 -> 1681323 bytes lib/optional/xml-apis.jar | Bin 0 -> 93717 bytes src/documentation/cocoon.xconf | 365 + src/documentation/images/.xvpics/header.gif | Bin 0 -> 1831 bytes src/documentation/images/add.jpg | Bin 0 -> 1406 bytes src/documentation/images/cocoon2-small.jpg | Bin 0 -> 1684 bytes src/documentation/images/fix.jpg | Bin 0 -> 932 bytes src/documentation/images/header.gif | Bin 0 -> 3165 bytes src/documentation/images/jakarta-logo.gif | Bin 0 -> 8006 bytes src/documentation/images/remove.jpg | Bin 0 -> 1658 bytes src/documentation/images/update.jpg | Bin 0 -> 1305 bytes src/documentation/linkalarm-readme.txt | 28 + src/documentation/sitemap.xmap | 211 + .../stylesheets/announcement.xsl | 11 + .../stylesheets/announcement2txt.xsl | 108 + src/documentation/stylesheets/book2menu.xsl | 33 + .../stylesheets/changes2document.xsl | 58 + src/documentation/stylesheets/copyover.xsl | 13 + .../stylesheets/docbook2body.xsl | 441 + src/documentation/stylesheets/docbook2fo.xsl | 742 + src/documentation/stylesheets/doclist.xsl | 15 + .../stylesheets/doclist2document.xsl | 85 + .../stylesheets/document2docbook.xsl | 177 + .../stylesheets/document2html.xsl | 389 + .../stylesheets/faq2document.xsl | 50 + src/documentation/stylesheets/filterlinks.xsl | 42 + .../stylesheets/printer_skin/book2menu.xsl | 62 + .../stylesheets/printer_skin/copyover.xsl | 13 + .../printer_skin/document2html.xsl | 277 + .../stylesheets/printer_skin/simple.css | 58 + .../stylesheets/printer_skin/site2xhtml.xsl | 122 + src/documentation/stylesheets/script-cli.js | 27 + src/documentation/stylesheets/script.js | 17 + src/documentation/stylesheets/site2xhtml.xsl | 67 + .../stylesheets/todo2document.xsl | 33 + src/documentation/xdocs/3rdparty.xml | 68 + src/documentation/xdocs/book.xml | 46 + src/documentation/xdocs/changes.xml | 24 + src/documentation/xdocs/contrib.xml | 275 + src/documentation/xdocs/dictionary.xml | 15 + src/documentation/xdocs/dtd/XMLSchema.dtd | 395 + .../xdocs/dtd/book-cocoon-v10.dtd | 70 + src/documentation/xdocs/dtd/changes-v10.dtd | 91 + src/documentation/xdocs/dtd/characters.ent | 290 + src/documentation/xdocs/dtd/datatypes.dtd | 195 + src/documentation/xdocs/dtd/document-v10.dtd | 555 + src/documentation/xdocs/dtd/faq-v10.dtd | 77 + .../xdocs/dtd/javadoc-v04draft.dtd | 254 + src/documentation/xdocs/dtd/sitemap-v02.dtd | 341 + .../xdocs/dtd/specification-v10.dtd | 85 + .../xdocs/dtd/svg-cocoon-v11.dtd | 82 + src/documentation/xdocs/dtd/svg10.dtd | 1538 ++ src/documentation/xdocs/dtd/todo-v10.dtd | 90 + src/documentation/xdocs/faq.xml | 28 + src/documentation/xdocs/hdf/book.xml | 14 + src/documentation/xdocs/hdf/index.xml | 25 + src/documentation/xdocs/historyandfuture.xml | 72 + src/documentation/xdocs/hssf/book.xml | 17 + src/documentation/xdocs/hssf/how-to.xml | 554 + src/documentation/xdocs/hssf/index.xml | 23 + src/documentation/xdocs/hssf/use-case.xml | 182 + src/documentation/xdocs/index.xml | 102 + src/documentation/xdocs/license.xml | 80 + src/documentation/xdocs/livesites.xml | 33 + src/documentation/xdocs/mail-archives.xml | 53 + src/documentation/xdocs/mail-lists.xml | 95 + src/documentation/xdocs/overview.xml | 62 + src/documentation/xdocs/patches.xml | 26 + src/documentation/xdocs/plan/POI10Vision.xml | 514 + src/documentation/xdocs/plan/book.xml | 17 + src/documentation/xdocs/plan/index.xml | 58 + src/documentation/xdocs/plan/release.xml | 63 + src/documentation/xdocs/poifs/book.xml | 14 + .../xdocs/poifs/html/POIFSDesignDocument.html | 1279 ++ .../xdocs/poifs/html/POIFSFormat.html | 837 + .../xdocs/poifs/html/POIFSUseCases.html | 449 + .../xdocs/poifs/html/how-to.html | 190 + src/documentation/xdocs/poifs/index.xml | 22 + src/documentation/xdocs/todo.xml | 29 + src/documentation/xdocs/utils/book.xml | 14 + src/documentation/xdocs/utils/index.xml | 20 + src/documentation/xdocs/who.xml | 57 + src/java/Manifest.mf | 1 + src/java/org/apache/poi/hdf/hdf.xml | 295 + src/java/org/apache/poi/hssf/HSSFLog.java | 96 + .../org/apache/poi/hssf/dev/BiffViewer.java | 662 + .../apache/poi/hssf/dev/BiffViewer.java.rep | 174 + .../org/apache/poi/hssf/dev/EFBiffViewer.java | 132 + src/java/org/apache/poi/hssf/dev/EFHSSF.java | 227 + .../org/apache/poi/hssf/dev/EFHSSF.java.rep | 116 + .../apache/poi/hssf/dev/FormulaViewer.java | 218 + src/java/org/apache/poi/hssf/dev/HSSF.java | 409 + .../poi/hssf/eventmodel/HSSFEventFactory.java | 186 + .../poi/hssf/eventmodel/HSSFListener.java | 78 + .../poi/hssf/eventmodel/HSSFRequest.java | 161 + src/java/org/apache/poi/hssf/model/Sheet.java | 1922 ++ .../org/apache/poi/hssf/model/Workbook.java | 1673 ++ .../org/apache/poi/hssf/model/package.html | 20 + src/java/org/apache/poi/hssf/package.uml | 5 + .../org/apache/poi/hssf/record/BOFRecord.java | 361 + .../apache/poi/hssf/record/BackupRecord.java | 170 + .../apache/poi/hssf/record/BeginRecord.java | 143 + .../apache/poi/hssf/record/BlankRecord.java | 347 + .../poi/hssf/record/BookBoolRecord.java | 170 + .../apache/poi/hssf/record/BoolErrRecord.java | 411 + .../poi/hssf/record/BoundSheetRecord.java | 286 + .../poi/hssf/record/CalcCountRecord.java | 172 + .../poi/hssf/record/CalcModeRecord.java | 197 + .../hssf/record/CellValueRecordInterface.java | 139 + .../poi/hssf/record/ChartFormatRecord.java | 222 + .../apache/poi/hssf/record/ChartRecord.java | 205 + .../poi/hssf/record/CodepageRecord.java | 179 + .../poi/hssf/record/ColumnInfoRecord.java | 358 + .../poi/hssf/record/ContinueRecord.java | 269 + .../apache/poi/hssf/record/CountryRecord.java | 200 + .../apache/poi/hssf/record/DBCellRecord.java | 241 + .../org/apache/poi/hssf/record/DSFRecord.java | 168 + .../poi/hssf/record/DateWindow1904Record.java | 169 + .../hssf/record/DefaultColWidthRecord.java | 168 + .../hssf/record/DefaultRowHeightRecord.java | 193 + .../apache/poi/hssf/record/DeltaRecord.java | 170 + .../poi/hssf/record/DimensionsRecord.java | 247 + .../org/apache/poi/hssf/record/EOFRecord.java | 144 + .../org/apache/poi/hssf/record/EndRecord.java | 143 + .../poi/hssf/record/ExtSSTInfoSubRecord.java | 164 + .../apache/poi/hssf/record/ExtSSTRecord.java | 214 + .../poi/hssf/record/ExtendedFormatRecord.java | 1826 ++ .../poi/hssf/record/FnGroupCountRecord.java | 176 + .../apache/poi/hssf/record/FontRecord.java | 594 + .../apache/poi/hssf/record/FooterRecord.java | 220 + .../apache/poi/hssf/record/FormatRecord.java | 240 + .../apache/poi/hssf/record/FormulaRecord.java | 482 + .../apache/poi/hssf/record/GridsetRecord.java | 179 + .../apache/poi/hssf/record/GutsRecord.java | 249 + .../apache/poi/hssf/record/HCenterRecord.java | 173 + .../apache/poi/hssf/record/HeaderRecord.java | 221 + .../apache/poi/hssf/record/HideObjRecord.java | 178 + .../apache/poi/hssf/record/IndexRecord.java | 228 + .../poi/hssf/record/InterfaceEndRecord.java | 143 + .../poi/hssf/record/InterfaceHdrRecord.java | 177 + .../poi/hssf/record/IterationRecord.java | 177 + .../apache/poi/hssf/record/LabelRecord.java | 313 + .../poi/hssf/record/LabelSSTRecord.java | 329 + .../org/apache/poi/hssf/record/MMSRecord.java | 193 + .../poi/hssf/record/MergeCellsRecord.java | 319 + .../poi/hssf/record/MulBlankRecord.java | 250 + .../apache/poi/hssf/record/MulRKRecord.java | 299 + .../apache/poi/hssf/record/NumberRecord.java | 354 + .../poi/hssf/record/PasswordRecord.java | 169 + .../poi/hssf/record/PasswordRev4Record.java | 170 + .../poi/hssf/record/PrecisionRecord.java | 177 + .../poi/hssf/record/PrintGridlinesRecord.java | 176 + .../poi/hssf/record/PrintHeadersRecord.java | 174 + .../poi/hssf/record/PrintSetupRecord.java | 426 + .../apache/poi/hssf/record/ProtectRecord.java | 176 + .../poi/hssf/record/ProtectionRev4Record.java | 176 + .../org/apache/poi/hssf/record/RKRecord.java | 377 + .../org/apache/poi/hssf/record/Record.java | 244 + .../apache/poi/hssf/record/RecordFactory.java | 329 + .../hssf/record/RecordFormatException.java | 70 + .../apache/poi/hssf/record/RefModeRecord.java | 173 + .../poi/hssf/record/RefreshAllRecord.java | 175 + .../org/apache/poi/hssf/record/RowRecord.java | 510 + .../org/apache/poi/hssf/record/SSTRecord.java | 1221 + .../poi/hssf/record/SaveRecalcRecord.java | 167 + .../poi/hssf/record/SelectionRecord.java | 277 + .../apache/poi/hssf/record/SeriesRecord.java | 242 + .../apache/poi/hssf/record/StyleRecord.java | 399 + .../apache/poi/hssf/record/TabIdRecord.java | 188 + .../apache/poi/hssf/record/UnicodeString.java | 366 + .../apache/poi/hssf/record/UnknownRecord.java | 177 + .../poi/hssf/record/UseSelFSRecord.java | 176 + .../apache/poi/hssf/record/VCenterRecord.java | 173 + .../apache/poi/hssf/record/WSBoolRecord.java | 418 + .../poi/hssf/record/WindowOneRecord.java | 504 + .../poi/hssf/record/WindowProtectRecord.java | 175 + .../poi/hssf/record/WindowTwoRecord.java | 618 + .../poi/hssf/record/WriteAccessRecord.java | 191 + .../aggregates/RowRecordsAggregate.java | 219 + .../aggregates/ValueRecordsAggregate.java | 276 + .../poi/hssf/record/formula/AddPtg.java | 121 + .../poi/hssf/record/formula/AreaPtg.java | 244 + .../poi/hssf/record/formula/AttrPtg.java | 208 + .../poi/hssf/record/formula/DividePtg.java | 121 + .../poi/hssf/record/formula/ExpPtg.java | 99 + .../poi/hssf/record/formula/FormulaUtil.java | 318 + .../poi/hssf/record/formula/IntPtg.java | 114 + .../poi/hssf/record/formula/MemErrPtg.java | 123 + .../poi/hssf/record/formula/MultiplyPtg.java | 121 + .../poi/hssf/record/formula/NamePtg.java | 108 + .../poi/hssf/record/formula/OperationPtg.java | 79 + .../hssf/record/formula/ParenthesisPtg.java | 103 + .../poi/hssf/record/formula/PowerPtg.java | 121 + .../apache/poi/hssf/record/formula/Ptg.java | 167 + .../poi/hssf/record/formula/SubtractPtg.java | 121 + .../poi/hssf/record/formula/UnknownPtg.java | 98 + .../record/formula/ValueReferencePtg.java | 161 + .../formula/ValueVariableFunctionPtg.java | 130 + .../apache/poi/hssf/usermodel/HSSFCell.java | 861 + .../poi/hssf/usermodel/HSSFCellStyle.java | 815 + .../hssf/usermodel/HSSFColorConstants.java | 114 + .../poi/hssf/usermodel/HSSFDataFormat.java | 241 + .../poi/hssf/usermodel/HSSFDateUtil.java | 210 + .../hssf/usermodel/HSSFErrorConstants.java | 77 + .../apache/poi/hssf/usermodel/HSSFFont.java | 390 + .../apache/poi/hssf/usermodel/HSSFRow.java | 548 + .../apache/poi/hssf/usermodel/HSSFSheet.java | 758 + .../poi/hssf/usermodel/HSSFWorkbook.java | 534 + .../org/apache/poi/hssf/util/HSSFColor.java | 1538 ++ src/java/org/apache/poi/hssf/util/Region.java | 257 + .../poi/poifs/common/PoiFSConstants.java | 71 + .../apache/poi/poifs/dev/POIFSViewEngine.java | 165 + .../apache/poi/poifs/dev/POIFSViewable.java | 115 + .../org/apache/poi/poifs/dev/POIFSViewer.java | 130 + .../poifs/eventfilesystem/POIFSReader.java | 364 + .../eventfilesystem/POIFSReaderEvent.java | 117 + .../eventfilesystem/POIFSReaderListener.java | 77 + .../eventfilesystem/POIFSReaderRegistry.java | 221 + .../poi/poifs/filesystem/BATManaged.java | 85 + .../poi/poifs/filesystem/DirectoryEntry.java | 164 + .../poi/poifs/filesystem/DirectoryNode.java | 446 + .../poifs/filesystem/DocumentDescriptor.java | 153 + .../poi/poifs/filesystem/DocumentEntry.java | 77 + .../poifs/filesystem/DocumentInputStream.java | 487 + .../poi/poifs/filesystem/DocumentNode.java | 204 + .../filesystem/DocumentOutputStream.java | 214 + .../apache/poi/poifs/filesystem/Entry.java | 133 + .../poi/poifs/filesystem/EntryNode.java | 231 + .../poi/poifs/filesystem/POIFSDocument.java | 669 + .../poifs/filesystem/POIFSDocumentPath.java | 314 + .../poi/poifs/filesystem/POIFSFileSystem.java | 519 + .../poifs/filesystem/POIFSWriterEvent.java | 128 + .../poifs/filesystem/POIFSWriterListener.java | 77 + .../org/apache/poi/poifs/property/Child.java | 102 + .../poi/poifs/property/DirectoryProperty.java | 310 + .../poi/poifs/property/DocumentProperty.java | 162 + .../org/apache/poi/poifs/property/Parent.java | 114 + .../apache/poi/poifs/property/Property.java | 576 + .../poi/poifs/property/PropertyConstants.java | 75 + .../poi/poifs/property/PropertyFactory.java | 139 + .../poi/poifs/property/PropertyTable.java | 281 + .../poi/poifs/property/RootProperty.java | 114 + .../apache/poi/poifs/storage/BATBlock.java | 274 + .../apache/poi/poifs/storage/BigBlock.java | 127 + .../storage/BlockAllocationTableReader.java | 322 + .../storage/BlockAllocationTableWriter.java | 241 + .../apache/poi/poifs/storage/BlockList.java | 118 + .../poi/poifs/storage/BlockListImpl.java | 189 + .../poi/poifs/storage/BlockWritable.java | 83 + .../poi/poifs/storage/DocumentBlock.java | 260 + .../poifs/storage/HeaderBlockConstants.java | 87 + .../poi/poifs/storage/HeaderBlockReader.java | 199 + .../poi/poifs/storage/HeaderBlockWriter.java | 240 + .../poi/poifs/storage/ListManagedBlock.java | 81 + .../poi/poifs/storage/PropertyBlock.java | 169 + .../poi/poifs/storage/RawDataBlock.java | 145 + .../poi/poifs/storage/RawDataBlockList.java | 99 + .../poifs/storage/SmallBlockTableReader.java | 101 + .../poifs/storage/SmallBlockTableWriter.java | 178 + .../poi/poifs/storage/SmallDocumentBlock.java | 322 + .../poifs/storage/SmallDocumentBlockList.java | 82 + src/java/org/apache/poi/util/BinaryTree.java | 2231 ++ src/java/org/apache/poi/util/BitField.java | 362 + src/java/org/apache/poi/util/ByteField.java | 257 + src/java/org/apache/poi/util/FixedField.java | 120 + src/java/org/apache/poi/util/HexDump.java | 184 + src/java/org/apache/poi/util/IntList.java | 678 + .../org/apache/poi/util/IntegerField.java | 256 + .../org/apache/poi/util/LittleEndian.java | 501 + .../apache/poi/util/LittleEndianConsts.java | 75 + src/java/org/apache/poi/util/LongField.java | 253 + .../org/apache/poi/util/POILogFactory.java | 143 + src/java/org/apache/poi/util/POILogger.java | 731 + src/java/org/apache/poi/util/ShortField.java | 253 + src/java/org/apache/poi/util/ShortList.java | 678 + src/java/org/apache/poi/util/StringUtil.java | 261 + src/models/BlockClassDiagram.pgml | 603 + src/models/HSSFOperationalUseCases.pgml | 712 + src/models/HSSFSerializerClassDiagram.pgml | 651 + src/models/HSSFSerializerUseCases.pgml | 1031 + src/models/HSSFUseCases.pgml | 707 + src/models/POIFSAddDocument.pgml | 1024 + src/models/POIFSClassDiagram.pgml | 1107 + src/models/POIFSInitialization.pgml | 572 + src/models/POIFSLifeCycle.pgml | 392 + src/models/POIFSPropertyTablePreWrite.pgml | 796 + src/models/POIFSRootPropertyPreWrite.pgml | 398 + src/models/POIFSWriteFilesystem.pgml | 1240 + src/models/POIUseCases.pgml | 988 + src/models/PropertyTableClassDiagram.pgml | 800 + src/models/analysismain.pgml | 192 + src/models/poi.argo | 109 + src/models/poi.xmi | 19114 ++++++++++++++++ src/models/poifsAnalysisClasses.pgml | 1225 + src/models/projectmain.pgml | 138 + ...readFileFromFilesystemSequenceDiagram.pgml | 1278 ++ ...eadFileSystemDirectorySequenceDiagram.pgml | 410 + src/models/readFilesystemSequenceDiagram.pgml | 1364 ++ src/models/utilClasses.pgml | 1105 + .../writeFilesystemSequenceDiagram.pgml | 1874 ++ .../entities/CatalogManager.properties | 50 + src/resources/entities/ISOdia.pen | 34 + src/resources/entities/ISOgrk1.pen | 74 + src/resources/entities/ISOlat1.pen | 79 + src/resources/entities/ISOnum.pen | 109 + src/resources/entities/ISOpub.pen | 110 + src/resources/entities/ISOtech.pen | 85 + src/resources/entities/README | 5 + src/resources/entities/XMLSchema.dtd | 395 + src/resources/entities/book-cocoon-v10.dtd | 70 + src/resources/entities/catalog | 67 + .../catalog-demo/catalog-demo-v10.dtd | 14 + .../entities/catalog-demo/override.xml | 4 + .../entities/catalog-demo/testpub.xml | 7 + .../entities/catalog-demo/testsys.xml | 5 + src/resources/entities/changes-v10.dtd | 91 + src/resources/entities/characters.ent | 290 + src/resources/entities/datatypes.dtd | 195 + src/resources/entities/document-v10.dtd | 555 + src/resources/entities/faq-v10.dtd | 77 + src/resources/entities/javadoc-v04draft.dtd | 254 + src/resources/entities/sitemap-v02.dtd | 341 + src/resources/entities/specification-v10.dtd | 85 + src/resources/entities/svg-cocoon-v11.dtd | 82 + src/resources/entities/svg10.dtd | 1538 ++ src/resources/entities/todo-v10.dtd | 90 + src/resources/javadoc.css | 32 + src/scratchpad/src/Manifest.mf | 1 + .../org/apache/poi/hssf/data/BigSSTRecord | 516 + .../org/apache/poi/hssf/data/BigSSTRecord2 | 515 + .../org/apache/poi/hssf/data/BigSSTRecord2CR1 | 514 + .../org/apache/poi/hssf/data/BigSSTRecord2CR2 | 515 + .../org/apache/poi/hssf/data/BigSSTRecord2CR3 | 515 + .../org/apache/poi/hssf/data/BigSSTRecord2CR4 | 515 + .../org/apache/poi/hssf/data/BigSSTRecord2CR5 | 515 + .../org/apache/poi/hssf/data/BigSSTRecord2CR6 | 515 + .../org/apache/poi/hssf/data/BigSSTRecord2CR7 | 105 + .../org/apache/poi/hssf/data/BigSSTRecordCR | 225 + .../org/apache/poi/hssf/data/Employee.xls | Bin 0 -> 13824 bytes .../org/apache/poi/hssf/data/Simple.xls | Bin 0 -> 13824 bytes .../org/apache/poi/hssf/data/SimpleChart.xls | Bin 0 -> 14336 bytes .../poi/hssf/data/SimpleWithFormula.xls | Bin 0 -> 13824 bytes .../apache/poi/hssf/data/SimpleWithSkip.xls | Bin 0 -> 13824 bytes .../poi/hssf/data/SimpleWithStyling.xls | Bin 0 -> 13824 bytes src/testcases/org/apache/poi/hssf/data/rk.xls | Bin 0 -> 13824 bytes .../org/apache/poi/hssf/data/test_properties1 | 11 + .../poi/hssf/record/TestRecordFactory.java | 167 + .../apache/poi/hssf/record/TestSSTRecord.java | 574 + .../poi/hssf/usermodel/TestCellStyle.java | 209 + .../poi/hssf/usermodel/TestHSSFDateUtil.java | 99 + .../poi/hssf/usermodel/TestHSSFSheet.java | 170 + .../hssf/usermodel/TestReadWriteChart.java | 116 + .../poi/hssf/usermodel/TestWorkbook.java | 643 + .../poi/poifs/eventfilesystem/Listener.java | 80 + .../TestPOIFSReaderRegistry.java | 224 + .../poi/poifs/filesystem/ReaderWriter.java | 224 + .../poifs/filesystem/TestDirectoryNode.java | 289 + .../poi/poifs/filesystem/TestDocument.java | 319 + .../filesystem/TestDocumentDescriptor.java | 248 + .../filesystem/TestDocumentInputStream.java | 472 + .../poifs/filesystem/TestDocumentNode.java | 142 + .../filesystem/TestDocumentOutputStream.java | 257 + .../filesystem/TestPOIFSDocumentPath.java | 370 + .../poi/poifs/property/LocalProperty.java | 94 + .../poifs/property/TestDirectoryProperty.java | 437 + .../poifs/property/TestDocumentProperty.java | 358 + .../poifs/property/TestPropertyFactory.java | 2275 ++ .../poi/poifs/property/TestPropertyTable.java | 2684 +++ .../poi/poifs/property/TestRootProperty.java | 259 + .../poi/poifs/storage/LocalProperty.java | 93 + .../poifs/storage/LocalRawDataBlockList.java | 243 + .../poi/poifs/storage/TestBATBlock.java | 320 + .../TestBlockAllocationTableReader.java | 1402 ++ .../TestBlockAllocationTableWriter.java | 231 + .../poi/poifs/storage/TestBlockListImpl.java | 362 + .../poi/poifs/storage/TestDocumentBlock.java | 216 + .../poifs/storage/TestHeaderBlockReader.java | 283 + .../poifs/storage/TestHeaderBlockWriter.java | 1061 + .../poi/poifs/storage/TestPropertyBlock.java | 275 + .../poi/poifs/storage/TestRawDataBlock.java | 176 + .../poifs/storage/TestRawDataBlockList.java | 152 + .../storage/TestSmallBlockTableReader.java | 2181 ++ .../storage/TestSmallBlockTableWriter.java | 165 + .../poifs/storage/TestSmallDocumentBlock.java | 346 + .../storage/TestSmallDocumentBlockList.java | 137 + .../org/apache/poi/util/LocalTestNode.java | 164 + .../org/apache/poi/util/TestBinaryTree.java | 2815 +++ .../org/apache/poi/util/TestBitField.java | 326 + .../org/apache/poi/util/TestByteField.java | 251 + .../org/apache/poi/util/TestHexDump.java | 341 + .../org/apache/poi/util/TestIntList.java | 723 + .../org/apache/poi/util/TestIntegerField.java | 279 + .../org/apache/poi/util/TestLittleEndian.java | 445 + .../org/apache/poi/util/TestLongField.java | 307 + .../apache/poi/util/TestPOILogFactory.java | 141 + .../org/apache/poi/util/TestPOILogger.java | 181 + .../org/apache/poi/util/TestShortField.java | 266 + .../org/apache/poi/util/TestShortList.java | 724 + .../org/apache/poi/util/TestStringUtil.java | 315 + .../org/apache/poi/util/data/test_properties1 | 11 + .../org/apache/poi/util/data/test_properties2 | 11 + .../org/apache/poi/util/data/test_properties3 | 11 + tools/.cvsignore | 1 + tools/bin/ant | 107 + tools/bin/ant.bat | 97 + tools/bin/antRun | 9 + tools/bin/antRun.bat | 20 + tools/bin/fix-packages.py | 216 + tools/bin/lcp.bat | 2 + tools/bin/runant.pl | 131 + tools/lib/.cvsignore | 3 + tools/lib/ant-1.4.1-optional.jar | Bin 0 -> 468566 bytes tools/lib/ant-1.4.1.jar | Bin 0 -> 417110 bytes tools/lib/jtidy-04aug2000r7-dev.jar | Bin 0 -> 161826 bytes tools/lib/junit.jar | Bin 0 -> 117522 bytes tools/lib/xalan-2.2.0.jar | Bin 0 -> 923866 bytes tools/resources/Release-Checklist.txt | 18 + tools/resources/jindent/poi.jin | 319 + tools/resources/stylesheets/html2xml.xsl | 153 + tools/src/ClassAvailable.java | 246 + tools/src/JTidyTask.java | 272 + tools/src/SitemapTool.java | 363 + tools/src/UserInput.java | 151 + tools/src/XConfTool.java | 238 + tools/src/announcement2header.xsl | 78 + tools/src/announcement2readme.xsl | 89 + tools/src/announcement2site.xsl | 92 + tools/src/announcement2txt.xsl | 174 + tools/src/bugzilla2patchqueue.xsl | 36 + tools/src/changelog.xsl | 95 + tools/src/patchqueue2text4dev.xsl | 70 + tools/src/patchqueue2xdocs.xsl | 109 + 450 files changed, 145122 insertions(+) create mode 100644 .cvsignore create mode 100755 README.txt create mode 100755 build.bat create mode 100755 build.sh create mode 100644 build.xml create mode 100755 legal/LICENSE create mode 100755 legal/LICENSE.apache create mode 100755 legal/LICENSE.resolver create mode 100644 lib/optional/avalon-excalibur-20020114.jar create mode 100644 lib/optional/avalon-framework-20020114.jar create mode 100644 lib/optional/cocoon-dev-20020129-nooptional.jar create mode 100644 lib/optional/commons-collections-1.0.jar create mode 100644 lib/optional/commons-httpclient-20011012.jar create mode 100644 lib/optional/jakarta-regexp-1.2.jar create mode 100644 lib/optional/jtidy-04aug2000r7-dev.jar create mode 100644 lib/optional/logkit-20011212.jar create mode 100755 lib/optional/resolver.jar create mode 100644 lib/optional/xalan-2.2.0.jar create mode 100644 lib/optional/xerces-1.4.4.jar create mode 100644 lib/optional/xml-apis.jar create mode 100755 src/documentation/cocoon.xconf create mode 100644 src/documentation/images/.xvpics/header.gif create mode 100755 src/documentation/images/add.jpg create mode 100755 src/documentation/images/cocoon2-small.jpg create mode 100755 src/documentation/images/fix.jpg create mode 100755 src/documentation/images/header.gif create mode 100755 src/documentation/images/jakarta-logo.gif create mode 100755 src/documentation/images/remove.jpg create mode 100755 src/documentation/images/update.jpg create mode 100755 src/documentation/linkalarm-readme.txt create mode 100755 src/documentation/sitemap.xmap create mode 100755 src/documentation/stylesheets/announcement.xsl create mode 100755 src/documentation/stylesheets/announcement2txt.xsl create mode 100755 src/documentation/stylesheets/book2menu.xsl create mode 100755 src/documentation/stylesheets/changes2document.xsl create mode 100755 src/documentation/stylesheets/copyover.xsl create mode 100755 src/documentation/stylesheets/docbook2body.xsl create mode 100755 src/documentation/stylesheets/docbook2fo.xsl create mode 100755 src/documentation/stylesheets/doclist.xsl create mode 100755 src/documentation/stylesheets/doclist2document.xsl create mode 100755 src/documentation/stylesheets/document2docbook.xsl create mode 100755 src/documentation/stylesheets/document2html.xsl create mode 100755 src/documentation/stylesheets/faq2document.xsl create mode 100755 src/documentation/stylesheets/filterlinks.xsl create mode 100755 src/documentation/stylesheets/printer_skin/book2menu.xsl create mode 100755 src/documentation/stylesheets/printer_skin/copyover.xsl create mode 100755 src/documentation/stylesheets/printer_skin/document2html.xsl create mode 100755 src/documentation/stylesheets/printer_skin/simple.css create mode 100755 src/documentation/stylesheets/printer_skin/site2xhtml.xsl create mode 100755 src/documentation/stylesheets/script-cli.js create mode 100755 src/documentation/stylesheets/script.js create mode 100755 src/documentation/stylesheets/site2xhtml.xsl create mode 100755 src/documentation/stylesheets/todo2document.xsl create mode 100644 src/documentation/xdocs/3rdparty.xml create mode 100644 src/documentation/xdocs/book.xml create mode 100644 src/documentation/xdocs/changes.xml create mode 100644 src/documentation/xdocs/contrib.xml create mode 100644 src/documentation/xdocs/dictionary.xml create mode 100755 src/documentation/xdocs/dtd/XMLSchema.dtd create mode 100755 src/documentation/xdocs/dtd/book-cocoon-v10.dtd create mode 100755 src/documentation/xdocs/dtd/changes-v10.dtd create mode 100755 src/documentation/xdocs/dtd/characters.ent create mode 100755 src/documentation/xdocs/dtd/datatypes.dtd create mode 100755 src/documentation/xdocs/dtd/document-v10.dtd create mode 100755 src/documentation/xdocs/dtd/faq-v10.dtd create mode 100755 src/documentation/xdocs/dtd/javadoc-v04draft.dtd create mode 100755 src/documentation/xdocs/dtd/sitemap-v02.dtd create mode 100755 src/documentation/xdocs/dtd/specification-v10.dtd create mode 100755 src/documentation/xdocs/dtd/svg-cocoon-v11.dtd create mode 100755 src/documentation/xdocs/dtd/svg10.dtd create mode 100755 src/documentation/xdocs/dtd/todo-v10.dtd create mode 100644 src/documentation/xdocs/faq.xml create mode 100644 src/documentation/xdocs/hdf/book.xml create mode 100644 src/documentation/xdocs/hdf/index.xml create mode 100755 src/documentation/xdocs/historyandfuture.xml create mode 100644 src/documentation/xdocs/hssf/book.xml create mode 100644 src/documentation/xdocs/hssf/how-to.xml create mode 100644 src/documentation/xdocs/hssf/index.xml create mode 100644 src/documentation/xdocs/hssf/use-case.xml create mode 100644 src/documentation/xdocs/index.xml create mode 100644 src/documentation/xdocs/license.xml create mode 100644 src/documentation/xdocs/livesites.xml create mode 100644 src/documentation/xdocs/mail-archives.xml create mode 100644 src/documentation/xdocs/mail-lists.xml create mode 100644 src/documentation/xdocs/overview.xml create mode 100644 src/documentation/xdocs/patches.xml create mode 100644 src/documentation/xdocs/plan/POI10Vision.xml create mode 100644 src/documentation/xdocs/plan/book.xml create mode 100644 src/documentation/xdocs/plan/index.xml create mode 100644 src/documentation/xdocs/plan/release.xml create mode 100644 src/documentation/xdocs/poifs/book.xml create mode 100755 src/documentation/xdocs/poifs/html/POIFSDesignDocument.html create mode 100755 src/documentation/xdocs/poifs/html/POIFSFormat.html create mode 100755 src/documentation/xdocs/poifs/html/POIFSUseCases.html create mode 100755 src/documentation/xdocs/poifs/html/how-to.html create mode 100644 src/documentation/xdocs/poifs/index.xml create mode 100644 src/documentation/xdocs/todo.xml create mode 100644 src/documentation/xdocs/utils/book.xml create mode 100644 src/documentation/xdocs/utils/index.xml create mode 100644 src/documentation/xdocs/who.xml create mode 100755 src/java/Manifest.mf create mode 100644 src/java/org/apache/poi/hdf/hdf.xml create mode 100644 src/java/org/apache/poi/hssf/HSSFLog.java create mode 100644 src/java/org/apache/poi/hssf/dev/BiffViewer.java create mode 100755 src/java/org/apache/poi/hssf/dev/BiffViewer.java.rep create mode 100644 src/java/org/apache/poi/hssf/dev/EFBiffViewer.java create mode 100644 src/java/org/apache/poi/hssf/dev/EFHSSF.java create mode 100755 src/java/org/apache/poi/hssf/dev/EFHSSF.java.rep create mode 100644 src/java/org/apache/poi/hssf/dev/FormulaViewer.java create mode 100644 src/java/org/apache/poi/hssf/dev/HSSF.java create mode 100644 src/java/org/apache/poi/hssf/eventmodel/HSSFEventFactory.java create mode 100644 src/java/org/apache/poi/hssf/eventmodel/HSSFListener.java create mode 100644 src/java/org/apache/poi/hssf/eventmodel/HSSFRequest.java create mode 100644 src/java/org/apache/poi/hssf/model/Sheet.java create mode 100644 src/java/org/apache/poi/hssf/model/Workbook.java create mode 100755 src/java/org/apache/poi/hssf/model/package.html create mode 100755 src/java/org/apache/poi/hssf/package.uml create mode 100644 src/java/org/apache/poi/hssf/record/BOFRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/BackupRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/BeginRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/BlankRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/BookBoolRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/BoolErrRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/BoundSheetRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/CalcCountRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/CalcModeRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/CellValueRecordInterface.java create mode 100644 src/java/org/apache/poi/hssf/record/ChartFormatRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/ChartRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/CodepageRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/ContinueRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/CountryRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/DBCellRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/DSFRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/DateWindow1904Record.java create mode 100644 src/java/org/apache/poi/hssf/record/DefaultColWidthRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/DefaultRowHeightRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/DeltaRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/DimensionsRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/EOFRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/EndRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/ExtSSTInfoSubRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/ExtSSTRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/ExtendedFormatRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/FnGroupCountRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/FontRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/FooterRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/FormatRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/FormulaRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/GridsetRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/GutsRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/HCenterRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/HeaderRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/HideObjRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/IndexRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/InterfaceEndRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/InterfaceHdrRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/IterationRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/LabelRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/LabelSSTRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/MMSRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/MergeCellsRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/MulBlankRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/MulRKRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/NumberRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/PasswordRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/PasswordRev4Record.java create mode 100644 src/java/org/apache/poi/hssf/record/PrecisionRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/PrintGridlinesRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/PrintHeadersRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/PrintSetupRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/ProtectRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/ProtectionRev4Record.java create mode 100644 src/java/org/apache/poi/hssf/record/RKRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/Record.java create mode 100644 src/java/org/apache/poi/hssf/record/RecordFactory.java create mode 100644 src/java/org/apache/poi/hssf/record/RecordFormatException.java create mode 100644 src/java/org/apache/poi/hssf/record/RefModeRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/RefreshAllRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/RowRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/SSTRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/SaveRecalcRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/SelectionRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/SeriesRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/StyleRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/TabIdRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/UnicodeString.java create mode 100644 src/java/org/apache/poi/hssf/record/UnknownRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/UseSelFSRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/VCenterRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/WSBoolRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/WindowOneRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/WindowProtectRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/WindowTwoRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/WriteAccessRecord.java create mode 100644 src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java create mode 100644 src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/AddPtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/AreaPtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/AttrPtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/DividePtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/ExpPtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/FormulaUtil.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/IntPtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/MemErrPtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/NamePtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/OperationPtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/PowerPtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/Ptg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/UnknownPtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/ValueReferencePtg.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFCell.java create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFColorConstants.java create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFDataFormat.java create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFErrorConstants.java create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFFont.java create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFRow.java create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java create mode 100644 src/java/org/apache/poi/hssf/util/HSSFColor.java create mode 100644 src/java/org/apache/poi/hssf/util/Region.java create mode 100644 src/java/org/apache/poi/poifs/common/PoiFSConstants.java create mode 100644 src/java/org/apache/poi/poifs/dev/POIFSViewEngine.java create mode 100644 src/java/org/apache/poi/poifs/dev/POIFSViewable.java create mode 100644 src/java/org/apache/poi/poifs/dev/POIFSViewer.java create mode 100644 src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java create mode 100644 src/java/org/apache/poi/poifs/eventfilesystem/POIFSReaderEvent.java create mode 100644 src/java/org/apache/poi/poifs/eventfilesystem/POIFSReaderListener.java create mode 100644 src/java/org/apache/poi/poifs/eventfilesystem/POIFSReaderRegistry.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/BATManaged.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/DirectoryEntry.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/DocumentDescriptor.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/DocumentEntry.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/DocumentNode.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/DocumentOutputStream.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/Entry.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/EntryNode.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/POIFSDocumentPath.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/POIFSWriterEvent.java create mode 100644 src/java/org/apache/poi/poifs/filesystem/POIFSWriterListener.java create mode 100644 src/java/org/apache/poi/poifs/property/Child.java create mode 100644 src/java/org/apache/poi/poifs/property/DirectoryProperty.java create mode 100644 src/java/org/apache/poi/poifs/property/DocumentProperty.java create mode 100644 src/java/org/apache/poi/poifs/property/Parent.java create mode 100644 src/java/org/apache/poi/poifs/property/Property.java create mode 100644 src/java/org/apache/poi/poifs/property/PropertyConstants.java create mode 100644 src/java/org/apache/poi/poifs/property/PropertyFactory.java create mode 100644 src/java/org/apache/poi/poifs/property/PropertyTable.java create mode 100644 src/java/org/apache/poi/poifs/property/RootProperty.java create mode 100644 src/java/org/apache/poi/poifs/storage/BATBlock.java create mode 100644 src/java/org/apache/poi/poifs/storage/BigBlock.java create mode 100644 src/java/org/apache/poi/poifs/storage/BlockAllocationTableReader.java create mode 100644 src/java/org/apache/poi/poifs/storage/BlockAllocationTableWriter.java create mode 100644 src/java/org/apache/poi/poifs/storage/BlockList.java create mode 100644 src/java/org/apache/poi/poifs/storage/BlockListImpl.java create mode 100644 src/java/org/apache/poi/poifs/storage/BlockWritable.java create mode 100644 src/java/org/apache/poi/poifs/storage/DocumentBlock.java create mode 100644 src/java/org/apache/poi/poifs/storage/HeaderBlockConstants.java create mode 100644 src/java/org/apache/poi/poifs/storage/HeaderBlockReader.java create mode 100644 src/java/org/apache/poi/poifs/storage/HeaderBlockWriter.java create mode 100644 src/java/org/apache/poi/poifs/storage/ListManagedBlock.java create mode 100644 src/java/org/apache/poi/poifs/storage/PropertyBlock.java create mode 100644 src/java/org/apache/poi/poifs/storage/RawDataBlock.java create mode 100644 src/java/org/apache/poi/poifs/storage/RawDataBlockList.java create mode 100644 src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java create mode 100644 src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java create mode 100644 src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java create mode 100644 src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java create mode 100644 src/java/org/apache/poi/util/BinaryTree.java create mode 100644 src/java/org/apache/poi/util/BitField.java create mode 100644 src/java/org/apache/poi/util/ByteField.java create mode 100644 src/java/org/apache/poi/util/FixedField.java create mode 100644 src/java/org/apache/poi/util/HexDump.java create mode 100644 src/java/org/apache/poi/util/IntList.java create mode 100644 src/java/org/apache/poi/util/IntegerField.java create mode 100644 src/java/org/apache/poi/util/LittleEndian.java create mode 100644 src/java/org/apache/poi/util/LittleEndianConsts.java create mode 100644 src/java/org/apache/poi/util/LongField.java create mode 100644 src/java/org/apache/poi/util/POILogFactory.java create mode 100644 src/java/org/apache/poi/util/POILogger.java create mode 100644 src/java/org/apache/poi/util/ShortField.java create mode 100644 src/java/org/apache/poi/util/ShortList.java create mode 100644 src/java/org/apache/poi/util/StringUtil.java create mode 100755 src/models/BlockClassDiagram.pgml create mode 100755 src/models/HSSFOperationalUseCases.pgml create mode 100755 src/models/HSSFSerializerClassDiagram.pgml create mode 100755 src/models/HSSFSerializerUseCases.pgml create mode 100755 src/models/HSSFUseCases.pgml create mode 100755 src/models/POIFSAddDocument.pgml create mode 100755 src/models/POIFSClassDiagram.pgml create mode 100755 src/models/POIFSInitialization.pgml create mode 100755 src/models/POIFSLifeCycle.pgml create mode 100755 src/models/POIFSPropertyTablePreWrite.pgml create mode 100755 src/models/POIFSRootPropertyPreWrite.pgml create mode 100755 src/models/POIFSWriteFilesystem.pgml create mode 100755 src/models/POIUseCases.pgml create mode 100755 src/models/PropertyTableClassDiagram.pgml create mode 100755 src/models/analysismain.pgml create mode 100755 src/models/poi.argo create mode 100755 src/models/poi.xmi create mode 100755 src/models/poifsAnalysisClasses.pgml create mode 100755 src/models/projectmain.pgml create mode 100755 src/models/readFileFromFilesystemSequenceDiagram.pgml create mode 100755 src/models/readFileSystemDirectorySequenceDiagram.pgml create mode 100755 src/models/readFilesystemSequenceDiagram.pgml create mode 100755 src/models/utilClasses.pgml create mode 100755 src/models/writeFilesystemSequenceDiagram.pgml create mode 100755 src/resources/entities/CatalogManager.properties create mode 100755 src/resources/entities/ISOdia.pen create mode 100755 src/resources/entities/ISOgrk1.pen create mode 100755 src/resources/entities/ISOlat1.pen create mode 100755 src/resources/entities/ISOnum.pen create mode 100755 src/resources/entities/ISOpub.pen create mode 100755 src/resources/entities/ISOtech.pen create mode 100755 src/resources/entities/README create mode 100755 src/resources/entities/XMLSchema.dtd create mode 100755 src/resources/entities/book-cocoon-v10.dtd create mode 100755 src/resources/entities/catalog create mode 100755 src/resources/entities/catalog-demo/catalog-demo-v10.dtd create mode 100644 src/resources/entities/catalog-demo/override.xml create mode 100644 src/resources/entities/catalog-demo/testpub.xml create mode 100644 src/resources/entities/catalog-demo/testsys.xml create mode 100755 src/resources/entities/changes-v10.dtd create mode 100755 src/resources/entities/characters.ent create mode 100755 src/resources/entities/datatypes.dtd create mode 100755 src/resources/entities/document-v10.dtd create mode 100755 src/resources/entities/faq-v10.dtd create mode 100755 src/resources/entities/javadoc-v04draft.dtd create mode 100755 src/resources/entities/sitemap-v02.dtd create mode 100755 src/resources/entities/specification-v10.dtd create mode 100755 src/resources/entities/svg-cocoon-v11.dtd create mode 100755 src/resources/entities/svg10.dtd create mode 100755 src/resources/entities/todo-v10.dtd create mode 100755 src/resources/javadoc.css create mode 100755 src/scratchpad/src/Manifest.mf create mode 100755 src/testcases/org/apache/poi/hssf/data/BigSSTRecord create mode 100755 src/testcases/org/apache/poi/hssf/data/BigSSTRecord2 create mode 100755 src/testcases/org/apache/poi/hssf/data/BigSSTRecord2CR1 create mode 100755 src/testcases/org/apache/poi/hssf/data/BigSSTRecord2CR2 create mode 100755 src/testcases/org/apache/poi/hssf/data/BigSSTRecord2CR3 create mode 100755 src/testcases/org/apache/poi/hssf/data/BigSSTRecord2CR4 create mode 100755 src/testcases/org/apache/poi/hssf/data/BigSSTRecord2CR5 create mode 100755 src/testcases/org/apache/poi/hssf/data/BigSSTRecord2CR6 create mode 100755 src/testcases/org/apache/poi/hssf/data/BigSSTRecord2CR7 create mode 100755 src/testcases/org/apache/poi/hssf/data/BigSSTRecordCR create mode 100755 src/testcases/org/apache/poi/hssf/data/Employee.xls create mode 100755 src/testcases/org/apache/poi/hssf/data/Simple.xls create mode 100755 src/testcases/org/apache/poi/hssf/data/SimpleChart.xls create mode 100755 src/testcases/org/apache/poi/hssf/data/SimpleWithFormula.xls create mode 100755 src/testcases/org/apache/poi/hssf/data/SimpleWithSkip.xls create mode 100755 src/testcases/org/apache/poi/hssf/data/SimpleWithStyling.xls create mode 100755 src/testcases/org/apache/poi/hssf/data/rk.xls create mode 100755 src/testcases/org/apache/poi/hssf/data/test_properties1 create mode 100644 src/testcases/org/apache/poi/hssf/record/TestRecordFactory.java create mode 100644 src/testcases/org/apache/poi/hssf/record/TestSSTRecord.java create mode 100644 src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java create mode 100644 src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java create mode 100644 src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java create mode 100644 src/testcases/org/apache/poi/hssf/usermodel/TestReadWriteChart.java create mode 100644 src/testcases/org/apache/poi/hssf/usermodel/TestWorkbook.java create mode 100644 src/testcases/org/apache/poi/poifs/eventfilesystem/Listener.java create mode 100644 src/testcases/org/apache/poi/poifs/eventfilesystem/TestPOIFSReaderRegistry.java create mode 100644 src/testcases/org/apache/poi/poifs/filesystem/ReaderWriter.java create mode 100644 src/testcases/org/apache/poi/poifs/filesystem/TestDirectoryNode.java create mode 100644 src/testcases/org/apache/poi/poifs/filesystem/TestDocument.java create mode 100644 src/testcases/org/apache/poi/poifs/filesystem/TestDocumentDescriptor.java create mode 100644 src/testcases/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java create mode 100644 src/testcases/org/apache/poi/poifs/filesystem/TestDocumentNode.java create mode 100644 src/testcases/org/apache/poi/poifs/filesystem/TestDocumentOutputStream.java create mode 100644 src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSDocumentPath.java create mode 100644 src/testcases/org/apache/poi/poifs/property/LocalProperty.java create mode 100644 src/testcases/org/apache/poi/poifs/property/TestDirectoryProperty.java create mode 100644 src/testcases/org/apache/poi/poifs/property/TestDocumentProperty.java create mode 100644 src/testcases/org/apache/poi/poifs/property/TestPropertyFactory.java create mode 100644 src/testcases/org/apache/poi/poifs/property/TestPropertyTable.java create mode 100644 src/testcases/org/apache/poi/poifs/property/TestRootProperty.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/LocalProperty.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/LocalRawDataBlockList.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/TestBlockAllocationTableReader.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/TestBlockAllocationTableWriter.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/TestBlockListImpl.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/TestDocumentBlock.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/TestHeaderBlockReader.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/TestHeaderBlockWriter.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/TestPropertyBlock.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/TestRawDataBlock.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/TestRawDataBlockList.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/TestSmallBlockTableReader.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/TestSmallBlockTableWriter.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/TestSmallDocumentBlock.java create mode 100644 src/testcases/org/apache/poi/poifs/storage/TestSmallDocumentBlockList.java create mode 100644 src/testcases/org/apache/poi/util/LocalTestNode.java create mode 100644 src/testcases/org/apache/poi/util/TestBinaryTree.java create mode 100644 src/testcases/org/apache/poi/util/TestBitField.java create mode 100644 src/testcases/org/apache/poi/util/TestByteField.java create mode 100644 src/testcases/org/apache/poi/util/TestHexDump.java create mode 100644 src/testcases/org/apache/poi/util/TestIntList.java create mode 100644 src/testcases/org/apache/poi/util/TestIntegerField.java create mode 100644 src/testcases/org/apache/poi/util/TestLittleEndian.java create mode 100644 src/testcases/org/apache/poi/util/TestLongField.java create mode 100644 src/testcases/org/apache/poi/util/TestPOILogFactory.java create mode 100644 src/testcases/org/apache/poi/util/TestPOILogger.java create mode 100644 src/testcases/org/apache/poi/util/TestShortField.java create mode 100644 src/testcases/org/apache/poi/util/TestShortList.java create mode 100644 src/testcases/org/apache/poi/util/TestStringUtil.java create mode 100755 src/testcases/org/apache/poi/util/data/test_properties1 create mode 100755 src/testcases/org/apache/poi/util/data/test_properties2 create mode 100755 src/testcases/org/apache/poi/util/data/test_properties3 create mode 100755 tools/.cvsignore create mode 100755 tools/bin/ant create mode 100755 tools/bin/ant.bat create mode 100755 tools/bin/antRun create mode 100755 tools/bin/antRun.bat create mode 100755 tools/bin/fix-packages.py create mode 100755 tools/bin/lcp.bat create mode 100755 tools/bin/runant.pl create mode 100755 tools/lib/.cvsignore create mode 100755 tools/lib/ant-1.4.1-optional.jar create mode 100755 tools/lib/ant-1.4.1.jar create mode 100644 tools/lib/jtidy-04aug2000r7-dev.jar create mode 100755 tools/lib/junit.jar create mode 100644 tools/lib/xalan-2.2.0.jar create mode 100755 tools/resources/Release-Checklist.txt create mode 100755 tools/resources/jindent/poi.jin create mode 100755 tools/resources/stylesheets/html2xml.xsl create mode 100644 tools/src/ClassAvailable.java create mode 100644 tools/src/JTidyTask.java create mode 100644 tools/src/SitemapTool.java create mode 100644 tools/src/UserInput.java create mode 100644 tools/src/XConfTool.java create mode 100755 tools/src/announcement2header.xsl create mode 100755 tools/src/announcement2readme.xsl create mode 100755 tools/src/announcement2site.xsl create mode 100755 tools/src/announcement2txt.xsl create mode 100755 tools/src/bugzilla2patchqueue.xsl create mode 100755 tools/src/changelog.xsl create mode 100755 tools/src/patchqueue2text4dev.xsl create mode 100755 tools/src/patchqueue2xdocs.xsl diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 000000000..f1f65bf2c --- /dev/null +++ b/.cvsignore @@ -0,0 +1,13 @@ +.ant.properties +dist +build +distributions +prj.el +emacs-jprj.el +docs +todo +p1.log +p2.log +poi.ipr +release-bin +POILogger.log \ No newline at end of file diff --git a/README.txt b/README.txt new file mode 100755 index 000000000..2c6be458f --- /dev/null +++ b/README.txt @@ -0,0 +1,49 @@ + + P O I + + @version@ + + + What is it? + ----------- + + + + Where is it? + ------------ + + The home page for the POI project can be found in the POI + Project web site (http://poi.sourceforge.net/). There you also find + information on how to download the latest release as well as all the other + information you might need regarding this project. + + + Requirements + ------------ + + The following requirements exist for installing it: + + o A Java 1.2 or later compatible virtual machine for your operating system. + + Installation Instructions and Documentation + ------------------------------------------- + + The documentation available as of the date of this release is + included in the "docs/" directory. + + Look for the most updated documentation on the POI web site. + + + Licensing and legal issues + -------------------------- + + For legal and licensing issues, please read the LICENSE files + in the /legal directory. + + + Thanks for using POI. + + The POI Project + http://poi.sourceforgef.net/ + + diff --git a/build.bat b/build.bat new file mode 100755 index 000000000..57c087d4b --- /dev/null +++ b/build.bat @@ -0,0 +1,23 @@ +@echo off +rem ---------------------------------------------------------------------------- +rem build.bat - Win32 Build Script for Apache Cocoon +rem +rem $Id$ +rem ---------------------------------------------------------------------------- + +rem ----- Copy Xalan and Xerces for the build system ------------------------ +copy lib\optional\xerces*.jar tools\lib +copy lib\optional\xalan*.jar tools\lib +copy lib\optional\xml-api*.jar tools\lib +copy lib\optional\jtidy*.jar tools\lib + +rem ----- Verify and Set Required Environment Variables ------------------------ + +REM Commented out so it always uses poi's ant -- gjs -- if not "%ANT_HOME%" == "" goto gotAntHome +set OLD_ANT_HOME=%ANT_HOME% +set ANT_HOME=tools +:gotAntHome + +call %ANT_HOME%\bin\ant %1 %2 %3 %4 %5 %6 %7 %8 %9 +set ANT_HOME=%OLD_ANT_HOME% + diff --git a/build.sh b/build.sh new file mode 100755 index 000000000..dc3c1d4a7 --- /dev/null +++ b/build.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +echo +echo "POI Build System " +echo "----------------------------" + +cp -f ./lib/optional/xalan*.jar ./tools/lib +cp -f ./lib/optional/xerces*.jar ./tools/lib +cp -f ./lib/optional/xml-api*.jar ./tools/lib +cp -f ./lib/optional/jtidy*.jar ./tools/lib + +chmod u+x ./tools/bin/antRun +chmod u+x ./tools/bin/ant + +unset ANT_HOME + +CP=$CLASSPATH +export CP +unset CLASSPATH + +$PWD/tools/bin/ant -logger org.apache.tools.ant.NoBannerLogger -emacs $@ + +CLASSPATH=$CP +export CLASSPATH diff --git a/build.xml b/build.xml new file mode 100644 index 000000000..d124561fc --- /dev/null +++ b/build.xml @@ -0,0 +1,1022 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Please select a target + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

POI Filesystem format

+

Introduction

+

+ The POI file format is essentially an archive wrapper + around files. It is intended to mimic a filesystem. For + the remainder of this document it is referred to as a + filesystem in order to avoid confusion with the + "files" it contains. +

+

+ POI filesystems are compatible with those document formats + used by a well-known software company's popular office + productivity suite and programs outputting compatible + data. Because the POI filesystem does not provide + compression, encryption or any other worthwhile feature, + its not a good choice unless you require interoperability + with these programs. +

+

+ The POI filesystem does not encode the documents + themselves. For example, if you had a word processor file + with the extension ".doc", you would actually + have a POI filesystem with a document file archived inside + of the filesystem. +

+

Document Conventions

+

+ This document utilizes the numeric types as described by + the Java Language Specification, which can be found at + java.sun.com. In short: +

+
    +
  • +

    + a byte is an 8 bit signed integer ranging from + (-128) to 127. +

    +
  • +
  • +

    + a short is a 16 bit signed integer ranging from + (-32768) to 32767 +

    +
  • +
  • +

    + an int is a 32 bit signed integer ranging from + (-2.14e+9) to 2.14e+9 +

    +
  • +
  • +

    + a long is a 64 bit signed integer ranging from + (-9.22e+18) to 9.22e+18 +

    +
  • +
+

+ The Java Language Specification spells out a number of + other types that are not referred to by this document. +

+

+ Where this document makes references to "endian + conversion" it is referring to the byte order of + stored numbers. Numbers in "little-endian order" + are stored with the LEAST significant byte first. In order + to properly read a short, for example, you'd read two + bytes and then shift the second byte 8 bits to the left + before performing an or operation to it + against the first byte while stripping the + "sign" from the first byte. The following code + illustrates this method: +

+

+ public int getShort (byte[ ] rec) + { +

+

+ return ( + (rec[1] << 8) | (rec[0] & 0xff) + ); +

+

+ } +

+

Filesystem Introduction

+

+ POI filesystems are essentially normal files stored on a + Java-compatible platform's native filesystem. They are + identified by names ending in a four character identifier + noting what type of data they contain. For example, a file + ending in ".xls" would likely contain + spreadsheet data, and a file ending in ".doc" + would probably contain a word processing document. POI + filesystems are called "filesystem", because + they contain multiple embedded files in a manner similar + to traditional filesystems. Along functional lines, it + would be more accurate to call these POI archives. +

+

+ POI filesystems do not provide encryption, compression, or + any other feature of a modern archive and are therefore a + poor choice for implementing new file formats. It is + suggested that POI filesystems are most useful for + interoperability with legacy applications that use a + compatible file format. +

+

Filesystem Walkthrough

+

+ This is a walkthrough of a POI filesystem and how it is + put together. It is not intended to give a concise + description but to give a "big picture" of the + general structure and how it's interpreted. +

+

+ A POI filesystem begins with a header. This header + identifies locations in the file by function and provides + a sanity check identifying a native filesystem file as + indeed a POI filesystem. +

+

+ The first 64 bits of the header compose a magic + number identifier. This identifier tells the + client software that this is indeed a POI filesystem and + that it should be treated as such. This is a "sanity + check" to make sure this is a POI filesystem and not + some other format. The header also contains an array + of block numbers. These block numbers refer to + blocks in the file. When these blocks are read together + they form the Block Allocation + Table. The header also contains a pointer to + the first element in the property table + also known as the root + element, and a pointer to the small Block + Allocation Table (SBAT). +

+

+ The block allocation + table or BAT, along with the property table + specify which blocks in the filesystem belong to which + files. It is somewhat hard to conceptualize the Block + Allocation Table at first. The block allocation table is + essentially an array of integers that point at each + other. These elements form chains. +

+

+ To read the block allocation + table you must first read the start + block of the file from the property + table. This is both your index for the next + element in the BAT array as well as the + index of the first block in your file. For instance: if + the start block from your file's property is + 0 then you read block 0 (the first block after the header) + from your filesystem as the first block of your file. You + also read element 0 from the BAT array. + Supposing this element has a value equal to 2, you'd read + block 2 from your filesystem as the next block of your + file and element 2 from your BAT array. + This will be covered further later in this document. +

+

+ The Property + Table is essentially the directory structure + for the filesystem. It consists of the name of the file or + directory, its start block in both the + filesystem and BAT, and its actual size. + The first property in the property table is the root element. Its real + purpose is to hold the start block for the small + blocks. +

+

Filesystem Structure

+

+ All values in the POI filesystem are stored in + "little-endian" order, meaning you must reverse + the order of the bytes before assigning them to + variables. Assume the values you see below are originally + stored backwards. +

+

+ The POI filesystem is divided into 512 byte blocks. Each + block has an implicit block-type. The order and + description of these is described below. +

+

Header Block

+

+ The POI filesystem begins with a header + block. The first 64 bits of the header form a long + file type id or magic number + identifier of + 0xE11AB1A1E011CFD0L. This is basically a + sanity check. If this isn't the first thing in the header + (and consequently the filesystem) then this is not a POI + filesystem and should be read with some other library. +

+

+ It's important to know the most important parts of the + header. These are discussed in the rest of this + section. +

+

BATs

+

+ At offset 0x2c is an int specifying the number of + elements in the BAT array. The array at + 0x4c an array of ints. This array contains the + indices of every block in the Block + Allocation Table. +

+

XBATs

+

+ Very large POI archives may have more blocks than can be + addressed by the BAT blocks enumerated in the header + block. How large? Well, the BAT array in the header can + contain up to 109 BAT block indices; each BAT block + references up to 128 blocks, and each block is 512 bytes, + so we're talking about 109 * 128 * 512 = 6.8MB. That's a + pretty respectable document! But, you could have much more + data than that, and in today's world of cheap gigabyte + drives, why not? So, the BAT may be extended in that + event. The integer value at offset 0x44 of the + header is the index of the first extended BAT (XBAT) + block. At offset 0x48 of the header, there + is an int value that specifies how many XBAT blocks there + are. The XBAT blocks begin at the specified index into the + array of blocks making up the POI filesystem, and continue + in sequence for the specified count of XBAT blocks. +

+

+ Each XBAT block contains the indices of up to 128 BAT + blocks, so the document size can be expanded by another + 8MB for each XBAT block. The BAT blocks indexed by an XBAT + block are appended to the end of the list of BAT blocks + enumerated in the header block. Thus the BAT blocks + enumerated in the header block are BAT blocks 0 through + 108, the BAT blocks enumerated in the first XBAT block are + BAT blocks 109 through 236, the BAT blocks enumerated in + the second XBAT block are BAT blocks 237 through 364, and + so on. +

+

+ Through the use of XBAT blocks, the limit on the overall + document size is that imposed by the 4-byte block indices; + if the indices are unsigned ints, the maximum file size is + 2 terabytes, 1 terabyte if the indices are treated as + signed ints. Either way, I have yet to see a disk drive + large enough to accommodate such a file on the shelves at + the local office supply stores. +

+

SBATs

+

+ If a file contained in a POI archive is smaller than 4096 + bytes, it is stored in small blocks. Small blocks are 64 + bytes in length and are contained within big blocks, up to + 8 to a big block. As the main BAT is used to navigate the + array of big blocks, so the small block allocation + table is used to navigate the array of small + blocks. The SBAT's start block index is found at offset + 0x3C of the header block, and remaining blocks + constituting the SBAT are found by walking the main BAT as + if it were an ordinary file in the POI filesystem (this + process is described below). +

+

Property Table Start Index

+

+ An integer at address 0x30 specifies the start + index of the property + table. This integer is specified as a + "block index". The Property Table is stored, as is + almost everything in a POI file system, in big blocks and + walked via the BAT. The Property + Table is described below. +

+

Property Table

+

+ The property table is essentially nothing more than the + directory system. Properties are 128 byte records + contained within the 512 byte blocks. The first property + is always the Root Entry. The + following applies to individual properties within a + property table: +

+

+ At offset 0x00 in the property is the + "name". This is stored as an + uncompressed 16 bit unicode string. In short every other + byte corresponds to an "ASCII" character. The + size of this string is stored at offset 0x40 + (string size) as a short. +

+

+ At offset 0x42 is the property type + (byte). The type is 1 for directory, 2 for file or 5 for + the Root Entry. +

+

+ At offset 0x43 is the node color + (byte). The color is either 1, (black), or 0, + (red). Properties are apparently meant to be arranged in a + red-black binary tree, subject to the following rules: + +

    +
  1. The root of the tree is always black +
  2. Two consecutive nodes cannot both be red +
  3. A property is less than another property if its + name length is less than the other property's name + length +
  4. If two properties have the same name length, the + sort order is determined by the sort order of the + properties' names. +
+

+

+ At offset 0x44 is the index (int) of the + previous property. +

+

+ At offset 0x48 is the index (int) of the next + property. +

+

+ At offset 0x4C is the index (int) of the + first directory entry. +

+

+ At offset 0x74 is an integer giving the start + block for the file described by this + property. This index corresponds to an index in the array + of indices that is the Block Allocation Table (or the + Small Block Allocation Table) as well as the index of the + first block in the file. +

+

+ At offset 0x78 is an integer giving the total + actual size of the file pointed at by this + property. If the file size is less than 4096, the file is + stored in small blocks and the SBAT is used to walk the + small blocks making up the file. If the file size is 4096 + or larger, the file is stored in big blocks and the main + BAT is used to walk the big blocks making up the file. The + exception to this rule is the Root Entry, + which, regardless of its size, is ALWAYS stored in big + blocks and the main BAT is used to walk the big blocks + making up this special file. +

+

Root Entry

+

+ The Root Entry in the Property Table + contains the information necessary to read and write small + files, which are files less than 4096 bytes long. The + start block field of the Root Entry is the start index of + the Small Block Array, which is read like + any other file in the POI filesysstem. Since the SBAT + cannot be used without the Small Block Array, the Root + Entry MUST be read or written using the Block Allocation Table. The + blocks making up the Small Block Array are divided into + 64-byte small blocks, up to the size indicated in the Root + Entry (which should always be a multiple of 64) +

+

Walking the Nodes of the Property + Table

+

+ The individual properties form a directory tree, with the + Root Entry as the directory tree's root, as + shown in the accompanying drawing. Note the numbers in + parentheses in each node; they represent the node's index + in the array of properties. The NEXT_PROP, + PREVIOUS_PROP, and CHILD_PROP fields hold + these indices, and are used to navigate the tree. +

+

+ +

+

+ Each directory entry (i.e., a + property whose type is directory or + root entry) uses its CHILD_PROP field + to point to one of its subordinate (child) properties. It + doesn't seem to matter which of its children it points + to. Thus in the previous drawing, the Root Entry's + CHILD_PROP field may contain 1, 4, or the index of one of + its other children. Similarly, the directory node (index + 1) may have, in its CHILD_PROP field, 2, 3, or the index + of one of its other children. +

+

+ The children of a given directory property point to + each other in a similar fashion by using their + NEXT_PROP and PREVIOUS_PROP fields. The + ordering of the children is governed by rules described here +

+

+ Unused NEXT_PROP, PREVIOUS_PROP, and + CHILD_PROP fields contain the marker value of + -1. All file properties have a value of -1 for their + CHILD_PROP fields for example. +

+

Block Allocation Table

+

+ The BAT blocks are pointed at by the bat + array contained in the header + and supplemented, if necessary, by the XBAT + blocks. These blocks form a large table of + integers. These integers are block numbers. The + Block Allocation Table holds chains of + integers. These chains are terminated with -2. The + elements in these chains refer to blocks in the files. The + starting block of a file is NOT specified in the BAT. It + is specified by the property for a given + file. The elements in this BAT are both the block number + (within the file minus the header) AND the number of the + next BAT element in the chain. This can be thought of as a + linked list of blocks. The BAT array contains the links + from one block to the next, including the end of chain + marker. +

+

+ Here's an example: Let's assume that the BAT begins as + follows: +

+

+ BAT[ 0 ] = 2 +

+

+ BAT[ 1 ] = 5 +

+

+ BAT[ 2 ] = 3 +

+

+ BAT[ 3 ] = 4 +

+

+ BAT[ 4 ] = 6 +

+

+ BAT[ 5 ] = + -2 +

+

+ BAT[ 6 ] = 7 +

+

+ BAT[ 7 ] = + -2 +

+

+ ... +

+

+ Now, if we have a file whose Property Table entry says it + begins with index 0, we walk the BAT array and see that + the file consists of blocks 0 (because the start block is + 0), 2 (because BAT[ 0 ] is 2), 3 (BAT[ 2 ] is 3), 4 (BAT[ + 3 ] is 4), 6 (BAT[ 4 ] is 6), and 7 (BAT[ 6 ] is 7). It + ends at block 7 because BAT[ 7 ] is -2, which is the end + of chain marker. +

+

+ Similarly, a file beginning at index 1 consists of + blocks 1 and 5. +

+

+ Other special numbers in a BAT array are: +

+
    +
  • +

    + -1, which indicates an unused block +

    +
  • +
  • +

    + -3, which indicates a "special" block, + such as a block used to make up the Small Block + Array, the Property + Table, the main BAT, or the SBAT +

    +
  • +
+

Filesystem Structures

+

+ The following outlines the basic filesystem structures. +

+

Header (block 1) -- 512 (0x200) bytes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescriptionOffsetLengthDefault value or const
FILETYPEMagic number identifying this as a POI + filesystem.0x0000Long0xE11AB1A1E011CFD0
UK1Unknown constant0x0008Integer0
UK2Unknown Constant0x000CInteger0
UK3Unknown Constant0x0014Integer0
UK4Unknown Constant (revision?)0x0018Short0x003B
UK5Unknown Constant (version?)0x001AShort0x0003
UK6Unknown Constant0x001CShort-2
LOG_2_BIG_BLOCK_SIZELog, base 2, of the big block size0x001EShort9 (2 ^ 9 = 512 bytes)
LOG_2_SMALL_BLOCK_SIZELog, base 2, of the small block size0x0020Integer6 (2 ^ 6 = 64 bytes)
UK7Unknown Constant0x0024Integer0
UK8Unknown Constant0x0028Integer0
BAT_COUNTNumber of elements in the BAT array0x002CIntegerrequired
PROPERTIES_STARTBlock index of the first block of the property table0x0030Integerrequired
UK9Unknown Constant0x0034Integer0
UK10Unknown Constant0x0038Integer0x00001000
SBAT_STARTBlock index of first big block containing the + small block allocation table (SBAT)0x003CInteger-2
UK11Unknown Constant0x0040Integer1
XBAT_STARTBlock index of the first block in the Extended + Block Allocation Table (XBAT)0x0044Integer-2
XBAT_COUNTNumber of elements in the Extended Block + Allocation Table (to be added to the BAT)0x0048Integer0
BAT_ARRAYArray of block indicies constituting the Block Allocation Table (BAT)0x004C, 0x0050, 0x0054 ... 0x01FCInteger[ ]-1 for unused elements, at least first element + must be filled.
N/AHeader block data not otherwise described in this + tableN/AN/A-1
+

Block Allocation Table Block -- 512 + (0x200) bytes

+ + + + + + + + + + + + + + + +
FieldDescriptionOffsetLengthDefault value or const
BAT_ELEMENTAny given element in the BAT block0x0000, 0x0004, 0x0008, ... 0x01FCInteger-1 = unused
+ -2 = end of chain
+ -3 = special (e.g., BAT block)
+ All other values point to the next element in the + chain and the next index of a block composing the + file.
+

Property Block -- 512 (0x200) byte block

+ + + + + + + + + + + + + + + +
FieldDescriptionOffsetLengthDefault value or const
Properties[ ]This block contains the properties.0x0000, 0x0080, 0x0100, 0x0180128 bytesAll unused space is set to -1.
+

Property -- 128 (0x80) byte block

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescriptionOffsetLengthDefault value or const
NAMEA unicode null-terminated uncompressed 16bit + string (lose the high bytes) containing the name + of the property.0x00, 0x02, 0x04, ... 0x3EShort[ ]0x0000 for unused elements, field required, 32 + (0x40) element max
NAME_SIZENumber of characters in the NAME field0x40ShortRequired
PROPERTY_TYPEProperty type (directory, file, or root)0x42Byte1 (directory), 2 (file), or 5 (root entry)
NODE_COLORNode color0x43Byte0 (red) or 1 (black)
PREVIOUS_PROPPrevious property index0x44Integer-1
NEXT_PROPNext property index0x48Integer-1
CHILD_PROPFirst child property index0x4cInteger-1
SECONDS_1Seconds component of the created timestamp?0x64Integer0
DAYS_1Days since epoch component of the created + timestamp?0x68Integer0
SECONDS_2Seconds component of the modified timestamp?0x6CInteger0
DAYS_2Days since epoch component of the modified + timestamp?0x70Integer0
START_BLOCKStarting block of the file, used as the first + block in the file and the pointer to the next + block from the BAT0x74IntegerRequired
SIZEActual size of the file this property points + to. (used to truncate the blocks to the real + size).0x78Integer0
+ + \ No newline at end of file diff --git a/src/documentation/xdocs/poifs/html/POIFSUseCases.html b/src/documentation/xdocs/poifs/html/POIFSUseCases.html new file mode 100755 index 000000000..7eddf0c35 --- /dev/null +++ b/src/documentation/xdocs/poifs/html/POIFSUseCases.html @@ -0,0 +1,449 @@ + + + + + + + + + + + + + +

POI Use Cases

+


+

+

Use Case 1: Read existing file +system

+

Primary Actor: POI client

+

Scope: POI

+

Level: Summary

+

Stakeholders and Interests:

+
    +
  • POI client- wants to read content + of file system

    +
  • POI - understands POI file system

    +
+

Precondition: None

+

Minimal Guarantee: None

+

Main Success Guarantee:

+
    +
  1. POI client requests POI to read a + POI file system, providing an InputStream + containing POI file system in question.

    +
  2. POI reads from the InputStream + in 512 byte blocks

    +
  3. POI verifies that the first block + begins with the well known signature (0xE11AB1A1E011CFD0)

    +
  4. POI reads the Block Allocation + Table from the first block and, if necessary, from the XBAT blocks.

    +
  5. POI obtains the start block of the + Property Table and reads the Property Table (use case 9, read file)

    +
  6. POI reads the individual entries + in the Property Table

    +
  7. POI obtains the start block of the + Small Block Allocation Table and reads the Small Block Allocation + Table (use case 9, read file)

    +
  8. POI obtains the start block of the + Small Block store from the first entry in the Property Table and + reads the Small Block Array (use case 9, read file)

    +
+

Extensions:

+

2a. If the last +block read is not a 512 byte block, the InputStream +is not that of a POI file system, and POI throws an appropriate +exception.

+

3a. If the +signature is incorrect, the InputStream +is not that of a POI file system, and POI throws an appropriate +exception.

+

+
+

+

Use Case 2: Write file system

+

Primary Actor: POI client

+

Scope: POI

+

+Level: Summary

+

Stakeholders and Interests:

+
    +
  • POI client- wants to write file + system out.

    +
  • POI - knows how to write file + system out.

    +
+

Precondition:

+
    +
  • File system + has been read (use case 1, read existing file system) and + subsequently modified (use case 4, replace file in file system; use + case 5, delete file from file systen; or use case 6, write new file + to file system; in any combination)

    +
+

or

+
    +
  • File system + has been created (use case 3, create new file system)

    +
+

Minimal Guarantee: None

+

Main Success Guarantee:

+
    +
  1. POI client + provides an OutputStream to + write the file system to.

    +
  2. POI gets the + sizes of the Property Table and each file in the file system.

    +
  3. If any files + in the file system requires storage in a Small Block Array, POI + creates a Small Block Array of sufficient size to hold all of the + small files.

    +
  4. POI + calculates the number of big blocks needed to hold all of the large + files, the Property Table, and, if necessary, the Small Block Array + and the Small Block Allocation Table.

    +
  5. POI creates a + set of big blocks sufficient to store the Block Allocation Table

    +
  6. POI creates + and writes the header block

    +
  7. POI writes + out the XBAT blocks, if needed.

    +
  8. POI writes + out the Small Block Array, if needed

    +
  9. POI writes + out the Small Block Allocation Table, if needed

    +
  10. POI writes + out the Property Table

    +
  11. POI writes + out the large files, if needed

    +
  12. POI closes + the OutputStream.

    +
+

Extensions:

+

6a. Exceptions +writing to the OutputStream +will be propagared back to the POI client.

+

7a. Exceptions +writing to the OutputStream +will be propagared back to the POI client.

+

8a. Exceptions +writing to the OutputStream +will be propagared back to the POI client.

+

9a. Exceptions +writing to the OutputStream +will be propagared back to the POI client.

+

10a. Exceptions +writing to the OutputStream +will be propagared back to the POI client.

+

11a. Exceptions +writing to the OutputStream +will be propagared back to the POI client.

+

12a. Exceptions +closing the OutputStream will +be propagared back to the POI client.

+


+

+

Use Case 3: Create new file +system

+

Primary Actor: POI client

+

Scope: POI

+

+Level: Summary

+

Stakeholders and Interests:

+
    +
  • POI client- wants to create a new + file system.

    +
  • POI - knows how to create a new + file system.

    +
+

Precondition:

+

Minimal Guarantee: None

+

Main Success Guarantee:

+
    +
  1. POI creates + an empty Property Table.

    +
+

Extensions: +None

+


+

+

Use Case 4: Replace file in file +system

+

Primary Actor: POI client

+

Scope: POI

+

+Level: Summary

+

Stakeholders and Interests:

+
    +
  • POI client- wants to replace an + existing file in the file system

    +
  • POI - knows how to manage the file + system.

    +
+

Precondition:

+

Either

+
    +
  • The file system has been read (use + case 1, read existing file system) and a file has been extracted + from the file system (use case 7, read existing file from file + system), or

    +

    the file system has been created (use + case 3, create new file system) and a file has been written to the + file system (use case 6, write new file to file system)

    +
  • The file already exists in the + file system.

    +
+

Minimal Guarantee: None

+

Main Success Guarantee:

+
    +
  1. POI discards + storage of the existing file.

    +
  2. POI updates + the existing file's entry in the Property Table

    +
  3. POI stores + the new file's data

    +
+

Extensions:

+

1a. POI throws an +exception if the file does not exist.

+


+

+

Use Case 5: Delete file from +file system

+

Primary Actor: POI client

+

Scope: POI

+

+Level: Summary

+

Stakeholders and Interests:

+
    +
  • POI client- wants to remove a file + from a file system

    +
  • POI - knows how to manage the file + system

    +
+

Precondition:

+
    +
  • The file system has been read (use + case 1, read existing file system) and a file has been extracted + from the file system (use case 7, read existing file from file + system), or

    +

    the file system has been created (use + case 3, create new file system) and a file has been written to the + file system (use case 6, write new file to file system)

    +
  • The file already exists in the + file system.

    +
+

Minimal Guarantee: None

+

Main Success Guarantee:

+
    +
  1. POI discards + the specified file's storage

    +
  2. POI discards + the file's Property Table entry

    +
+

Extensions:

+

1a. POI throws an +exception if the file does not exist.

+


+

+

Use Case 6: Write new file to +file system

+

Primary Actor: POI client

+

Scope: POI

+

+Level: Summary

+

Stakeholders and Interests:

+
    +
  • POI client- wants to add a new + file to the file system

    +
  • POI - knows how to manage the file + system.

    +
+

Precondition: +

+
    +
  • The specified file does not yet + exist in the file system.

    +
+

Minimal Guarantee: None

+

Main Success Guarantee:

+
    +
  1. The POI + client provides a file name

    +
  2. POI creates a + new Property Table entry for the new file

    +
  3. POI + provides the POI client with an OutputStream + to write to.

    +
  4. The POI client writes data to the + provided OutputStream.

    +
  5. The POI client closes the provided + OutputStream

    +
  6. POI updates the Property Table + entry with the new file's size

    +
+

Extensions:

+

1a. POI throws an +exception if a file with the specified name already exists in the +file system.

+

1b. POI throws an +exception if the file name is too long. The limit on file name length +is 32 characters.

+


+

+

Use Case 7: Read existing file +from file system

+

Primary Actor: POI client

+

Scope: POI

+

+Level: Summary

+

Stakeholders and Interests:

+
    +
  • POI client- wants to read a file + from the file system.

    +
  • POI - knows how to manage the file + system.

    +
+

Precondition:

+
    +
  • The file + system is has been read (use case 1, read existing file system) or + has been created and written to (use case 3, create new file system; + use case 6, write new file to file system.

    +
  • The specified + file exists in the file system.

    +
+

Minimal Guarantee: None

+

Main Success Guarantee:

+
    +
  1. The POI + client provides the name of a file to be read

    +
  2. POI provides + an InputStream to read from.

    +
  3. The POI + client reads from the InputStream.

    +
  4. The POI + client closes the InputStream.

    +
+

Extensions:

+

1a. POI throws an +exception if no file with the specified name exists.

+


+

+

Use Case 8: Read file system +directory

+

Primary Actor: POI client

+

Scope: POI

+

+Level: Summary

+

Stakeholders and Interests:

+
    +
  • POI client- wants to know what + files exist in the file system.

    +
  • POI - POI knows how to manage the + file system.

    +
+

Precondition:

+
    +
  • The file + system has been read (use case 1, read existing file system) or + created (use case 3, create new file system)

    +
+

Minimal Guarantee: None

+

Main Success Guarantee:

+
    +
  1. The POI + client requests the file system directory.

    +
  2. POI returns + an Iterator. The Iterator + will not include the root entry in the Property Table, and may be an + Iterator over an empty + Collection.

    +
+

Extensions: +None

+


+

+

Use Case 9: Read file

+

Primary Actor: POI

+

Scope: POI

+

+Level: Summary

+

Stakeholders and Interests:

+
    +
  • POI - POI needs to read a file, or + something resembling a file (i.e., the Property Table, the Small + Block Array, or the Small Block Allocation Table)

    +
+

Precondition: None

+

Minimal Guarantee: None

+

Main Success Guarantee:

+
    +
  1. POI begins + with a start block, a file size, and a flag indicating whether to + use the Big Block Allocation Table or the Small Block Allocation + Table

    +
  2. POI returns + an InputStream.

    +
  3. Reads from + the InputStream are performed by walking the specified Block + Allocation Table and reading the blocks indicated.

    +
  4. POI closes + the InputStream when finished reading the file, or its client wants + to close the InputStream.

    +
+

Extensions:

+

3a. An exception +will be thrown if the specified Block Allocation Table is corrupt, as +evidenced by an index pointing to a non-existent block, or by a chain +extending past the known size of the file.

+


+

+

Use Case 10: Rename existing +file in file system

+

Primary Actor: POI client

+

Scope: POI

+

+Level: Summary

+

Stakeholders and Interests:

+
    +
  • POI client- wants to rename an + existing file in the file system.

    +
  • POI - knows how to manage the file + system.

    +
+

Precondition: +

+
    +
  • The file + system is has been read (use case 1, read existing file system) or + has been created and written to (use case 3, create new file system; + use case 6, write new file to file system.

    +
  • The specified + file exists in the file system.

    +
  • The new name + for the file does not duplicate another file in the file system.

    +
+

Minimal Guarantee: None

+

Main Success Guarantee:

+
    +
  1. POI updates + the Property Table entry for the specified file with its new name.

    +
+

Extensions:

+

1a. If the old +file name is not in the file system, POI throws an exception.

+

1b. If the new +file name already exists in the file system, POI throws an exception.

+

1c. If the new +file name is too long (the limit is 32 characters), POI throws an +exception.

+


+

+ + \ No newline at end of file diff --git a/src/documentation/xdocs/poifs/html/how-to.html b/src/documentation/xdocs/poifs/html/how-to.html new file mode 100755 index 000000000..df402e89e --- /dev/null +++ b/src/documentation/xdocs/poifs/html/how-to.html @@ -0,0 +1,190 @@ + + + + + + + + + + + +

POIFS HOW TO

+

How to use POIFS directly

+

Andrew C. Oliver - December 14, 2001

+
+
10.31.2001- initial revision for + build POI 0.12.3 +
+ 12.15.2001 - minor revisions - thread safety, entry modification, + name restrictions, and so on.
+ 12.30.2001 - revised for POI 1.0-final - minor revisions +
+

+Capabilities

+
+
This release of POIFS contains the + full functionality to read, write and modify (by recreation) files + in the format most commonly referred to as OLE 2 Compound Document + Format (proabably tm - Microsoft). +
+

+Target Audience

+

This release candidate is intended for general use. It is +considered to be production-ready. It has not yet been extensively +tested (especially in a high load multi-threaded server situation), +though it's been unit tested quite a bit. This release is considered +to be "golden" as it has been used by HSSF and other users +without problems for some time, and has not changed recently. +

+

General Use

+

User API

+

High level description and overview

+

Files written with the POIFS library are referred to as POIFS file +systems (or sometimes archives). The OLE 2 Compound Document format +is designed to mimic many of the characteristics of a pre-modern file +system (most similar to FAT). We make the distinction between POIFS +written files and "native" written OLE 2 Compound Document +Format files because while we believe POIFS to be a full, correct and +complete implementation, most of this was accomplished through +researching other open source implementations and flat out guesses.

+

This overview is in no way intended to be complete (for a more +intense discussion please see POIFSFormat.html in this same +directory), it should give you a good idea into the principals of a +POIFS file system. Please note that specific file formats such as XLS +(HSSF) or DOC utilize POIFS file systems to contain their data, POIFS +itself does not know how to interpret the archived data.

+

Every POIFS file system contains a hierarchy of directories +starting with the root (there is always one, and only one, root). +Each directory, including the root, may contain one or more +directories and/or documents. Every directory and document has a +name. The root directory has a name, but unlike other directories, +its name is fixed and cannot be renamed.

+

The POIFS API was not designed to be, and is not, +thread-safe. Only one thread of control should ever +manipulate a specific POIFS file system over that file system's +lifetime. You can, of course, have multiple threads, each +manipulating a distinct POIFS file system instance.

+

Writing a new one

+

To create a new (from scratch) POIFS file system for writing to, +you simply create an instance of +net.sourceforge.poi.poifs.filesystem.Filesystem using +the default constructor (no arguments). Initially this POIFS file +system will be empty except for containing the essential root +directory.

+

From there you can create a directory entry by calling  +Filesystem.createDirectory(name), and passing in the name of +the directory. This will return an instance +of net.sourceforge.poi.poifs.filesystem.DirectoryEntry +. You can also create a document within the root directory by +calling  Filesystem.createDocument(name, inputstream), +and passing the name of the document and an instance +of java.io.InputStream from which the document's +data can be obtained. It is noted that, the most commonly used file +formats of the Microsoft Corporation such as DOC, XLS, etc. are all +POIFS-compatible file systems with documents stored in the root +directory.

+

Supposing the document is to be stored in a directory other than +the root, you take the instance of DirectoryEntry +that you created and call createDocument(name, +inputstream) on it instead. You can also create a child +directory by calling  createDirectory(name). +Alternatively you can call Filesystem.getRoot() and +use it just like any other directory entry.

+

When you've finished creating entries in the filesystem, simply +call  Filesystem.writeFilesystem(stream) passing in +an instance of  java.io.OutputStream. Be sure you +close the stream when you're done.

+
Names
+

The POIFS file system imposes two limitations on document and +directory names:

+
    +
  1. The names of documents and + directories must be unique within their containing directory. Pretty + obvious. +

    +
  2. Names are restricted to 31 characters. If you create a + directory or document with a name longer than that, it will be + silently truncated. When truncated, it may conflict with the name of + another directory or document, and the create operation will fail. +

    +
+
Why not Readers and Writers?
+

The POIFS file system uses Streams because HSSF, and virtually all +other applications that would use POIFS, deals with binary files, +which Streams handle correctly. Readers and Writers deal with text +and know how to handle 16-bit characters. If there is a demand for +providing support for Readers and Writers, let us know.

+

Here is some example code (excerpted and adapted from +net.sourceforge.poi.hssf.usermodel.Workbook class):

+
        byte[]     bytes        = getBytes();                                             // get the bytes for the document (elsewhere in the class)
+        FileOutputStream stream = new FileOutputStream("/home/reportsys/test/text.xls");  // create a new FileOuputStream
+        Filesystem fs           = new Filesystem();                                       // create a new POIFS Filesystem object
+        fs.createDocument(new ByteArrayInputStream(bytes), "Workbook");                   // create a new document in the root directory of the POIFS filesystem
+                                                                                          // close on ByteArrayInputStream is a no-op so we don't bother, no real file handle is used
+        fs.writeFilesystem(stream);                                                       // write the filesystem to the output stream.
+        Stream.close();                                                                   // close our stream (don't leak file handles its bad news)

+Reading or modifying an existing file

+

Reading in an exising POIFS file system is equally simple. Create +a new instance of net.sourceforge.poi.poifs.filesystem.Filesystem +by calling the Filesystem(java.io.InputStream) +constructor and passing in your file system's data (this would +probably be a FileInputStream , but it doesn't matter). +From there you can get documents from the root directory by calling +Filesystem.createDocumentInputStream(name) and passing a +string representing that document's name.

+

If you wish to walk the filesystem, the easiest thing to do is +DirectoryEntry.getEntries(). This will give you a +java.util.Iterator of Entry instances +(DirectoryEntry and DocumentEntry are +extensions of Entry) contained by the DirectoryEntry +. For instance you could call Filesystem.getRoot() to +retrieve a DirectoryEntry instance. From there you could +call DirectoryEntry.getEntries() and retrieve an +Iterator of those entries. Iterating through these +entries, you'd call getName() to check the name of the +entry and isDocumentEntry() or isDirectoryEntry() +to determine its type. Going the other way, given an Entry, +you can walk back up the directory chain by calling getParent(), +which returns the Entry's containing DirectoryEntry +(calling getParent() on the root directory returns a +null reference).

+

With a DocumentEntry, you can create an instance of +net.sourceforge.poi.poifs.filesystem.DocumentInputStream +, by passing the DocumentEntry as the only argument to +the constructor of DocumentInputStream.The +DocumentInputStream class is a simple extension of +java.io.InputStream that fully supports the InputStream +API, including the mark , reset, and skip +methods, providing a form of random access I/O.

+

To modify the file you would simply walk through the entries and +follow the same instructions for writing a POIFS file system from +scratch. There are also methods to delete an Entry +(note: you cannot delete the root directory, nor can you delete a +DirectoryEntry unless it's empty) and to rename an Entry +(but see the notes above). +

+

POIFS Logging facility

+

POIFS does not yet use log4j style logging.

+

Here is an example +

+
Paste log config example

+POIFS Developer's Tools

+

POIFS does not yet have developer's tools. +

+

What's Next?

+
    +
  1. Refactoring of the API to more + cleanly separate write from read. +

    +
  2. Add logging/tracing code +

    +
  3. Add tree viewer (probably Andy) +

    +
  4. Read/write support for creation and modification time stamps +

    +
+



+

+ + \ No newline at end of file diff --git a/src/documentation/xdocs/poifs/index.xml b/src/documentation/xdocs/poifs/index.xml new file mode 100644 index 000000000..e525920a5 --- /dev/null +++ b/src/documentation/xdocs/poifs/index.xml @@ -0,0 +1,22 @@ + + + + +
+ PoiFS + Overview + + + + +
+ + + + +

POIFS is a pure Java implementation of the OLE 2 Compound Document format.

+

TODO: copy POIFS docs and port to XML. For now please reference old site. +

+
+ +
diff --git a/src/documentation/xdocs/todo.xml b/src/documentation/xdocs/todo.xml new file mode 100644 index 000000000..24804606f --- /dev/null +++ b/src/documentation/xdocs/todo.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + do it + + + + + + + do it + + + + diff --git a/src/documentation/xdocs/utils/book.xml b/src/documentation/xdocs/utils/book.xml new file mode 100644 index 000000000..f6ed52cee --- /dev/null +++ b/src/documentation/xdocs/utils/book.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/src/documentation/xdocs/utils/index.xml b/src/documentation/xdocs/utils/index.xml new file mode 100644 index 000000000..a8777c036 --- /dev/null +++ b/src/documentation/xdocs/utils/index.xml @@ -0,0 +1,20 @@ + + + + +
+ Poi Utils + Overview + + + +
+ + + + +

This is Poi Utils.

+ +
+ +
diff --git a/src/documentation/xdocs/who.xml b/src/documentation/xdocs/who.xml new file mode 100644 index 000000000..96bb28771 --- /dev/null +++ b/src/documentation/xdocs/who.xml @@ -0,0 +1,57 @@ + + + + +
+ Who we are + + + + +
+ + + + +

+ The Poi Project operates on a meritocracy: the more you do, the more + responsibility you will obtain. This page lists all of the people who have + gone the extra mile and are Committers. If you would like to get involved, + the first step is to join the mailing lists. +

+ +

+ We ask that you please do not send us emails privately asking for support. + We are non-paid volunteers who help out with the project and we do not + necessarily have the time or energy to help people on an individual basis. + Instead, we have setup mailing lists which often contain hundreds of + individuals who will help answer detailed requests for help. The benefit of + using mailing lists over private communication is that it is a shared + resource where others can also learn from common mistakes and as a + community we all grow together. +

+ + +
    +
  • Stefano Mazzocchi (stefano at apache dot org) +
  • +
+
+ + +
    +
  • Andrew C. Oliver (acoliver at apache dot org)
  • +
  • Marc Johnson (mjohnson at apache dot org)
  • +
+
+ +
    +
  • Glen Stampoultzis (gstamp at iprimus dot com dot au)
  • +
  • Nicola Ken Barozzi (barozzi at nicolaken dot com)
  • +
+
+
+ + +
+ diff --git a/src/java/Manifest.mf b/src/java/Manifest.mf new file mode 100755 index 000000000..348f1bdd3 --- /dev/null +++ b/src/java/Manifest.mf @@ -0,0 +1 @@ +Manifest-Version: 1.0 \ No newline at end of file diff --git a/src/java/org/apache/poi/hdf/hdf.xml b/src/java/org/apache/poi/hdf/hdf.xml new file mode 100644 index 000000000..1ed43fa03 --- /dev/null +++ b/src/java/org/apache/poi/hdf/hdf.xml @@ -0,0 +1,295 @@ + + + + HDF Horrible Document File Format + + + + + + + A word docfile consists of a main stream, a summary information stream, + a table stream, a data stream, and 0 or more object streams which contain + private data for POI-FS 2.0 objects embedded within the Word document. + The summary information stream is described in the section immediately + following this one. The object storages contain binary data for embedded + objects. Word has no knowledge of the contents of these storages; + this information is accessed and manipulated though the POI-FS 2.0 APIs. + + +
+ + + Stored at beginning of page 0 of the file. fib.fComplex will be set to zero. + The FIB contains a "magic word" and pointers to the various other parts of + the file,as well as information about the length of the file. + The FIB starts at the beginning of the file. + + + + + text of body, footnotes, headers + Text begins at the position recorded in fib.fcMin. + The text of the file starts at fib.fcMin. fib.fcMin is usually set to the + next 128 byte boundary after the end of the FIB. The text in a Word document + is ASCII text with the following restrictions (ASCII codes given in decimal):\ + + Paragraph ends are stored as a single Carriage Return character (ASCII 13). + No other occurrences of this character sequence are allowed. + Hard line breaks which are not paragraph ends are stored as ASCII 11. Other + line break or word wrap information is not stored. + Breaking hyphens are stored as ASCII 45 (normal hyphen code); Non-required + hyphens are ASCII 31. Non-breaking hyphens are stored as ASCII 30. + Non-breaking spaces are stored as 160. Normal spaces are ASCII 32. + Page breaks and Section marks are ASCII 12 (normal form feed); if there's + an entry in the section table, it's a section mark, otherwise it's a page + break. + Column breaks are stored as ASCII 14. + Tab characters are ASCII 9 (normal). + The field begin mark which delimits the beginning of a field is ASCII 19. + The field end mark which delimits the end of a field is ASCII 21. The field + separator ,which marks the boundary between the preceding field code text + and following field expansion text within a field, is ASCII 20. The field + escape character is the '\' character which also serves as the formula mark. + The cell mark which delimits the end of a cell in a table row is stored as + ASCII 7 and has the fInTable paragraph property set to fTrue + (pap.fInTable == 1). + The row mark which delimits the end of a table row is stored as ASCII 7 + and has the fInTable paragraph property and fTtp paragraph property set + to fTrue (pap.fInTable == 1 && pap.fTtp == 1). + + + + + FKPs for CHPs, PAPs and LVCs + The first FKP begins at a 512-byte boundary after the last byte text written.. + The remaining FKPs are recorded in the 512-byte pages that immediately follow. + The FKPs for CHPs PAPs and LVCs are interleaved. Previous versions of Word + wrote them in contiguous chunks. The hplcfbte's of the three flavors + (CHP, PAP and LVC) are used to find the relevant FKP of the appropriate type. + group of SEPXs + + + + + SEPXs immediately follow the FKPs and are concatenated one after the other. + SEPXs are no longer guaranteed to start on a page boundary if it would span a + boundary if placed immediately after the preceding SEPX. + + +
+ + + The summary information for a Word document is stored in two structured storage + streams, SummaryInformation and DocumentSummaryInformation. Information on the + layout of the SummaryInformation stream can be found in Appendix B of the POI-FS 2 + Programmers Reference. + + + + + Word stores various plcfs and tables with the stream named either "0Table" or + "1Table". Ordinarily a file will contain only one table stream. However, in + some unusual circumstances (e.g. crash during file save) a file might have two + table streams. In that case the bit field fWhichTblStm in the FIB should be used + to determine which table stream to read. If fWhichTblStm is 0, then the FIB refers + to the stream named "0Table", and if fWhichTblStm is 1, then the FIB refers to + the stream name "1Table". + + + + + Undocumented undo / versioning data + + + + + + Undocumented undo / versioning data + + + + + + Undocumented undo / versioning data + + + + + + Undocumented undo / versioning data + + + + + + (style sheet) Written immediately after the previous table. + This is recorded in all Word documents. + + + +
+ + + + + +
+
+ \ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/HSSFLog.java b/src/java/org/apache/poi/hssf/HSSFLog.java new file mode 100644 index 000000000..cfef5c31f --- /dev/null +++ b/src/java/org/apache/poi/hssf/HSSFLog.java @@ -0,0 +1,96 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * HSSFLog.java + * + * Created on December 3, 2001, 2:30 PM + */ +package org.apache.poi.hssf; + +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * Provides logging to HSSF without it having to mess with + * configuration/initialization. + * + * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class HSSFLog + extends POILogFactory +{ + private static HSSFLog _the_instance = null; + + /** + * Create a new instance of HSSFLog + */ + + private HSSFLog() + { + super("hssflog.properties", "HSSF.log"); + } + + public static POILogger getPOILogger(final Class theclass) + { + if (_the_instance == null) + { + _the_instance = new HSSFLog(); + } + return _the_instance.getLogger(theclass); + } +} diff --git a/src/java/org/apache/poi/hssf/dev/BiffViewer.java b/src/java/org/apache/poi/hssf/dev/BiffViewer.java new file mode 100644 index 000000000..b44abf42f --- /dev/null +++ b/src/java/org/apache/poi/hssf/dev/BiffViewer.java @@ -0,0 +1,662 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * BiffViewer.java + * + * Created on November 13, 2001, 9:23 AM + */ +package org.apache.poi.hssf.dev; + +import java.io.InputStream; +import java.io.IOException; +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; + +//import java.io.*; +import java.util.ArrayList; + +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.HexDump; +import org.apache.poi.hssf.record.*; +import org.apache.poi.hssf.model.*; +import org.apache.poi.hssf.usermodel.*; + +/** + * Utillity for reading in BIFF8 records and displaying data from them. + * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Glen Stampoultzis (gstamp at iprimus dot com dot au) + * @see #main + */ + +public class BiffViewer +{ + String filename; + private boolean dump; + + /** + * Creates new BiffViewer + * + * @param args + */ + + public BiffViewer(String [] args) + { + if (args.length > 0) + { + filename = args[ 0 ]; + } + else + { + System.out.println("BIFFVIEWER REQUIRES A FILENAME***"); + } + } + + /** + * Method run + * + * starts up BiffViewer... + */ + + public void run() + { + try + { + POIFSFileSystem fs = + new POIFSFileSystem(new FileInputStream(filename)); + InputStream stream = + fs.createDocumentInputStream("Workbook"); + Record[] records = createRecords(stream, dump); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * Create an array of records from an input stream + * + * @param in the InputStream from which the records will be + * obtained + * @param dump + * + * @return an array of Records created from the InputStream + * + * @exception RecordFormatException on error processing the + * InputStream + */ + + public static Record [] createRecords(InputStream in, boolean dump) + throws RecordFormatException + { + ArrayList records = new ArrayList(); + Record last_record = null; + int loc = 0; + + try + { + long offset = 0; + short rectype = 0; + + do + { + System.out.println("you are at offset " + loc); + rectype = LittleEndian.readShort(in); + loc += 2; + if (rectype != 0) + { + short recsize = LittleEndian.readShort(in); + + loc += 2; + byte[] data = new byte[ ( int ) recsize ]; + + in.read(data); + if ((rectype == WSBoolRecord.sid) && (recsize == 0)) + { + System.out.println(loc); + } + loc += recsize; + offset += 4 + recsize; + if (dump) + { + System.out + .println("fixing to recordize the following"); + System.out.println("rectype = " + + Integer.toHexString(rectype)); + System.out.println("recsize = " + + Integer.toHexString(recsize)); + System.out.println( + "--------------------------------------------"); + if (data.length > 0) + { + HexDump.dump(data, 0, System.out, 0); + } + else + { + System.out.print("**NO RECORD DATA**"); + } + System.out.println(); + System.out.println( + "-END----------------------------------------"); + } + Record[] recs = createRecord(rectype, recsize, + data); // handle MulRK records + + if (recs.length > 1) + { + for (int k = 0; k < recs.length; k++) + { + records.add( + recs[ k ]); // these will be number records + last_record = + recs[ k ]; // do to keep the algorythm homogenous...you can't + } // actually continue a number record anyhow. + } + else + { + Record record = recs[ 0 ]; + + if ((record instanceof UnknownRecord) + && !dump) // if we didn't already dump + { // just cause dump was on and we're hit an unknow + + // record hex dump it! + System.out.println( + "-----UNKNOWN----------------------------------"); + if (data.length > 0) + { + HexDump.dump(data, 0, System.out, 0); + } + else + { + System.out.print("**NO RECORD DATA**"); + } + System.out.println(); + System.out.println( + "-----UNKNOWN----------------------------------"); + } + if (record != null) + { + if (rectype == ContinueRecord.sid) + { + if (last_record == null) + { + throw new RecordFormatException( + "First record is a ContinueRecord??"); + } + if (dump) + { + System.out.println( + "-----PRECONTINUED LAST RECORD WOULD SERIALIZE LIKE:"); + byte[] lr = last_record.serialize(); + + if (lr != null) + { + HexDump.dump(last_record.serialize(), + 0, System.out, 0); + } + System.out.println(); + System.out.println( + "-----PRECONTINUED----------------------------------"); + } + last_record.processContinueRecord(data); + if (dump) + { + System.out.println( + "-----CONTINUED LAST RECORD WOULD SERIALIZE LIKE:"); + HexDump.dump(last_record.serialize(), 0, + System.out, 0); + System.out.println(); + System.out.println( + "-----CONTINUED----------------------------------"); + } + } + else + { + last_record = record; + records.add(record); + } + } + } + } + } + while (rectype != 0); + } + catch (IOException e) + { + throw new RecordFormatException("Error reading bytes"); + } + Record[] retval = new Record[ records.size() ]; + + retval = ( Record [] ) records.toArray(retval); + return retval; + } + + /** + * Essentially a duplicate of RecordFactory. Kept seperate as not to + * screw up non-debug operations. + * + */ + + private static Record [] createRecord(short rectype, short size, + byte [] data) + { + Record retval = null; + Record[] realretval = null; + + // int irectype = rectype; + switch (rectype) + { + + case ChartRecord.sid : + retval = new ChartRecord(rectype, size, data); + break; + + case ChartFormatRecord.sid : + retval = new ChartFormatRecord(rectype, size, data); + break; + + case SeriesRecord.sid : + retval = new SeriesRecord(rectype, size, data); + break; + + case BeginRecord.sid : + retval = new BeginRecord(rectype, size, data); + break; + + case EndRecord.sid : + retval = new EndRecord(rectype, size, data); + break; + + case BOFRecord.sid : + retval = new BOFRecord(rectype, size, data); + break; + + case InterfaceHdrRecord.sid : + retval = new InterfaceHdrRecord(rectype, size, data); + break; + + case MMSRecord.sid : + retval = new MMSRecord(rectype, size, data); + break; + + case InterfaceEndRecord.sid : + retval = new InterfaceEndRecord(rectype, size, data); + break; + + case WriteAccessRecord.sid : + retval = new WriteAccessRecord(rectype, size, data); + break; + + case CodepageRecord.sid : + retval = new CodepageRecord(rectype, size, data); + break; + + case DSFRecord.sid : + retval = new DSFRecord(rectype, size, data); + break; + + case TabIdRecord.sid : + retval = new TabIdRecord(rectype, size, data); + break; + + case FnGroupCountRecord.sid : + retval = new FnGroupCountRecord(rectype, size, data); + break; + + case WindowProtectRecord.sid : + retval = new WindowProtectRecord(rectype, size, data); + break; + + case ProtectRecord.sid : + retval = new ProtectRecord(rectype, size, data); + break; + + case PasswordRecord.sid : + retval = new PasswordRecord(rectype, size, data); + break; + + case ProtectionRev4Record.sid : + retval = new ProtectionRev4Record(rectype, size, data); + break; + + case PasswordRev4Record.sid : + retval = new PasswordRev4Record(rectype, size, data); + break; + + case WindowOneRecord.sid : + retval = new WindowOneRecord(rectype, size, data); + break; + + case BackupRecord.sid : + retval = new BackupRecord(rectype, size, data); + break; + + case HideObjRecord.sid : + retval = new HideObjRecord(rectype, size, data); + break; + + case DateWindow1904Record.sid : + retval = new DateWindow1904Record(rectype, size, data); + break; + + case PrecisionRecord.sid : + retval = new PrecisionRecord(rectype, size, data); + break; + + case RefreshAllRecord.sid : + retval = new RefreshAllRecord(rectype, size, data); + break; + + case BookBoolRecord.sid : + retval = new BookBoolRecord(rectype, size, data); + break; + + case FontRecord.sid : + retval = new FontRecord(rectype, size, data); + break; + + case FormatRecord.sid : + retval = new FormatRecord(rectype, size, data); + break; + + case ExtendedFormatRecord.sid : + retval = new ExtendedFormatRecord(rectype, size, data); + break; + + case StyleRecord.sid : + retval = new StyleRecord(rectype, size, data); + break; + + case UseSelFSRecord.sid : + retval = new UseSelFSRecord(rectype, size, data); + break; + + case BoundSheetRecord.sid : + retval = new BoundSheetRecord(rectype, size, data); + break; + + case CountryRecord.sid : + retval = new CountryRecord(rectype, size, data); + break; + + case SSTRecord.sid : + retval = new SSTRecord(rectype, size, data); + break; + + case ExtSSTRecord.sid : + retval = new ExtSSTRecord(rectype, size, data); + break; + + case EOFRecord.sid : + retval = new EOFRecord(rectype, size, data); + break; + + case IndexRecord.sid : + retval = new IndexRecord(rectype, size, data); + break; + + case CalcModeRecord.sid : + retval = new CalcModeRecord(rectype, size, data); + break; + + case CalcCountRecord.sid : + retval = new CalcCountRecord(rectype, size, data); + break; + + case RefModeRecord.sid : + retval = new RefModeRecord(rectype, size, data); + break; + + case IterationRecord.sid : + retval = new IterationRecord(rectype, size, data); + break; + + case DeltaRecord.sid : + retval = new DeltaRecord(rectype, size, data); + break; + + case SaveRecalcRecord.sid : + retval = new SaveRecalcRecord(rectype, size, data); + break; + + case PrintHeadersRecord.sid : + retval = new PrintHeadersRecord(rectype, size, data); + break; + + case PrintGridlinesRecord.sid : + retval = new PrintGridlinesRecord(rectype, size, data); + break; + + case GridsetRecord.sid : + retval = new GridsetRecord(rectype, size, data); + break; + + case GutsRecord.sid : + retval = new GutsRecord(rectype, size, data); + break; + + case DefaultRowHeightRecord.sid : + retval = new DefaultRowHeightRecord(rectype, size, data); + break; + + case WSBoolRecord.sid : + retval = new WSBoolRecord(rectype, size, data); + break; + + case HeaderRecord.sid : + retval = new HeaderRecord(rectype, size, data); + break; + + case FooterRecord.sid : + retval = new FooterRecord(rectype, size, data); + break; + + case HCenterRecord.sid : + retval = new HCenterRecord(rectype, size, data); + break; + + case VCenterRecord.sid : + retval = new VCenterRecord(rectype, size, data); + break; + + case PrintSetupRecord.sid : + retval = new PrintSetupRecord(rectype, size, data); + break; + + case DefaultColWidthRecord.sid : + retval = new DefaultColWidthRecord(rectype, size, data); + break; + + case DimensionsRecord.sid : + retval = new DimensionsRecord(rectype, size, data); + break; + + case RowRecord.sid : + retval = new RowRecord(rectype, size, data); + break; + + case LabelSSTRecord.sid : + retval = new LabelSSTRecord(rectype, size, data); + break; + + case RKRecord.sid : + retval = new RKRecord(rectype, size, data); + break; + + case NumberRecord.sid : + retval = new NumberRecord(rectype, size, data); + break; + + case DBCellRecord.sid : + retval = new DBCellRecord(rectype, size, data); + break; + + case WindowTwoRecord.sid : + retval = new WindowTwoRecord(rectype, size, data); + break; + + case SelectionRecord.sid : + retval = new SelectionRecord(rectype, size, data); + break; + + case ContinueRecord.sid : + retval = new ContinueRecord(rectype, size, data); + break; + + case LabelRecord.sid : + retval = new LabelRecord(rectype, size, data); + break; + + case MulRKRecord.sid : + retval = new MulRKRecord(rectype, size, data); + break; + + case MulBlankRecord.sid : + retval = new MulBlankRecord(rectype, size, data); + break; + + case BlankRecord.sid : + retval = new BlankRecord(rectype, size, data); + break; + + case BoolErrRecord.sid : + retval = new BoolErrRecord(rectype, size, data); + break; + + case ColumnInfoRecord.sid : + retval = new ColumnInfoRecord(rectype, size, data); + break; + + case MergeCellsRecord.sid : + retval = new MergeCellsRecord(rectype, size, data); + break; + + default : + retval = new UnknownRecord(rectype, size, data); + } + if (realretval == null) + { + realretval = new Record[ 1 ]; + realretval[ 0 ] = retval; + System.out.println("recordid = " + rectype + ", size =" + size); + System.out.println(realretval[ 0 ].toString()); + } + return realretval; + } + + /** + * Method setDump - hex dump out data or not. + * + * + * @param dump + * + */ + + public void setDump(boolean dump) + { + this.dump = dump; + } + + /** + * Method main + * with 1 argument just run straight biffview against given file

+ * with 2 arguments where the second argument is "on" - run biffviewer

+ * with hex dumps of records

+ * + * with 2 arguments where the second argument is "bfd" just run a big fat + * hex dump of the file...don't worry about biffviewing it at all + * + * + * @param args + * + */ + + public static void main(String [] args) + { + try + { + BiffViewer viewer = new BiffViewer(args); + + if ((args.length > 1) && args[ 1 ].equals("on")) + { + viewer.setDump(true); + } + if ((args.length > 1) && args[ 1 ].equals("bfd")) + { + POIFSFileSystem fs = + new POIFSFileSystem(new FileInputStream(args[ 0 ])); + InputStream stream = + fs.createDocumentInputStream("Workbook"); + int size = stream.available(); + byte[] data = new byte[ size ]; + + stream.read(data); + HexDump.dump(data, 0, System.out, 0); + } + else + { + viewer.run(); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } +} diff --git a/src/java/org/apache/poi/hssf/dev/BiffViewer.java.rep b/src/java/org/apache/poi/hssf/dev/BiffViewer.java.rep new file mode 100755 index 000000000..d5b5fd32e --- /dev/null +++ b/src/java/org/apache/poi/hssf/dev/BiffViewer.java.rep @@ -0,0 +1,174 @@ +println +filename +short +stream +Record +equals +length +RKRecord +FileInputStream +InterfaceEndRecord +FooterRecord +toString +BackupRecord +static +RecordFormatException +toArray +ArrayList +SeriesRecord +records +processContinueRecord +read +VCenterRecord +readShort +run +ColumnInfoRecord +Exception +io +SSTRecord +in +printStackTrace +GridsetRecord +if +PrintSetupRecord +null +BlankRecord +add +UnknownRecord +DeltaRecord +CalcCountRecord +HideObjRecord +RefreshAllRecord +void +BookBoolRecord +FileOutputStream +POIFSFileSystem +size +else +int +args +record +true +public +this +try +ExtSSTRecord +hssf +DefaultColWidthRecord +default +filesystem +EndRecord +fs +main +poifs +print +MMSRecord +InputStream +createRecord +ContinueRecord +throw +class +switch +case +PasswordRev4Record +new +util +LabelRecord +while +net +ByteArrayInputStream +break +UseSelFSRecord +RowRecord +import +CalcModeRecord +BiffViewer +HeaderRecord +WindowProtectRecord +PasswordRecord +last_record +HexDump +CodepageRecord +dev +BoundSheetRecord +RefModeRecord +GutsRecord +do +WindowOneRecord +DSFRecord +viewer +data +PrintHeadersRecord +available +System +IOException +LittleEndian +IterationRecord +NumberRecord +StyleRecord +sid +FontRecord +WSBoolRecord +out +long +poi +k +SelectionRecord +PrecisionRecord +usermodel +String +e +EOFRecord +rectype +SaveRecalcRecord +WindowTwoRecord +catch +DimensionsRecord +WriteAccessRecord +loc +package +MulBlankRecord +InterfaceHdrRecord +java +DBCellRecord +realretval +for +private +MergeCellsRecord +sourceforge +BOFRecord +serialize +setDump +retval +TabIdRecord +throws +MulRKRecord +ProtectionRev4Record +createRecords +recsize +DefaultRowHeightRecord +DateWindow1904Record +LabelSSTRecord +ChartFormatRecord +CountryRecord +ChartRecord +ProtectRecord +boolean +ExtendedFormatRecord +PrintGridlinesRecord +FormatRecord +createDocumentInputStream +HCenterRecord +FnGroupCountRecord +BeginRecord +toHexString +offset +IndexRecord +model +return +lr +recs +Integer +byte +dump +instanceof diff --git a/src/java/org/apache/poi/hssf/dev/EFBiffViewer.java b/src/java/org/apache/poi/hssf/dev/EFBiffViewer.java new file mode 100644 index 000000000..6a9391929 --- /dev/null +++ b/src/java/org/apache/poi/hssf/dev/EFBiffViewer.java @@ -0,0 +1,132 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.dev; + +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.IOException; + +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.hssf.eventmodel.*; +import org.apache.poi.hssf.record.Record; + +/** + * + * @author andy + */ + +public class EFBiffViewer +{ + String file; + + /** Creates a new instance of EFBiffViewer */ + + public EFBiffViewer() + { + } + + public void run() + throws IOException + { + FileInputStream fin = new FileInputStream(file); + POIFSFileSystem poifs = new POIFSFileSystem(fin); + InputStream din = poifs.createDocumentInputStream("Workbook"); + HSSFRequest req = new HSSFRequest(); + + req.addListenerForAllRecords(new HSSFListener() + { + public void processRecord(Record rec) + { + System.out.println(rec.toString()); + } + }); + HSSFEventFactory factory = new HSSFEventFactory(); + + factory.processEvents(req, din); + } + + public void setFile(String file) + { + this.file = file; + } + + public static void main(String [] args) + { + if ((args.length == 1) && !args[ 0 ].equals("--help")) + { + try + { + EFBiffViewer viewer = new EFBiffViewer(); + + viewer.setFile(args[ 0 ]); + viewer.run(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + else + { + System.out.println("EFBiffViewer"); + System.out.println( + "Outputs biffview of records based on HSSFEventFactory"); + System.out + .println("usage: java org.apache.poi.hssf.dev.EBBiffViewer " + + "filename"); + } + } +} diff --git a/src/java/org/apache/poi/hssf/dev/EFHSSF.java b/src/java/org/apache/poi/hssf/dev/EFHSSF.java new file mode 100644 index 000000000..78b5be456 --- /dev/null +++ b/src/java/org/apache/poi/hssf/dev/EFHSSF.java @@ -0,0 +1,227 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.dev; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.IOException; + +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.hssf.record.*; +import org.apache.poi.hssf.eventmodel.*; +import org.apache.poi.hssf.usermodel.*; + +/** + * Event Factory version of HSSF test class. + * @author andy + */ + +public class EFHSSF +{ + String infile; + String outfile; + HSSFWorkbook workbook = null; + HSSFSheet cursheet = null; + + /** Creates a new instance of EFHSSF */ + + public EFHSSF() + { + } + + public void setInputFile(String infile) + { + this.infile = infile; + } + + public void setOutputFile(String outfile) + { + this.outfile = outfile; + } + + public void run() + throws IOException + { + FileInputStream fin = new FileInputStream(infile); + POIFSFileSystem poifs = new POIFSFileSystem(fin); + InputStream din = poifs.createDocumentInputStream("Workbook"); + HSSFRequest req = new HSSFRequest(); + + req.addListenerForAllRecords(new EFHSSFListener(this)); + HSSFEventFactory factory = new HSSFEventFactory(); + + factory.processEvents(req, din); + fin.close(); + din.close(); + FileOutputStream fout = new FileOutputStream(outfile); + + workbook.write(fout); + fout.close(); + System.out.println("done."); + } + + public void recordHandler(Record record) + { + HSSFRow row = null; + HSSFCell cell = null; + int sheetnum = -1; + + switch (record.getSid()) + { + + case BOFRecord.sid : + BOFRecord bof = ( BOFRecord ) record; + + if (bof.getType() == bof.TYPE_WORKBOOK) + { + workbook = new HSSFWorkbook(); + } + else if (bof.getType() == bof.TYPE_WORKSHEET) + { + sheetnum++; + cursheet = workbook.getSheetAt(sheetnum); + } + break; + + case BoundSheetRecord.sid : + BoundSheetRecord bsr = ( BoundSheetRecord ) record; + + workbook.createSheet(bsr.getSheetname()); + break; + + case RowRecord.sid : + RowRecord rowrec = ( RowRecord ) record; + + cursheet.createRow(rowrec.getRowNumber()); + break; + + case NumberRecord.sid : + NumberRecord numrec = ( NumberRecord ) record; + + row = cursheet.getRow(numrec.getRow()); + cell = row.createCell(numrec.getColumn(), + HSSFCell.CELL_TYPE_NUMERIC); + cell.setCellValue(numrec.getValue()); + break; + + case SSTRecord.sid : + SSTRecord sstrec = ( SSTRecord ) record; + + for (int k = 0; k < sstrec.getNumUniqueStrings(); k++) + { + workbook.addSSTString(sstrec.getString(k)); + } + break; + + case LabelSSTRecord.sid : + LabelSSTRecord lrec = ( LabelSSTRecord ) record; + + row = cursheet.getRow(lrec.getRow()); + cell = row.createCell(lrec.getColumn(), + HSSFCell.CELL_TYPE_STRING); + cell.setCellValue(workbook.getSSTString(lrec.getSSTIndex())); + break; + } + } + + public static void main(String [] args) + { + if ((args.length < 2) || !args[ 0 ].equals("--help")) + { + try + { + EFHSSF viewer = new EFHSSF(); + + viewer.setInputFile(args[ 0 ]); + viewer.setOutputFile(args[ 1 ]); + viewer.run(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + else + { + System.out.println("EFHSSF"); + System.out.println( + "General testbed for HSSFEventFactory based testing and " + + "Code examples"); + System.out.println("Usage: java org.apache.poi.hssf.dev.EFHSSF " + + "file1 file2"); + System.out.println( + " --will rewrite the file reading with the event api"); + System.out.println("and writing with the standard API"); + } + } +} + +class EFHSSFListener + implements HSSFListener +{ + EFHSSF efhssf; + + public EFHSSFListener(EFHSSF efhssf) + { + this.efhssf = efhssf; + } + + public void processRecord(Record record) + { + efhssf.recordHandler(record); + } +} diff --git a/src/java/org/apache/poi/hssf/dev/EFHSSF.java.rep b/src/java/org/apache/poi/hssf/dev/EFHSSF.java.rep new file mode 100755 index 000000000..a1bde00fa --- /dev/null +++ b/src/java/org/apache/poi/hssf/dev/EFHSSF.java.rep @@ -0,0 +1,116 @@ +cell +println +addSSTString +CELL_TYPE_NUMERIC +write +getString +getSSTString +Record +equals +length +FileInputStream +static +getRow +getSid +sheetnum +run +eventmodel +io +SSTRecord +CELL_TYPE_STRING +printStackTrace +if +null +recordHandler +fin +void +din +FileOutputStream +getType +POIFSFileSystem +getNumUniqueStrings +else +int +args +processEvents +record +HSSFWorkbook +public +createRow +this +rowrec +try +close +getSSTIndex +hssf +filesystem +main +poifs +setInputFile +InputStream +req +switch +class +case +bsr +numrec +new +break +net +setOutputFile +RowRecord +HSSFRow +HSSFRequest +HSSFEventFactory +EFHSSF +import +HSSFCell +TYPE_WORKSHEET +outfile +dev +BoundSheetRecord +setCellValue +viewer +System +createCell +row +efhssf +IOException +infile +NumberRecord +implements +getValue +sid +TYPE_WORKBOOK +cursheet +out +poi +k +createSheet +usermodel +String +getSheetAt +e +processRecord +catch +package +java +for +HSSFSheet +sourceforge +BOFRecord +fout +EFHSSFListener +HSSFListener +throws +bof +factory +LabelSSTRecord +sstrec +addListenerForAllRecords +createDocumentInputStream +workbook +lrec +getSheetname +getRowNumber +getColumn diff --git a/src/java/org/apache/poi/hssf/dev/FormulaViewer.java b/src/java/org/apache/poi/hssf/dev/FormulaViewer.java new file mode 100644 index 000000000..15f363bd1 --- /dev/null +++ b/src/java/org/apache/poi/hssf/dev/FormulaViewer.java @@ -0,0 +1,218 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * FormulaViewer.java - finds formulas in a BIFF8 file and attempts to parse them and + * display info about them. + * + * Created on November 18, 2001, 7:58 AM + */ +package org.apache.poi.hssf.dev; + +import java.io.InputStream; +import java.io.IOException; +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; + +//import java.io.*; +import java.util.List; + +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.HexDump; +import org.apache.poi.hssf.record.*; +import org.apache.poi.hssf.record.formula.*; +import org.apache.poi.hssf.model.*; +import org.apache.poi.hssf.usermodel.*; + +/** + * FormulaViewer - finds formulas in a BIFF8 file and attempts to read them/display + * data from them. Only works if Formulas are enabled in "RecordFactory" + * @author andy + */ + +public class FormulaViewer +{ + private String file; + + /** Creates new FormulaViewer */ + + public FormulaViewer() + { + } + + /** + * Method run + * + * + * @exception Exception + * + */ + + public void run() + throws Exception + { + POIFSFileSystem fs = + new POIFSFileSystem(new FileInputStream(file)); + List records = + RecordFactory + .createRecords(fs.createDocumentInputStream("Workbook")); + + for (int k = 0; k < records.size(); k++) + { + Record record = ( Record ) records.get(k); + + if (record.getSid() == FormulaRecord.sid) + { + parseFormulaRecord(( FormulaRecord ) record); + } + } + } + + /** + * Method parseFormulaRecord + * + * + * @param record + * + */ + + public void parseFormulaRecord(FormulaRecord record) + { + System.out.println("In ParseFormula Record"); + System.out.println("row = " + record.getRow()); + System.out.println("col = " + record.getColumn()); + System.out.println("value = " + record.getValue()); + System.out.println("xf = " + record.getXFIndex()); + System.out.println("number of ptgs = " + + record.getNumberOfExpressionTokens()); + System.out.println("options = " + record.getOptions()); + System.out.println(composeForumla(record)); + } + + public String composeForumla(FormulaRecord record) + { + StringBuffer formula = new StringBuffer("="); + int numptgs = record.getNumberOfExpressionTokens(); + List ptgs = record.getParsedExpression(); + + for (int ptgnum = numptgs - 1; ptgnum > (-1); ptgnum--) + { + Ptg ptg = ( Ptg ) ptgs.get(ptgnum); + OperationPtg optg = ( OperationPtg ) ptg; + int numops = optg.getNumberOfOperands(); + Ptg[] ops = new Ptg[ numops ]; + int opoffset = 1; + + for (int opnum = ops.length - 1; opnum > -1; opnum--) + { + ops[ opnum ] = ( Ptg ) ptgs.get(ptgnum - opoffset); + opoffset++; + } + formula.append(optg.toFormulaString(ops)); + ptgnum -= ops.length; + } + return formula.toString(); + } + + /** + * Method setFile + * + * + * @param file + * + */ + + public void setFile(String file) + { + this.file = file; + } + + /** + * Method main + * + * pass me a filename and I'll try and parse the formulas from it + * + * @param args pass one argument with the filename or --help + * + */ + + public static void main(String args[]) + { + if ((args == null) || (args.length != 1) + || args[ 0 ].equals("--help")) + { + System.out.println( + "FormulaViewer .8 proof that the devil lies in the details (or just in BIFF8 files in general)"); + System.out.println("usage: Give me a big fat file name"); + } + else + { + try + { + FormulaViewer viewer = new FormulaViewer(); + + viewer.setFile(args[ 0 ]); + viewer.run(); + } + catch (Exception e) + { + System.out.println("Whoops!"); + e.printStackTrace(); + } + } + } +} diff --git a/src/java/org/apache/poi/hssf/dev/HSSF.java b/src/java/org/apache/poi/hssf/dev/HSSF.java new file mode 100644 index 000000000..2cae1c9b8 --- /dev/null +++ b/src/java/org/apache/poi/hssf/dev/HSSF.java @@ -0,0 +1,409 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.dev; + +import java.io.InputStream; +import java.io.IOException; +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; + +import java.util.Random; + +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.hssf.record.*; +import org.apache.poi.hssf.model.*; +import org.apache.poi.hssf.usermodel.*; +import org.apache.poi.hssf.util.*; + +/** + * File for HSSF testing/examples + * + * THIS IS NOT THE MAIN HSSF FILE!! This is a util for testing functionality. + * It does contain sample API usage that may be educational to regular API users. + * + * @see #main + * @author Andrew Oliver (acoliver at apache dot org) + */ + +public class HSSF +{ + private String filename = null; + + // private POIFSFileSystem fs = null; + private InputStream stream = null; + private Record[] records = null; + protected HSSFWorkbook hssfworkbook = null; + + /** + * Constructor HSSF - creates an HSSFStream from an InputStream. The HSSFStream + * reads in the records allowing modification. + * + * + * @param filename + * + * @exception IOException + * + */ + + public HSSF(String filename) + throws IOException + { + this.filename = filename; + POIFSFileSystem fs = + new POIFSFileSystem(new FileInputStream(filename)); + + hssfworkbook = new HSSFWorkbook(fs); + + // records = RecordFactory.createRecords(stream); + } + + /** + * Constructor HSSF - given a filename this outputs a sample sheet with just + * a set of rows/cells. + * + * + * @param filename + * @param write + * + * @exception IOException + * + */ + + public HSSF(String filename, boolean write) + throws IOException + { + short rownum = 0; + FileOutputStream out = new FileOutputStream(filename); + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet s = wb.createSheet(); + HSSFRow r = null; + HSSFCell c = null; + HSSFCellStyle cs = wb.createCellStyle(); + HSSFCellStyle cs2 = wb.createCellStyle(); + HSSFCellStyle cs3 = wb.createCellStyle(); + HSSFFont f = wb.createFont(); + HSSFFont f2 = wb.createFont(); + + f.setFontHeightInPoints(( short ) 12); + f.setColor(( short ) 0xA); + f.setBoldweight(f.BOLDWEIGHT_BOLD); + f2.setFontHeightInPoints(( short ) 10); + f2.setColor(( short ) 0xf); + f2.setBoldweight(f2.BOLDWEIGHT_BOLD); + cs.setFont(f); + cs.setDataFormat(HSSFDataFormat.getFormat("($#,##0_);[Red]($#,##0)")); + cs2.setBorderBottom(cs2.BORDER_THIN); + cs2.setFillPattern(( short ) 1); // fill w fg + cs2.setFillForegroundColor(( short ) 0xA); + cs2.setFont(f2); + wb.setSheetName(0, "HSSF Test"); + for (rownum = ( short ) 0; rownum < 300; rownum++) + { + r = s.createRow(rownum); + if ((rownum % 2) == 0) + { + r.setHeight(( short ) 0x249); + } + + // r.setRowNum(( short ) rownum); + for (short cellnum = ( short ) 0; cellnum < 50; cellnum += 2) + { + c = r.createCell(cellnum, HSSFCell.CELL_TYPE_NUMERIC); + c.setCellValue(rownum * 10000 + cellnum + + ((( double ) rownum / 1000) + + (( double ) cellnum / 10000))); + if ((rownum % 2) == 0) + { + c.setCellStyle(cs); + } + c = r.createCell(( short ) (cellnum + 1), + HSSFCell.CELL_TYPE_STRING); + c.setCellValue("TEST"); + s.setColumnWidth(( short ) (cellnum + 1), + ( short ) ((50 * 8) / (( double ) 1 / 20))); + if ((rownum % 2) == 0) + { + c.setCellStyle(cs2); + } + } // 50 characters divided by 1/20th of a point + } + + // draw a thick black border on the row at the bottom using BLANKS + rownum++; + rownum++; + r = s.createRow(rownum); + cs3.setBorderBottom(cs3.BORDER_THICK); + for (short cellnum = ( short ) 0; cellnum < 50; cellnum++) + { + c = r.createCell(cellnum, HSSFCell.CELL_TYPE_BLANK); + + // c.setCellValue(0); + c.setCellStyle(cs3); + } + s.addMergedRegion(new Region(( short ) 0, ( short ) 0, ( short ) 3, + ( short ) 3)); + s.addMergedRegion(new Region(( short ) 100, ( short ) 100, + ( short ) 110, ( short ) 110)); + + // end draw thick black border + // create a sheet, set its title then delete it + s = wb.createSheet(); + wb.setSheetName(1, "DeletedSheet"); + wb.removeSheetAt(1); + + // end deleted sheet + wb.write(out); + out.close(); + } + + /** + * Constructor HSSF - takes in file - attempts to read it then reconstruct it + * + * + * @param infile + * @param outfile + * @param write + * + * @exception IOException + * + */ + + public HSSF(String infile, String outfile, boolean write) + throws IOException + { + this.filename = filename; + POIFSFileSystem fs = + new POIFSFileSystem(new FileInputStream(filename)); + + hssfworkbook = new HSSFWorkbook(fs); + + // HSSFWorkbook book = hssfstream.getWorkbook(); + } + + /** + * Method main + * + * Given 1 argument takes that as the filename, inputs it and dumps the + * cell values/types out to sys.out + * + * given 2 arguments where the second argument is the word "write" and the + * first is the filename - writes out a sample (test) spreadsheet (see + * public HSSF(String filename, boolean write)). + * + * given 2 arguments where the first is an input filename and the second + * an output filename (not write), attempts to fully read in the + * spreadsheet and fully write it out. + * + * given 3 arguments where the first is an input filename and the second an + * output filename (not write) and the third is "modify1", attempts to read in the + * spreadsheet, deletes rows 0-24, 74-99. Changes cell at row 39, col 3 to + * "MODIFIED CELL" then writes it out. Hence this is "modify test 1". If you + * take the output from the write test, you'll have a valid scenario. + * + * @param args + * + */ + + public static void main(String [] args) + { + if (args.length < 2) + { + +/* try + { + HSSF hssf = new HSSF(args[ 0 ]); + + System.out.println("Data dump:\n"); + HSSFWorkbook wb = hssf.hssfworkbook; + + for (int k = 0; k < wb.getNumberOfSheets(); k++) + { + System.out.println("Sheet " + k); + HSSFSheet sheet = wb.getSheetAt(k); + int rows = sheet.getPhysicalNumberOfRows(); + + for (int r = 0; r < rows; r++) + { + HSSFRow row = sheet.getPhysicalRowAt(r); + int cells = row.getPhysicalNumberOfCells(); + + System.out.println("ROW " + row.getRowNum()); + for (int c = 0; c < cells; c++) + { + HSSFCell cell = row.getPhysicalCellAt(c); + String value = null; + + switch (cell.getCellType()) + { + + case HSSFCell.CELL_TYPE_FORMULA : + value = "FORMULA "; + break; + + case HSSFCell.CELL_TYPE_NUMERIC : + value = "NUMERIC value=" + + cell.getNumericCellValue(); + break; + + case HSSFCell.CELL_TYPE_STRING : + value = "STRING value=" + + cell.getStringCellValue(); + break; + + default : + } + System.out.println("CELL col=" + + cell.getCellNum() + + " VALUE=" + value); + } + } + } + } + catch (Exception e) + { + e.printStackTrace(); + }*/ + } + else if (args.length == 2) + { + if (args[ 1 ].toLowerCase().equals("write")) + { + System.out.println("Write mode"); + try + { + long time = System.currentTimeMillis(); + HSSF hssf = new HSSF(args[ 0 ], true); + + System.out + .println("" + (System.currentTimeMillis() - time) + + " ms generation time"); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + else + { + System.out.println("readwrite test"); + try + { + HSSF hssf = new HSSF(args[ 0 ]); + + // HSSFStream hssfstream = hssf.hssfstream; + HSSFWorkbook wb = hssf.hssfworkbook; + FileOutputStream stream = new FileOutputStream(args[ 1 ]); + + // HSSFCell cell = new HSSFCell(); + // cell.setCellNum((short)3); + // cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC); + // cell.setCellValue(-8009.999); + // hssfstream.modifyCell(cell,0,(short)6); + wb.write(stream); + stream.close(); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + } + else if ((args.length == 3) + && args[ 2 ].toLowerCase().equals("modify1")) + { + try // delete row 0-24, row 74 - 99 && change cell 3 on row 39 to string "MODIFIED CELL!!" + { + HSSF hssf = new HSSF(args[ 0 ]); + + // HSSFStream hssfstream = hssf.hssfstream; + HSSFWorkbook wb = hssf.hssfworkbook; + FileOutputStream stream = new FileOutputStream(args[ 1 ]); + HSSFSheet sheet = wb.getSheetAt(0); + + for (int k = 0; k < 25; k++) + { + HSSFRow row = sheet.getRow(k); + + sheet.removeRow(row); + } + for (int k = 74; k < 100; k++) + { + HSSFRow row = sheet.getRow(k); + + sheet.removeRow(row); + } + HSSFRow row = sheet.getRow(39); + HSSFCell cell = row.getCell(( short ) 3); + + cell.setCellType(HSSFCell.CELL_TYPE_STRING); + cell.setCellValue("MODIFIED CELL!!!!!"); + + // HSSFCell cell = new HSSFCell(); + // cell.setCellNum((short)3); + // cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC); + // cell.setCellValue(-8009.999); + // hssfstream.modifyCell(cell,0,(short)6); + wb.write(stream); + stream.close(); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + } +} diff --git a/src/java/org/apache/poi/hssf/eventmodel/HSSFEventFactory.java b/src/java/org/apache/poi/hssf/eventmodel/HSSFEventFactory.java new file mode 100644 index 000000000..b415f3b54 --- /dev/null +++ b/src/java/org/apache/poi/hssf/eventmodel/HSSFEventFactory.java @@ -0,0 +1,186 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.eventmodel; + +import java.io.InputStream; +import java.io.IOException; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.hssf.record.RecordFormatException; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.RecordFactory; +import org.apache.poi.hssf.record.ContinueRecord; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; + +/** + * Low level event based HSSF reader. Pass either a DocumentInputStream to + * process events along with a request object or pass a POIFS POIFSFileSystem to + * processWorkbookEvents along with a request. + * + * This will cause your file to be processed a record at a time. Each record with + * a static id matching one that you have registed in your HSSFRequest will be passed + * to your associated HSSFListener. + * + * @see org.apache.poi.hssf.dev.EFHSSF + * + * @author andy + */ + +public class HSSFEventFactory +{ + + /** Creates a new instance of HSSFEventFactory */ + + public HSSFEventFactory() + { + } + + /** + * Processes a file into essentially record events. + * + * @param request an Instance of HSSFRequest which has your registered listeners + * @param filesystem a POIFS filesystem containing your workbook + */ + + public void processWorkbookEvents(HSSFRequest req, POIFSFileSystem fs) + throws IOException + { + InputStream in = fs.createDocumentInputStream("Workbook"); + + processEvents(req, in); + } + + /** + * Processes a DocumentInputStream into essentially Record events. + * + * @see org.apache.poi.poifs.filesystem.POIFSFileSystem#createDocumentInputStream(String) + * @param request an Instance of HSSFRequest which has your registered listeners + * @param InputStream - a DocumentInputStream obtained from POIFS's POIFSFileSystem object + */ + + public void processEvents(HSSFRequest req, InputStream in) + throws IOException + { + try + { + byte[] sidbytes = new byte[ 2 ]; + int bytesread = in.read(sidbytes); + Record rec = null; + + while (bytesread > 0) + { + short sid = 0; + + sid = LittleEndian.getShort(sidbytes); + if ((rec != null) && (sid != ContinueRecord.sid)) + { + req.processRecord(rec); + } + if (sid != ContinueRecord.sid) + { + short size = LittleEndian.readShort(in); + byte[] data = new byte[ size ]; + + if (data.length > 0) + { + in.read(data); + } + Record[] recs = RecordFactory.createRecord(sid, size, + data); + + if (recs.length > 1) + { // we know that the multiple + for (int k = 0; k < (recs.length - 1); k++) + { // record situations do not + req.processRecord( + recs[ k ]); // contain continue records + } + } + rec = recs[ recs.length - 1 ]; // regardless we'll process + + // the last record as though + // it might be continued + // if there is only one + // records, it will go here too. + } + else + { // we do have a continue record + short size = LittleEndian.readShort(in); + byte[] data = new byte[ size ]; + + if (data.length > 0) + { + in.read(data); + } + rec.processContinueRecord(data); + } + bytesread = in.read(sidbytes); // read next record sid + } + if (rec != null) + { + req.processRecord(rec); + } + } + catch (IOException e) + { + throw new RecordFormatException("Error reading bytes"); + } + + // Record[] retval = new Record[ records.size() ]; + // retval = ( Record [] ) records.toArray(retval); + // return null; + } +} diff --git a/src/java/org/apache/poi/hssf/eventmodel/HSSFListener.java b/src/java/org/apache/poi/hssf/eventmodel/HSSFListener.java new file mode 100644 index 000000000..09ac21c75 --- /dev/null +++ b/src/java/org/apache/poi/hssf/eventmodel/HSSFListener.java @@ -0,0 +1,78 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.eventmodel; + +import org.apache.poi.hssf.record.Record; + +/** + * Interface for use with the HSSFRequest and HSSFEventFactory. Users should create + * a listener supporting this interface and register it with the HSSFRequest (associating + * it with Record SID's). + * + * @see org.apache.poi.hssf.eventmodel.HSSFEventFactory + * @see org.apache.poi.hssf.eventmodel.HSSFRequest + * @author andy + */ + +public interface HSSFListener +{ + + /** + * process an HSSF Record. Called when a record occurs in an HSSF file. + */ + + public void processRecord(Record record); +} diff --git a/src/java/org/apache/poi/hssf/eventmodel/HSSFRequest.java b/src/java/org/apache/poi/hssf/eventmodel/HSSFRequest.java new file mode 100644 index 000000000..d2bd8fda7 --- /dev/null +++ b/src/java/org/apache/poi/hssf/eventmodel/HSSFRequest.java @@ -0,0 +1,161 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.eventmodel; + +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; + +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.RecordFactory; + +/** + * An HSSFRequest object should be constructed registering an instance or multiple + * instances of HSSFListener with each Record.sid you wish to listen for. + * + * @see org.apache.poi.hssf.eventmodel.HSSFEventFactory + * @see org.apache.poi.hssf.eventmodel.HSSFListener + * @see org.apache.poi.hssf.dev.EFHSSF + * @author andy + */ + +public class HSSFRequest +{ + private HashMap records; + + /** Creates a new instance of HSSFRequest */ + + public HSSFRequest() + { + records = + new HashMap(50); // most folks won't listen for too many of these + } + + /** + * add an event listener for a particular record type. The trick is you have to know + * what the records are for or just start with our examples and build on them. Alternatively, + * you CAN call addListenerForAllRecords and you'll recieve ALL record events in one listener, + * but if you like to squeeze every last byte of efficiency out of life you my not like this. + * (its sure as heck what I plan to do) + * + * @see #addListenerForAllRecords(HSSFListener) + * + * @param listener for the event + * @param static identifier for the record type this is the .sid static member on the individual records + * for example req.addListener(myListener, BOFRecord.sid) + */ + + public void addListener(HSSFListener lsnr, short sid) + { + List list = null; + Object obj = records.get(new Short(sid)); + + if (obj != null) + { + list = ( List ) obj; + } + else + { + list = new ArrayList( + 1); // probably most people will use one listener + list.add(lsnr); + records.put(new Short(sid), list); + } + } + + /** + * This is the equivilent of calling addListener(myListener, sid) for EVERY + * record in the org.apache.poi.hssf.record package. This is for lazy + * people like me. You can call this more than once with more than one listener, but + * that seems like a bad thing to do from a practice-perspective unless you have a + * compelling reason to do so (like maybe you send the event two places or log it or + * something?). + * + * @param a single listener to associate with ALL records + */ + + public void addListenerForAllRecords(HSSFListener lsnr) + { + short[] rectypes = RecordFactory.getAllKnownRecordSIDs(); + + for (int k = 0; k < rectypes.length; k++) + { + addListener(lsnr, rectypes[ k ]); + } + } + + /** + * called by HSSFEventFactory, passes the Record to each listener associated with + * a record.sid. + */ + + protected void processRecord(Record rec) + { + Object obj = records.get(new Short(rec.getSid())); + + if (obj != null) + { + List listeners = ( List ) obj; + + for (int k = 0; k < listeners.size(); k++) + { + HSSFListener listener = ( HSSFListener ) listeners.get(k); + + listener.processRecord(rec); + } + } + } +} diff --git a/src/java/org/apache/poi/hssf/model/Sheet.java b/src/java/org/apache/poi/hssf/model/Sheet.java new file mode 100644 index 000000000..d2437c8ef --- /dev/null +++ b/src/java/org/apache/poi/hssf/model/Sheet.java @@ -0,0 +1,1922 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.model; + +import java.io.OutputStream; + +import java.util.List; +import java.util.ArrayList; +import java.util.Iterator; + +import org.apache.poi.hssf.HSSFLog; +import org.apache.poi.hssf + .record.*; // normally I don't do this, buy we literally mean ALL +import org.apache.poi.hssf.record.formula.FormulaUtil; +import org.apache.poi.hssf.record.formula.Ptg; +import org.apache.poi.util.IntList; +import org.apache.poi.util.POILogger; +import org.apache.poi.hssf.record + .aggregates.*; // normally I don't do this, buy we literally mean ALL + +/** + * Low level model implementation of a Sheet (one workbook contains many sheets) + * This file contains the low level binary records starting at the sheets BOF and + * ending with the sheets EOF. Use HSSFSheet for a high level representation. + *

+ * The structures of the highlevel API use references to this to perform most of their + * operations. Its probably unwise to use these low level structures directly unless you + * really know what you're doing. I recommend you read the Microsoft Excel 97 Developer's + * Kit (Microsoft Press) and the documentation at http://sc.openoffice.org/excelfileformat.pdf + * before even attempting to use this. + *

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Glen Stampoultzis (gstamp at iprimus dot com dot au) + * @see org.apache.poi.hssf.model.Workbook + * @see org.apache.poi.hssf.usermodel.HSSFSheet + * @version 1.0-pre + */ + +public class Sheet + extends java.lang.Object +{ + protected ArrayList records = null; + int preoffset = + 0; // offset of the sheet in a new file + int loc = 0; + protected boolean containsLabels = false; + ; + protected int dimsloc = 0; + protected DimensionsRecord dims; + protected DefaultColWidthRecord defaultcolwidth = null; + protected DefaultRowHeightRecord defaultrowheight = null; + protected GridsetRecord gridset = null; + protected MergeCellsRecord merged = null; + protected int mergedloc = 0; + private static POILogger log = + HSSFLog.getPOILogger(Sheet.class); + private ArrayList columnSizes = + null; // holds column info + protected ValueRecordsAggregate cells = null; + protected RowRecordsAggregate rows = null; + private Iterator valueRecIterator = null; + private Iterator rowRecIterator = null; + + /** + * Creates new Sheet with no intialization --useless at this point + * @see #createSheet(Record[],int,int) + */ + + public Sheet() + { + } + + /** + * read support (offset used as starting point for search) for low level + * API. Pass in an array of Record objects, the sheet number (0 based) and + * a record offset (should be the location of the sheets BOF record). A Sheet + * object is constructed and passed back with all of its initialization set + * to the passed in records and references to those records held. This function + * is normally called via Workbook. + * + * @param recs array containing those records in the sheet in sequence (normally obtained from RecordFactory) + * @param sheetnum integer specifying the sheet's number (0,1 or 2 in this release) + * @param offset of the sheet's BOF record + * + * @return Sheet object with all values set to those read from the file + * + * @see org.apache.poi.hssf.model.Workbook + * @see org.apache.poi.hssf.record.Record + */ + + public static Sheet createSheet(List recs, int sheetnum, int offset) + { + log.logFormatted(log.DEBUG, + "Sheet createSheet (existing file) with %", + new Integer(recs.size())); + Sheet retval = new Sheet(); + ArrayList records = new ArrayList(recs.size() / 5); + boolean isfirstcell = true; + boolean isfirstrow = true; + int bofEofNestingLevel = 0; + + for (int k = offset; k < recs.size(); k++) + { + Record rec = ( Record ) recs.get(k); + + if (rec.getSid() == LabelRecord.sid) + { + log.log(log.DEBUG, "Hit label record"); + retval.containsLabels = true; + } + else if (rec.getSid() == BOFRecord.sid) + { + bofEofNestingLevel++; + } + else if ((rec.getSid() == EOFRecord.sid) + && (--bofEofNestingLevel == 0)) + { + log.log(log.DEBUG, "Hit EOF record at "); + records.add(rec); + break; + } + else if (rec.getSid() == DimensionsRecord.sid) + { + retval.dims = ( DimensionsRecord ) rec; + retval.dimsloc = records.size(); + } + else if (rec.getSid() == MergeCellsRecord.sid) + { + retval.merged = ( MergeCellsRecord ) rec; + retval.mergedloc = k - offset; + } + else if (rec.getSid() == ColumnInfoRecord.sid) + { + if (retval.columnSizes == null) + { + retval.columnSizes = new ArrayList(); + } + retval.columnSizes.add(( ColumnInfoRecord ) rec); + } + else if (rec.getSid() == DefaultColWidthRecord.sid) + { + retval.defaultcolwidth = ( DefaultColWidthRecord ) rec; + } + else if (rec.getSid() == DefaultRowHeightRecord.sid) + { + retval.defaultrowheight = ( DefaultRowHeightRecord ) rec; + } + else if (rec.isValue()) + { + if (isfirstcell) + { + retval.cells = new ValueRecordsAggregate(); + rec = retval.cells; + retval.cells.construct(k, recs); + isfirstcell = false; + } + else + { + rec = null; + } + } + else if (rec.getSid() == RowRecord.sid) + { + if (isfirstrow) + { + retval.rows = new RowRecordsAggregate(); + rec = retval.rows; + retval.rows.construct(k, recs); + isfirstrow = false; + } + else + { + rec = null; + } + } + if (rec != null) + { + records.add(rec); + } + } + retval.records = records; + log.log(log.DEBUG, "sheet createSheet (existing file) exited"); + return retval; + } + + /** + * read support (offset = 0) Same as createSheet(Record[] recs, int, int) + * only the record offset is assumed to be 0. + * + * @param recs array containing those records in the sheet in sequence (normally obtained from RecordFactory) + * @param sheetnum integer specifying the sheet's number (0,1 or 2 in this release) + * @return Sheet object + */ + + public static Sheet createSheet(List records, int sheetnum) + { + log.log(log.DEBUG, + "Sheet createSheet (exisiting file) assumed offset 0"); + return createSheet(records, sheetnum, 0); + } + + /** + * Creates a sheet with all the usual records minus values and the "index" + * record (not required). Sets the location pointer to where the first value + * records should go. Use this to create a sheet from "scratch". + * + * @return Sheet object with all values set to defaults + */ + + public static Sheet createSheet() + { + log.log(log.DEBUG, "Sheet createsheet from scratch called"); + Sheet retval = new Sheet(); + ArrayList records = new ArrayList(30); + + records.add(retval.createBOF()); + + // records.add(retval.createIndex()); + records.add(retval.createCalcMode()); + records.add(retval.createCalcCount()); + records.add(retval.createRefMode()); + records.add(retval.createIteration()); + records.add(retval.createDelta()); + records.add(retval.createSaveRecalc()); + records.add(retval.createPrintHeaders()); + records.add(retval.createPrintGridlines()); + retval.gridset = ( GridsetRecord ) retval.createGridset(); + records.add(retval.gridset); + records.add(retval.createGuts()); + retval.defaultrowheight = + ( DefaultRowHeightRecord ) retval.createDefaultRowHeight(); + records.add(retval.defaultrowheight); + records.add(retval.createWSBool()); + records.add(retval.createHeader()); + records.add(retval.createFooter()); + records.add(retval.createHCenter()); + records.add(retval.createVCenter()); + records.add(retval.createPrintSetup()); + retval.defaultcolwidth = + ( DefaultColWidthRecord ) retval.createDefaultColWidth(); + records.add(retval.defaultcolwidth); + retval.dims = ( DimensionsRecord ) retval.createDimensions(); + retval.dimsloc = 19; + records.add(retval.dims); + records.add(retval.createWindowTwo()); + retval.setLoc(records.size() - 1); + records.add(retval.createSelection()); + records.add(retval.createEOF()); + retval.records = records; + log.log(log.DEBUG, "Sheet createsheet from scratch exit"); + return retval; + } + + private void checkCells() + { + if (cells == null) + { + cells = new ValueRecordsAggregate(); + records.add(getDimsLoc() + 1, cells); + } + } + + private void checkRows() + { + if (rows == null) + { + rows = new RowRecordsAggregate(); + records.add(getDimsLoc() + 1, rows); + } + } + + public int addMergedRegion(short rowFrom, short colFrom, short rowTo, + short colTo) + { + if (merged == null) + { + merged = ( MergeCellsRecord ) createMergedCells(); + mergedloc = records.size() - 1; + records.add(records.size() - 1, merged); + } + return merged.addArea(rowFrom, colFrom, rowTo, colTo); + } + + public void removeMergedRegion(int index) + { + merged.removeAreaAt(index); + if (merged.getNumAreas() == 0) + { + merged = null; + records.remove(mergedloc); + mergedloc = 0; + } + } + + public MergeCellsRecord.MergedRegion getMergedRegionAt(int index) + { + return merged.getAreaAt(index); + } + + public int getNumMergedRegions() + { + return merged.getNumAreas(); + } + + /** + * This is basically a kludge to deal with the now obsolete Label records. If + * you have to read in a sheet that contains Label records, be aware that the rest + * of the API doesn't deal with them, the low level structure only provides read-only + * semi-immutable structures (the sets are there for interface conformance with NO + * impelmentation). In short, you need to call this function passing it a reference + * to the Workbook object. All labels will be converted to LabelSST records and their + * contained strings will be written to the Shared String tabel (SSTRecord) within + * the Workbook. + * + * @param wb sheet's matching low level Workbook structure containing the SSTRecord. + * @see org.apache.poi.hssf.record.LabelRecord + * @see org.apache.poi.hssf.record.LabelSSTRecord + * @see org.apache.poi.hssf.record.SSTRecord + */ + + public void convertLabelRecords(Workbook wb) + { + log.log(log.DEBUG, "convertLabelRecords called"); + if (containsLabels) + { + for (int k = 0; k < records.size(); k++) + { + Record rec = ( Record ) records.get(k); + + if (rec.getSid() == LabelRecord.sid) + { + LabelRecord oldrec = ( LabelRecord ) rec; + + records.remove(k); + LabelSSTRecord newrec = new LabelSSTRecord(); + int stringid = + wb.addSSTString(oldrec.getValue()); + + newrec.setRow(oldrec.getRow()); + newrec.setColumn(oldrec.getColumn()); + newrec.setXFIndex(oldrec.getXFIndex()); + newrec.setSSTIndex(stringid); + records.add(k, newrec); + } + } + } + log.log(log.DEBUG, "convertLabelRecords exit"); + } + + /** + * Returns the number of low level binary records in this sheet. This adjusts things for the so called + * AgregateRecords. + * + * @see org.apache.poi.hssf.record.Record + */ + + public int getNumRecords() + { + checkCells(); + checkRows(); + log.log(log.DEBUG, "Sheet.getNumRecords"); + log.logFormatted(log.DEBUG, "returning % + % + % - 2 = %", new int[] + { + records.size(), cells.getPhysicalNumberOfCells(), + rows.getPhysicalNumberOfRows(), + records.size() + cells.getPhysicalNumberOfCells() + + rows.getPhysicalNumberOfRows() - 2 + }); + return records.size() + cells.getPhysicalNumberOfCells() + + rows.getPhysicalNumberOfRows() - 2; + } + + /** + * Per an earlier reported bug in working with Andy Khan's excel read library. This + * sets the values in the sheet's DimensionsRecord object to be correct. Excel doesn't + * really care, but we want to play nice with other libraries. + * + * @see org.apache.poi.hssf.record.DimensionsRecord + */ + + public void setDimensions(short firstrow, short firstcol, short lastrow, + short lastcol) + { + log.log(log.DEBUG, "Sheet.setDimensions"); + log.log(log.DEBUG, + (new StringBuffer("firstrow")).append(firstrow) + .append("firstcol").append(firstcol).append("lastrow") + .append(lastrow).append("lastcol").append(lastcol) + .toString()); + dims.setFirstCol(firstcol); + dims.setFirstRow(firstrow); + dims.setLastCol(lastcol); + dims.setLastRow(lastrow); + log.log(log.DEBUG, "Sheet.setDimensions exiting"); + } + + /** + * set the locator for where we should look for the next value record. The + * algorythm will actually start here and find the correct location so you + * can set this to 0 and watch performance go down the tubes but it will work. + * After a value is set this is automatically advanced. Its also set by the + * create method. So you probably shouldn't mess with this unless you have + * a compelling reason why or the help for the method you're calling says so. + * Check the other methods for whether they care about + * the loc pointer. Many of the "modify" and "remove" methods re-initialize this + * to "dimsloc" which is the location of the Dimensions Record and presumably the + * start of the value section (at or around 19 dec). + * + * @param loc the record number to start at + * + */ + + public void setLoc(int loc) + { + valueRecIterator = null; + log.log(log.DEBUG, "sheet.setLoc(): " + loc); + this.loc = loc; + } + + /** + * Returns the location pointer to the first record to look for when adding rows/values + * + */ + + public int getLoc() + { + log.log(log.DEBUG, "sheet.getLoc():" + loc); + return loc; + } + + /** + * Set the preoffset when using DBCELL records (currently unused) - this is + * the position of this sheet within the whole file. + * + * @param offset the offset of the sheet's BOF within the file. + */ + + public void setPreOffset(int offset) + { + this.preoffset = offset; + } + + /** + * get the preoffset when using DBCELL records (currently unused) - this is + * the position of this sheet within the whole file. + * + * @return offset the offset of the sheet's BOF within the file. + */ + + public int getPreOffset() + { + return preoffset; + } + + /** + * Serializes all records in the sheet into one big byte array. Use this to write + * the sheet out. + * + * @return byte[] array containing the binary representation of the records in this sheet + * + */ + + public byte [] serialize() + { + log.log(log.DEBUG, "Sheet.serialize"); + + // addDBCellRecords(); + byte[] retval = null; + + // ArrayList bytes = new ArrayList(4096); + int arraysize = getSize(); + 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; + // log.debug((new StringBuffer("arraysize=")).append(arraysize) + // .toString()); + // } + retval = new byte[ arraysize ]; + for (int k = 0; k < records.size(); k++) + { + + // byte[] rec = (( byte [] ) bytes.get(k)); + // System.arraycopy(rec, 0, retval, pos, rec.length); + pos += (( Record ) records.get(k)).serialize(pos, + retval); // rec.length; + } + log.log(log.DEBUG, "Sheet.serialize returning " + retval); + return retval; + } + + /** + * Serializes all records in the sheet into one big byte array. Use this to write + * the sheet out. + * + * @param offset to begin write at + * @param byte[] array containing the binary representation of the records in this sheet + * + */ + + public int serialize(int offset, byte [] data) + { + log.log(log.DEBUG, "Sheet.serialize using offsets"); + + // addDBCellRecords(); + // ArrayList bytes = new ArrayList(4096); + 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; + // log.debug((new StringBuffer("arraysize=")).append(arraysize) + // .toString()); + // } + 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; + } + log.log(log.DEBUG, "Sheet.serialize returning "); + return pos; + } + + /** + * Create a row record. (does not add it to the records contained in this sheet) + * + * @param row number + * @return RowRecord created for the passed in row number + * @see org.apache.poi.hssf.record.RowRecord + */ + + public RowRecord createRow(int row) + { + log.log(log.DEBUG, "create row number " + row); + RowRecord rowrec = new RowRecord(); + + rowrec.setRowNumber(( short ) row); + rowrec.setHeight(( short ) 0xff); + rowrec.setOptimize(( short ) 0x0); + rowrec.setOptionFlags(( short ) 0x0); + rowrec.setXFIndex(( short ) 0x0); + return rowrec; + } + + /** + * Create a LABELSST Record (does not add it to the records contained in this sheet) + * + * @param row the row the LabelSST is a member of + * @param col the column the LabelSST defines + * @param index the index of the string within the SST (use workbook addSSTString method) + * @return LabelSSTRecord newly created containing your SST Index, row,col. + * @see org.apache.poi.hssf.record.SSTRecord + */ + + public LabelSSTRecord createLabelSST(short row, short col, int index) + { + log.logFormatted(log.DEBUG, "create labelsst row,col,index %,%,%", + new int[] + { + row, col, index + }); + LabelSSTRecord rec = new LabelSSTRecord(); + + rec.setRow(row); + rec.setColumn(col); + rec.setSSTIndex(index); + rec.setXFIndex(( short ) 0x0f); + return rec; + } + + /** + * Create a NUMBER Record (does not add it to the records contained in this sheet) + * + * @param row the row the NumberRecord is a member of + * @param col the column the NumberRecord defines + * @param value for the number record + * + * @return NumberRecord for that row, col containing that value as added to the sheet + */ + + public NumberRecord createNumber(short row, short col, double value) + { + log.logFormatted(log.DEBUG, "create number row,col,value %,%,%", + new double[] + { + row, col, value + }); + NumberRecord rec = new NumberRecord(); + + rec.setRow(( short ) row); + rec.setColumn(col); + rec.setValue(value); + rec.setXFIndex(( short ) 0x0f); + return rec; + } + + /** + * create a BLANK record (does not add it to the records contained in this sheet) + * + * @param row - the row the BlankRecord is a member of + * @param col - the column the BlankRecord is a member of + */ + + public BlankRecord createBlank(short row, short col) + { + log.logFormatted(log.DEBUG, "create blank row,col %,%", new short[] + { + row, col + }); + BlankRecord rec = new BlankRecord(); + + rec.setRow(( short ) row); + rec.setColumn(col); + rec.setXFIndex(( short ) 0x0f); + return rec; + } + + /** + * Attempts to parse the formula into PTGs and create a formula record + * DOES NOT WORK YET + * + * @param row - the row for the formula record + * @param col - the column of the formula record + * @param formula - a String representing the formula. To be parsed to PTGs + * @return bogus/useless formula record + */ + + public FormulaRecord createFormula(short row, short col, String formula) + { + log.logFormatted(log.DEBUG, "create formula row,col,formula %,%,%", + new short[] + { + row, col + }, formula); + FormulaRecord rec = new FormulaRecord(); + + rec.setRow(row); + rec.setColumn(col); + rec.setOptions(( short ) 2); + rec.setValue(0); + rec.setXFIndex(( short ) 0x0f); + Ptg[] ptg = FormulaUtil.parseFormula(formula); + int size = 0; + + for (int k = 0; k < ptg.length; k++) + { + size += ptg[ k ].getSize(); + rec.pushExpressionToken(ptg[ k ]); + } + rec.setExpressionLength(( short ) size); + return rec; + } + + /** + * Adds a value record to the sheet's contained binary records + * (i.e. LabelSSTRecord or NumberRecord). + *

+ * This method is "loc" sensitive. Meaning you need to set LOC to where you + * want it to start searching. If you don't know do this: setLoc(getDimsLoc). + * When adding several rows you can just start at the last one by leaving loc + * at what this sets it to. + * + * @param row the row to add the cell value to + * @param col the cell value record itself. + */ + + public void addValueRecord(short row, CellValueRecordInterface col) + { + checkCells(); + log.logFormatted(log.DEBUG, "add value record row,loc %,%", new int[] + { + row, loc + }); + DimensionsRecord d = ( DimensionsRecord ) records.get(getDimsLoc()); + + if (col.getColumn() > d.getLastCol()) + { + d.setLastCol(( short ) (col.getColumn() + 1)); + } + if (col.getColumn() < d.getFirstCol()) + { + d.setFirstCol(col.getColumn()); + } + cells.insertCell(col); + + /* + * for (int k = loc; k < records.size(); k++) + * { + * Record rec = ( Record ) records.get(k); + * + * if (rec.getSid() == RowRecord.sid) + * { + * RowRecord rowrec = ( RowRecord ) rec; + * + * if (rowrec.getRowNumber() == col.getRow()) + * { + * records.add(k + 1, col); + * loc = k; + * if (rowrec.getLastCol() <= col.getColumn()) + * { + * rowrec.setLastCol((( short ) (col.getColumn() + 1))); + * } + * break; + * } + * } + * } + */ + } + + /** + * remove a value record from the records array. + * + * This method is not loc sensitive, it resets loc to = dimsloc so no worries. + * + * @param row - the row of the value record you wish to remove + * @param col - a record supporting the CellValueRecordInterface. + * @see org.apache.poi.hssf.record.CellValueRecordInterface + */ + + public void removeValueRecord(short row, CellValueRecordInterface col) + { + checkCells(); + log.logFormatted(log.DEBUG, "remove value record row,dimsloc %,%", + new int[] + { + row, dimsloc + }); + loc = dimsloc; + cells.removeCell(col); + + /* + * for (int k = loc; k < records.size(); k++) + * { + * Record rec = ( Record ) records.get(k); + * + * // checkDimsLoc(rec,k); + * if (rec.isValue()) + * { + * CellValueRecordInterface cell = + * ( CellValueRecordInterface ) rec; + * + * if ((cell.getRow() == col.getRow()) + * && (cell.getColumn() == col.getColumn())) + * { + * records.remove(k); + * break; + * } + * } + * } + */ + } + + /** + * replace a value record from the records array. + * + * This method is not loc sensitive, it resets loc to = dimsloc so no worries. + * + * @param newval - a record supporting the CellValueRecordInterface. this will replace + * the cell value with the same row and column. If there isn't one, one will + * be added. + */ + + public void replaceValueRecord(CellValueRecordInterface newval) + { + checkCells(); + setLoc(dimsloc); + log.log(log.DEBUG, "replaceValueRecord "); + cells.insertCell(newval); + + /* + * CellValueRecordInterface oldval = getNextValueRecord(); + * + * while (oldval != null) + * { + * if (oldval.isEqual(newval)) + * { + * records.set(( short ) (getLoc() - 1), newval); + * return; + * } + * oldval = getNextValueRecord(); + * } + * addValueRecord(newval.getRow(), newval); + * setLoc(dimsloc); + */ + } + + /** + * Adds a row record to the sheet + * + *

+ * This method is "loc" sensitive. Meaning you need to set LOC to where you + * want it to start searching. If you don't know do this: setLoc(getDimsLoc). + * When adding several rows you can just start at the last one by leaving loc + * at what this sets it to. + * + * @param row the row record to be added + * @see #setLoc(int) + */ + + public void addRow(RowRecord row) + { + checkRows(); + log.log(log.DEBUG, "addRow "); + DimensionsRecord d = ( DimensionsRecord ) records.get(getDimsLoc()); + + if (row.getRowNumber() > d.getLastRow()) + { + d.setLastRow(row.getRowNumber() + 1); + } + if (row.getRowNumber() < d.getFirstRow()) + { + d.setFirstRow(row.getRowNumber()); + } + IndexRecord index = null; + + rows.insertRow(row); + + /* + * for (int k = loc; k < records.size(); k++) + * { + * Record rec = ( Record ) records.get(k); + * + * if (rec.getSid() == IndexRecord.sid) + * { + * index = ( IndexRecord ) rec; + * } + * if (rec.getSid() == RowRecord.sid) + * { + * RowRecord rowrec = ( RowRecord ) rec; + * + * if (rowrec.getRowNumber() > row.getRowNumber()) + * { + * records.add(k, row); + * loc = k; + * break; + * } + * } + * if (rec.getSid() == WindowTwoRecord.sid) + * { + * records.add(k, row); + * loc = k; + * break; + * } + * } + * if (index != null) + * { + * if (index.getLastRowAdd1() <= row.getRowNumber()) + * { + * index.setLastRowAdd1(row.getRowNumber() + 1); + * } + * } + */ + log.log(log.DEBUG, "exit addRow"); + } + + /** + * Removes a row record + * + * This method is not loc sensitive, it resets loc to = dimsloc so no worries. + * + * @param the row record to remove + */ + + public void removeRow(RowRecord row) + { + checkRows(); + IndexRecord index = null; + + setLoc(getDimsLoc()); + rows.removeRow(row); + + /* + * for (int k = loc; k < records.size(); k++) + * { + * Record rec = ( Record ) records.get(k); + * + * // checkDimsLoc(rec,k); + * if (rec.getSid() == RowRecord.sid) + * { + * RowRecord rowrec = ( RowRecord ) rec; + * + * if (rowrec.getRowNumber() == row.getRowNumber()) + * { + * records.remove(k); + * break; + * } + * } + * if (rec.getSid() == WindowTwoRecord.sid) + * { + * break; + * } + * } + */ + } + + /** + * get the NEXT value record (from LOC). The first record that is a value record + * (starting at LOC) will be returned. + * + *

+ * This method is "loc" sensitive. Meaning you need to set LOC to where you + * want it to start searching. If you don't know do this: setLoc(getDimsLoc). + * When adding several rows you can just start at the last one by leaving loc + * at what this sets it to. For this method, set loc to dimsloc to start with, + * subsequent calls will return values in (physical) sequence or NULL when you get to the end. + * + * @return CellValueRecordInterface representing the next value record or NULL if there are no more + * @see #setLoc(int) + */ + + public CellValueRecordInterface getNextValueRecord() + { + log.log(log.DEBUG, "getNextValue loc= " + loc); + if (valueRecIterator == null) + { + valueRecIterator = cells.getIterator(); + } + if (!valueRecIterator.hasNext()) + { + return null; + } + return ( CellValueRecordInterface ) valueRecIterator.next(); + + /* + * if (this.getLoc() < records.size()) + * { + * for (int k = getLoc(); k < records.size(); k++) + * { + * Record rec = ( Record ) records.get(k); + * + * this.setLoc(k + 1); + * if (rec instanceof CellValueRecordInterface) + * { + * return ( CellValueRecordInterface ) rec; + * } + * } + * } + * return null; + */ + } + + /** + * get the NEXT RowRecord or CellValueRecord(from LOC). The first record that + * is a Row record or CellValueRecord(starting at LOC) will be returned. + *

+ * This method is "loc" sensitive. Meaning you need to set LOC to where you + * want it to start searching. If you don't know do this: setLoc(getDimsLoc). + * When adding several rows you can just start at the last one by leaving loc + * at what this sets it to. For this method, set loc to dimsloc to start with. + * subsequent calls will return rows in (physical) sequence or NULL when you get to the end. + * + * @return RowRecord representing the next row record or CellValueRecordInterface + * representing the next cellvalue or NULL if there are no more + * @see #setLoc(int) + * + */ + +/* public Record getNextRowOrValue() + { + log.debug((new StringBuffer("getNextRow loc= ")).append(loc) + .toString()); + if (this.getLoc() < records.size()) + { + for (int k = this.getLoc(); k < records.size(); k++) + { + Record rec = ( Record ) records.get(k); + + this.setLoc(k + 1); + if (rec.getSid() == RowRecord.sid) + { + return rec; + } + else if (rec.isValue()) + { + return rec; + } + } + } + return null; + } + */ + + /** + * get the NEXT RowRecord (from LOC). The first record that is a Row record + * (starting at LOC) will be returned. + *

+ * This method is "loc" sensitive. Meaning you need to set LOC to where you + * want it to start searching. If you don't know do this: setLoc(getDimsLoc). + * When adding several rows you can just start at the last one by leaving loc + * at what this sets it to. For this method, set loc to dimsloc to start with. + * subsequent calls will return rows in (physical) sequence or NULL when you get to the end. + * + * @return RowRecord representing the next row record or NULL if there are no more + * @see #setLoc(int) + * + */ + + public RowRecord getNextRow() + { + log.log(log.DEBUG, "getNextRow loc= " + loc); + if (rowRecIterator == null) + { + rowRecIterator = rows.getIterator(); + } + if (!rowRecIterator.hasNext()) + { + return null; + } + return ( RowRecord ) rowRecIterator.next(); + +/* if (this.getLoc() < records.size()) + { + for (int k = this.getLoc(); k < records.size(); k++) + { + Record rec = ( Record ) records.get(k); + + this.setLoc(k + 1); + if (rec.getSid() == RowRecord.sid) + { + return ( RowRecord ) rec; + } + } + }*/ + } + + /** + * get the NEXT (from LOC) RowRecord where rownumber matches the given rownum. + * The first record that is a Row record (starting at LOC) that has the + * same rownum as the given rownum will be returned. + *

+ * This method is "loc" sensitive. Meaning you need to set LOC to where you + * want it to start searching. If you don't know do this: setLoc(getDimsLoc). + * When adding several rows you can just start at the last one by leaving loc + * at what this sets it to. For this method, set loc to dimsloc to start with. + * subsequent calls will return rows in (physical) sequence or NULL when you get to the end. + * + * @param row number - which row to return (careful with LOC) + * @return RowRecord representing the next row record or NULL if there are no more + * @see #setLoc(int) + * + */ + + public RowRecord getRow(short rownum) + { + log.log(log.DEBUG, "getNextRow loc= " + loc); + return rows.getRow(rownum); + + /* + * if (this.getLoc() < records.size()) + * { + * for (int k = this.getLoc(); k < records.size(); k++) + * { + * Record rec = ( Record ) records.get(k); + * + * this.setLoc(k + 1); + * if (rec.getSid() == RowRecord.sid) + * { + * if ((( RowRecord ) rec).getRowNumber() == rownum) + * { + * return ( RowRecord ) rec; + * } + * } + * } + * } + */ + + // return null; + } + + /** + * Not currently used method to calculate and add dbcell records + * + */ + + public void addDBCellRecords() + { + int offset = 0; + int recnum = 0; + int rownum = 0; + int lastrow = 0; + long lastrowoffset = 0; + IndexRecord index = null; + + // ArrayList rowOffsets = new ArrayList(); + IntList rowOffsets = new IntList(); + + for (recnum = 0; recnum < records.size(); recnum++) + { + Record rec = ( Record ) records.get(recnum); + + if (rec.getSid() == IndexRecord.sid) + { + index = ( IndexRecord ) rec; + } + if (rec.getSid() != RowRecord.sid) + { + offset += rec.serialize().length; + } + else + { + break; + } + } + + // First Row Record + for (; recnum < records.size(); recnum++) + { + Record rec = ( Record ) records.get(recnum); + + if (rec.getSid() == RowRecord.sid) + { + rownum++; + rowOffsets.add(offset); + if ((rownum % 32) == 0) + { + + // if this is the last rec in a dbcell block + // find the next row or last value record + for (int rn = recnum; rn < records.size(); rn++) + { + rec = ( Record ) records.get(rn); + if ((!rec.isInValueSection()) + || (rec.getSid() == RowRecord.sid)) + { + + // here is the next row or last value record + records.add(rn, + createDBCell(offset, rowOffsets, + index)); + recnum = rn; + break; + } + } + } + else + { + } + } + if (!rec.isInValueSection()) + { + records.add(recnum, createDBCell(offset, rowOffsets, index)); + break; + } + offset += rec.serialize().length; + } + } + + /** not currently used */ + + private DBCellRecord createDBCell(int offset, IntList rowoffsets, + IndexRecord index) + { + DBCellRecord rec = new DBCellRecord(); + + rec.setRowOffset(offset - rowoffsets.get(0)); + + // test hack + rec.addCellOffset(( short ) 0x0); + + // end test hack + addDbCellToIndex(offset, index); + return rec; + } + + /** not currently used */ + + private void addDbCellToIndex(int offset, IndexRecord index) + { + int numdbcells = index.getNumDbcells() + 1; + + index.addDbcell(offset + preoffset); + + // stupid but whenever we add an offset that causes everything to be shifted down 4 + for (int k = 0; k < numdbcells; k++) + { + int dbval = index.getDbcellAt(k); + + index.setDbcell(k, dbval + 4); + } + } + + /** + * creates the BOF record + * @see org.apache.poi.hssf.record.BOFRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a BOFRecord + */ + + protected Record createBOF() + { + BOFRecord retval = new BOFRecord(); + + retval.setVersion(( short ) 0x600); + retval.setType(( short ) 0x010); + + // retval.setBuild((short)0x10d3); + retval.setBuild(( short ) 0x0dbb); + retval.setBuildYear(( short ) 1996); + retval.setHistoryBitMask(0xc1); + retval.setRequiredVersion(0x6); + return retval; + } + + /** + * creates the Index record - not currently used + * @see org.apache.poi.hssf.record.IndexRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a IndexRecord + */ + + protected Record createIndex() + { + IndexRecord retval = new IndexRecord(); + + retval.setFirstRow(0); // must be set explicitly + retval.setLastRowAdd1(0); + return retval; + } + + /** + * creates the CalcMode record and sets it to 1 (automatic formula caculation) + * @see org.apache.poi.hssf.record.CalcModeRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a CalcModeRecord + */ + + protected Record createCalcMode() + { + CalcModeRecord retval = new CalcModeRecord(); + + retval.setCalcMode(( short ) 1); + return retval; + } + + /** + * creates the CalcCount record and sets it to 0x64 (default number of iterations) + * @see org.apache.poi.hssf.record.CalcCountRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a CalcCountRecord + */ + + protected Record createCalcCount() + { + CalcCountRecord retval = new CalcCountRecord(); + + retval.setIterations(( short ) 0x64); // default 64 iterations + return retval; + } + + /** + * creates the RefMode record and sets it to A1 Mode (default reference mode) + * @see org.apache.poi.hssf.record.RefModeRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a RefModeRecord + */ + + protected Record createRefMode() + { + RefModeRecord retval = new RefModeRecord(); + + retval.setMode(retval.USE_A1_MODE); + return retval; + } + + /** + * creates the Iteration record and sets it to false (don't iteratively calculate formulas) + * @see org.apache.poi.hssf.record.IterationRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a IterationRecord + */ + + protected Record createIteration() + { + IterationRecord retval = new IterationRecord(); + + retval.setIteration(false); + return retval; + } + + /** + * creates the Delta record and sets it to 0.0010 (default accuracy) + * @see org.apache.poi.hssf.record.DeltaRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a DeltaRecord + */ + + protected Record createDelta() + { + DeltaRecord retval = new DeltaRecord(); + + retval.setMaxChange((( double ) 0.0010)); + return retval; + } + + /** + * creates the SaveRecalc record and sets it to true (recalculate before saving) + * @see org.apache.poi.hssf.record.SaveRecalcRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a SaveRecalcRecord + */ + + protected Record createSaveRecalc() + { + SaveRecalcRecord retval = new SaveRecalcRecord(); + + retval.setRecalc(true); + return retval; + } + + /** + * creates the PrintHeaders record and sets it to false (we don't create headers yet so why print them) + * @see org.apache.poi.hssf.record.PrintHeadersRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a PrintHeadersRecord + */ + + protected Record createPrintHeaders() + { + PrintHeadersRecord retval = new PrintHeadersRecord(); + + retval.setPrintHeaders(false); + return retval; + } + + /** + * creates the PrintGridlines record and sets it to false (that makes for ugly sheets). As far as I can + * tell this does the same thing as the GridsetRecord + * + * @see org.apache.poi.hssf.record.PrintGridlinesRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a PrintGridlinesRecord + */ + + protected Record createPrintGridlines() + { + PrintGridlinesRecord retval = new PrintGridlinesRecord(); + + retval.setPrintGridlines(false); + return retval; + } + + /** + * creates the Gridset record and sets it to true (user has mucked with the gridlines) + * @see org.apache.poi.hssf.record.GridsetRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a GridsetRecord + */ + + protected Record createGridset() + { + GridsetRecord retval = new GridsetRecord(); + + retval.setGridset(true); + return retval; + } + + /** + * creates the Guts record and sets leftrow/topcol guttter and rowlevelmax/collevelmax to 0 + * @see org.apache.poi.hssf.record.GutsRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a GutsRecordRecord + */ + + protected Record createGuts() + { + GutsRecord retval = new GutsRecord(); + + retval.setLeftRowGutter(( short ) 0); + retval.setTopColGutter(( short ) 0); + retval.setRowLevelMax(( short ) 0); + retval.setColLevelMax(( short ) 0); + return retval; + } + + /** + * creates the DefaultRowHeight Record and sets its options to 0 and rowheight to 0xff + * @see org.apache.poi.hssf.record.DefaultRowHeightRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a DefaultRowHeightRecord + */ + + protected Record createDefaultRowHeight() + { + DefaultRowHeightRecord retval = new DefaultRowHeightRecord(); + + retval.setOptionFlags(( short ) 0); + retval.setRowHeight(( short ) 0xff); + return retval; + } + + /** + * creates the WSBoolRecord and sets its values to defaults + * @see org.apache.poi.hssf.record.WSBoolRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a WSBoolRecord + */ + + protected Record createWSBool() + { + WSBoolRecord retval = new WSBoolRecord(); + + retval.setWSBool1(( byte ) 0x4); + retval.setWSBool2(( byte ) 0xffffffc1); + return retval; + } + + /** + * creates the Header Record and sets it to nothing/0 length + * @see org.apache.poi.hssf.record.HeaderRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a HeaderRecord + */ + + protected Record createHeader() + { + HeaderRecord retval = new HeaderRecord(); + + retval.setHeaderLength(( byte ) 0); + retval.setHeader(null); + return retval; + } + + /** + * creates the Footer Record and sets it to nothing/0 length + * @see org.apache.poi.hssf.record.FooterRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a FooterRecord + */ + + protected Record createFooter() + { + FooterRecord retval = new FooterRecord(); + + retval.setFooterLength(( byte ) 0); + retval.setFooter(null); + return retval; + } + + /** + * creates the HCenter Record and sets it to false (don't horizontally center) + * @see org.apache.poi.hssf.record.HCenterRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a HCenterRecord + */ + + protected Record createHCenter() + { + HCenterRecord retval = new HCenterRecord(); + + retval.setHCenter(false); + return retval; + } + + /** + * creates the VCenter Record and sets it to false (don't horizontally center) + * @see org.apache.poi.hssf.record.VCenterRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a VCenterRecord + */ + + protected Record createVCenter() + { + VCenterRecord retval = new VCenterRecord(); + + retval.setVCenter(false); + return retval; + } + + /** + * creates the PrintSetup Record and sets it to defaults and marks it invalid + * @see org.apache.poi.hssf.record.PrintSetupRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a PrintSetupRecord + */ + + protected Record createPrintSetup() + { + PrintSetupRecord retval = new PrintSetupRecord(); + + retval.setPaperSize(( short ) 1); + retval.setScale(( short ) 100); + retval.setPageStart(( short ) 1); + retval.setFitWidth(( short ) 1); + retval.setFitHeight(( short ) 1); + retval.setOptions(( short ) 2); + retval.setHResolution(( short ) 300); + retval.setVResolution(( short ) 300); + retval.setHeaderMargin(( double ) 0.5); + retval.setFooterMargin(( double ) 0.5); + retval.setCopies(( short ) 0); + return retval; + } + + /** + * creates the DefaultColWidth Record and sets it to 8 + * @see org.apache.poi.hssf.record.DefaultColWidthRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a DefaultColWidthRecord + */ + + protected Record createDefaultColWidth() + { + DefaultColWidthRecord retval = new DefaultColWidthRecord(); + + retval.setColWidth(( short ) 8); + return retval; + } + + /** + * creates the ColumnInfo Record and sets it to a default column/width + * @see org.apache.poi.hssf.record.ColumnInfoRecord + * @return record containing a ColumnInfoRecord + */ + + protected Record createColInfo() + { + ColumnInfoRecord retval = new ColumnInfoRecord(); + + retval.setColumnWidth(( short ) 0x8); + retval.setOptions(( short ) 6); + retval.setXFIndex(( short ) 0x0f); + return retval; + } + + /** + * get the default column width for the sheet (if the columns do not define their own width) + * @return default column width + */ + + public short getDefaultColumnWidth() + { + return defaultcolwidth.getColWidth(); + } + + /** + * get whether gridlines are printed. + * @return true if printed + */ + + public boolean isGridsPrinted() + { + return !gridset.getGridset(); + } + + /** + * set whether gridlines printed or not. + * @param value True if gridlines printed. + */ + + public void setGridsPrinted(boolean value) + { + gridset.setGridset(!value); + } + + /** + * set the default column width for the sheet (if the columns do not define their own width) + * @param default column width + */ + + public void setDefaultColumnWidth(short dcw) + { + defaultcolwidth.setColWidth(dcw); + } + + /** + * set the default row height for the sheet (if the rows do not define their own height) + * @return default row height + */ + + public void setDefaultRowHeight(short dch) + { + defaultrowheight.setRowHeight(dch); + } + + /** + * get the default row height for the sheet (if the rows do not define their own height) + * @param default row height + */ + + public short getDefaultRowHeight() + { + return defaultrowheight.getRowHeight(); + } + + /** + * get the width of a given column in units of 1/20th of a point width (twips?) + * @param column index + * @see org.apache.poi.hssf.record.DefaultColWidthRecord + * @see org.apache.poi.hssf.record.ColumnInfoRecord + * @see #setColumnWidth(short,short) + * @return column width in units of 1/20th of a point (twips?) + */ + + public short getColumnWidth(short column) + { + short retval = 0; + ColumnInfoRecord ci = null; + int k = 0; + + if (columnSizes != null) + { + for (k = 0; k < columnSizes.size(); k++) + { + ci = ( ColumnInfoRecord ) columnSizes.get(k); + if ((ci.getFirstColumn() >= column) + && (ci.getLastColumn() <= column)) + { + break; + } + ci = null; + } + } + if (ci != null) + { + retval = ci.getColumnWidth(); + } + else + { + retval = defaultcolwidth.getColWidth(); + } + return retval; + } + + /** + * set the width for a given column in 1/20th of a character width units + * @param column - the column number + * @param width (in units of 1/20th of a character width) + */ + + public void setColumnWidth(short column, short width) + { + ColumnInfoRecord ci = null; + int k = 0; + + if (columnSizes == null) + { + columnSizes = new ArrayList(); + } + int cioffset = getDimsLoc() - columnSizes.size(); + + for (k = 0; k < columnSizes.size(); k++) + { + ci = ( ColumnInfoRecord ) columnSizes.get(k); + if ((ci.getFirstColumn() >= column) + && (ci.getLastColumn() <= column)) + { + break; + } + ci = null; + } + if (ci != null) + { + if (ci.getColumnWidth() == width) + { + + // do nothing...the cell's width is equal to what we're setting it to. + } + else if ((ci.getFirstColumn() == column) + && (ci.getLastColumn() == column)) + { // if its only for this cell then + ci.setColumnWidth(width); // who cares, just change the width + } + else if ((ci.getFirstColumn() == column) + || (ci.getLastColumn() == column)) + { + + // okay so the width is different but the first or last column == the column we'return setting + // we'll just divide the info and create a new one + if (ci.getFirstColumn() == column) + { + ci.setFirstColumn(( short ) (column + 1)); + } + else + { + ci.setLastColumn(( short ) (column - 1)); + } + ColumnInfoRecord nci = ( ColumnInfoRecord ) createColInfo(); + + nci.setFirstColumn(column); + nci.setLastColumn(column); + nci.setOptions(ci.getOptions()); + nci.setXFIndex(ci.getXFIndex()); + nci.setColumnWidth(width); + columnSizes.add(k, nci); + records.add((1 + getDimsLoc() - columnSizes.size()) + k, nci); + dimsloc++; + } + } + else + { + + // okay so there ISN'T a column info record that cover's this column so lets create one! + ColumnInfoRecord nci = ( ColumnInfoRecord ) createColInfo(); + + nci.setFirstColumn(column); + nci.setLastColumn(column); + nci.setColumnWidth(width); + columnSizes.add(k, nci); + records.add((1 + getDimsLoc() - columnSizes.size()) + k, nci); + dimsloc++; + } + } + + /** + * creates the Dimensions Record and sets it to bogus values (you should set this yourself + * or let the high level API do it for you) + * @see org.apache.poi.hssf.record.DimensionsRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a DimensionsRecord + */ + + protected Record createDimensions() + { + DimensionsRecord retval = new DimensionsRecord(); + + retval.setFirstCol(( short ) 0); + retval.setLastRow(1); // one more than it is + retval.setFirstRow(0); + retval.setLastCol(( short ) 1); // one more than it is + return retval; + } + + /** + * creates the WindowTwo Record and sets it to:

+ * options = 0x6b6

+ * toprow = 0

+ * leftcol = 0

+ * headercolor = 0x40

+ * pagebreakzoom = 0x0

+ * normalzoom = 0x0

+ * @see org.apache.poi.hssf.record.WindowTwoRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a WindowTwoRecord + */ + + protected Record createWindowTwo() + { + WindowTwoRecord retval = new WindowTwoRecord(); + + retval.setOptions(( short ) 0x6b6); + retval.setTopRow(( short ) 0); + retval.setLeftCol(( short ) 0); + retval.setHeaderColor(0x40); + retval.setPageBreakZoom(( short ) 0); + retval.setNormalZoom(( short ) 0); + return retval; + } + + /** + * Creates the Selection record and sets it to nothing selected + * + * @see org.apache.poi.hssf.record.SelectionRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a SelectionRecord + */ + + protected Record createSelection() + { + SelectionRecord retval = new SelectionRecord(); + + retval.setPane(( byte ) 0x3); + retval.setActiveCellCol(( short ) 0x0); + retval.setActiveCellRow(( short ) 0x0); + retval.setNumRefs(( short ) 0x0); + return retval; + } + + protected Record createMergedCells() + { + MergeCellsRecord retval = new MergeCellsRecord(); + + retval.setNumAreas(( short ) 0); + return retval; + } + + /** + * creates the EOF record + * @see org.apache.poi.hssf.record.EOFRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a EOFRecord + */ + + protected Record createEOF() + { + return new EOFRecord(); + } + + /** + * get the location of the DimensionsRecord (which is the last record before the value section) + * @return location in the array of records of the DimensionsRecord + */ + + public int getDimsLoc() + { + log.log(log.DEBUG, "getDimsLoc dimsloc= " + dimsloc); + return dimsloc; + } + + /** + * in the event the record is a dimensions record, resets both the loc index and dimsloc index + */ + + public void checkDimsLoc(Record rec, int recloc) + { + if (rec.getSid() == DimensionsRecord.sid) + { + loc = recloc; + dimsloc = recloc; + } + } + + public int getSize() + { + int retval = 0; + + for (int k = 0; k < records.size(); k++) + { + retval += (( Record ) records.get(k)).getRecordSize(); + } + return retval; + } + + public List getRecords() + { + return records; + } + + /** + * Gets the gridset record for this sheet. + */ + + public GridsetRecord getGridsetRecord() + { + return gridset; + } + + /** + * Returns the first occurance of a record matching a particular sid. + */ + + public Record findFirstRecordBySid(short sid) + { + for (Iterator iterator = records.iterator(); iterator.hasNext(); ) + { + Record record = ( Record ) iterator.next(); + + if (record.getSid() == sid) + { + return record; + } + } + return null; + } +} diff --git a/src/java/org/apache/poi/hssf/model/Workbook.java b/src/java/org/apache/poi/hssf/model/Workbook.java new file mode 100644 index 000000000..271f1b891 --- /dev/null +++ b/src/java/org/apache/poi/hssf/model/Workbook.java @@ -0,0 +1,1673 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.model; + +import java.io.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Iterator; + +import org.apache.poi.hssf.record.*; +import org.apache.poi.util.POILogger; +import org.apache.poi.hssf.HSSFLog; + +/** + * Workbook + * Low level model implementation of a Workbook. Provides creational methods + * for settings and objects contained in the workbook object. + *

+ * This file contains the low level binary records starting at the workbook's BOF and + * ending with the workbook's EOF. Use HSSFWorkbook for a high level representation. + *

+ * The structures of the highlevel API use references to this to perform most of their + * operations. Its probably unwise to use these low level structures directly unless you + * really know what you're doing. I recommend you read the Microsoft Excel 97 Developer's + * Kit (Microsoft Press) and the documentation at http://sc.openoffice.org/excelfileformat.pdf + * before even attempting to use this. + * + * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Glen Stampoultzis (gstamp at iprimus dot com dot au) + * @see org.apache.poi.hssf.usermodel.HSSFWorkbook + * @version 1.0-pre + */ + +public class Workbook +{ + private static final int DEBUG = POILogger.DEBUG; + + /** + * constant used to set the "codepage" wherever "codepage" is set in records + * (which is duplciated in more than one record) + */ + + private final static short CODEPAGE = ( short ) 0x4b0; + + /** + * this contains the Worksheet record objects + */ + + protected ArrayList records = null; + + /** + * this contains a reference to the SSTRecord so that new stings can be added + * to it. + */ + + protected SSTRecord sst = null; + + /** + * holds the "boundsheet" records (aka bundlesheet) so that they can have their + * reference to their "BOF" marker + */ + + protected ArrayList boundsheets = new ArrayList(); + protected int bspos = + 0; // holds the position of the last bound sheet. + protected int tabpos = + 0; // holds the position of the tabid record + protected int fontpos = + 0; // hold the position of the last font record + protected int numfonts = + 0; // hold the number of font records + protected int xfpos = + 0; // hold the position of the last extended font record + protected int numxfs = + 0; // hold the number of extended format records + private int backuppos = + 0; // holds the position of the backup record. + private static POILogger log = + HSSFLog.getPOILogger(Workbook.class); + + /** + * Creates new Workbook with no intitialization --useless right now + * @see #createWorkbook(Record[]) + */ + + public Workbook() + { + } + + /** + * read support for low level + * API. Pass in an array of Record objects, A Workbook + * object is constructed and passed back with all of its initialization set + * to the passed in records and references to those records held. Unlike Sheet + * workbook does not use an offset (its assumed to be 0) since its first in a file. + * If you need an offset then construct a new array with a 0 offset or write your + * own ;-p. + * + * @param recs an array of Record objects + * @return Workbook object + */ + + public static Workbook createWorkbook(List recs) + { + log.log(DEBUG, "Workbook (readfile) created with reclen=", + new Integer(recs.size())); + Workbook retval = new Workbook(); + ArrayList records = new ArrayList(recs.size() / 3); + + for (int k = 0; k < recs.size(); k++) + { + Record rec = ( Record ) recs.get(k); + + if (rec.getSid() == EOFRecord.sid) + { + records.add(rec); + log.log(DEBUG, "found workbook eof record at " + k); + break; + } + switch (rec.getSid()) + { + + case BoundSheetRecord.sid : + log.log(DEBUG, "found boundsheet record at " + k); + retval.boundsheets.add(rec); + retval.bspos = k; + break; + + case SSTRecord.sid : + log.log(DEBUG, "found sst record at " + k); + retval.sst = ( SSTRecord ) rec; + break; + + case FontRecord.sid : + log.log(DEBUG, "found font record at " + k); + retval.fontpos = k; + retval.numfonts++; + break; + + case ExtendedFormatRecord.sid : + log.log(DEBUG, "found XF record at " + k); + retval.xfpos = k; + retval.numxfs++; + break; + + case TabIdRecord.sid : + log.log(DEBUG, "found tabid record at " + k); + retval.tabpos = k; + break; + + case BackupRecord.sid : + log.log(DEBUG, "found backup record at " + k); + retval.backuppos = k; + break; + + default : + } + records.add(rec); + } + retval.records = records; + log.log(DEBUG, "exit create workbook from existing file function"); + return retval; + } + + /** + * Creates an empty workbook object with three blank sheets and all the empty + * fields. Use this to create a workbook from scratch. + */ + + public static Workbook createWorkbook() + { + log.log(DEBUG, "creating new workbook from scratch"); + Workbook retval = new Workbook(); + ArrayList records = new ArrayList(30); + + records.add(retval.createBOF()); + records.add(retval.createInterfaceHdr()); + records.add(retval.createMMS()); + records.add(retval.createInterfaceEnd()); + records.add(retval.createWriteAccess()); + records.add(retval.createCodepage()); + records.add(retval.createDSF()); + records.add(retval.createTabId()); + retval.tabpos = records.size() - 1; + records.add(retval.createFnGroupCount()); + records.add(retval.createWindowProtect()); + records.add(retval.createProtect()); + records.add(retval.createPassword()); + records.add(retval.createProtectionRev4()); + records.add(retval.createPasswordRev4()); + records.add(retval.createWindowOne()); + records.add(retval.createBackup()); + retval.backuppos = records.size() - 1; + records.add(retval.createHideObj()); + records.add(retval.createDateWindow1904()); + records.add(retval.createPrecision()); + records.add(retval.createRefreshAll()); + records.add(retval.createBookBool()); + records.add(retval.createFont()); + records.add(retval.createFont()); + records.add(retval.createFont()); + records.add(retval.createFont()); + retval.fontpos = records.size() - 1; // last font record postion + retval.numfonts = 4; + records.add(retval.createFormat(0)); + records.add(retval.createFormat(1)); + records.add(retval.createFormat(2)); + records.add(retval.createFormat(3)); + records.add(retval.createFormat(4)); + records.add(retval.createFormat(5)); + records.add(retval.createFormat(6)); + records.add(retval.createFormat(7)); + for (int k = 0; k < 21; k++) + { + records.add(retval.createExtendedFormat(k)); + retval.numxfs++; + } + retval.xfpos = records.size() - 1; + for (int k = 0; k < 6; k++) + { + records.add(retval.createStyle(k)); + } + records.add(retval.createUseSelFS()); + for (int k = 0; k < 1; k++) + { // now just do 1 + BoundSheetRecord bsr = + ( BoundSheetRecord ) retval.createBoundSheet(k); + + records.add(bsr); + retval.boundsheets.add(bsr); + retval.bspos = records.size() - 1; + } + records.add(retval.createCountry()); + retval.sst = ( SSTRecord ) retval.createSST(); + records.add(retval.sst); + records.add(retval.createExtendedSST()); + + // TODO + records.add(retval.createEOF()); + retval.records = records; + log.log(DEBUG, "exit create new workbook from scratch"); + return retval; + } + + public int getNumRecords() + { + return records.size(); + } + + /** + * gets the font record at the given index in the font table. Remember + * "There is No Four" (someone at M$ must have gone to Rocky Horror one too + * many times) + * + * @param idx the index to look at (0 or greater but NOT 4) + * @return FontRecord located at the given index + */ + + public FontRecord getFontRecordAt(int idx) + { + int index = idx; + + if (index > 4) + { + index -= 1; // adjust for "There is no 4" + } + if (index > (numfonts - 1)) + { + throw new ArrayIndexOutOfBoundsException( + "There are only " + numfonts + + " font records, you asked for " + idx); + } + FontRecord retval = + ( FontRecord ) records.get((fontpos - (numfonts - 1)) + index); + + return retval; + } + + /** + * creates a new font record and adds it to the "font table". This causes the + * boundsheets to move down one, extended formats to move down (so this function moves + * those pointers as well) + * + * @return FontRecord that was just created + */ + + public FontRecord createNewFont() + { + FontRecord rec = ( FontRecord ) createFont(); + + ++fontpos; + ++bspos; + ++xfpos; + records.add(fontpos, rec); + numfonts++; + return rec; + } + + /** + * gets the number of font records + * + * @param number of font records in the "font table" + */ + + public int getNumberOfFontRecords() + { + return numfonts; + } + + /** + * Sets the BOF for a given sheet + * + * @param sheetnum the number of the sheet to set the positing of the bof for + * @param pos the actual bof position + */ + + public void setSheetBof(int sheetnum, int pos) + { + log.log(DEBUG, "setting bof for sheetnum =", new Integer(sheetnum), + " at pos=", new Integer(pos)); + checkSheets(sheetnum); + (( BoundSheetRecord ) boundsheets.get(sheetnum)) + .setPositionOfBof(pos); + } + + /** + * Returns the position of the backup record. + */ + + public BackupRecord getBackupRecord() + { + return ( BackupRecord ) records.get(backuppos); + } + + /** + * sets the name for a given sheet. If the boundsheet record doesn't exist and + * its only one more than we have, go ahead and create it. If its > 1 more than + * we have, except + * + * @param sheetnum the sheet number (0 based) + * @param sheetname the name for the sheet + */ + + public void setSheetName(int sheetnum, String sheetname) + { + checkSheets(sheetnum); + (( BoundSheetRecord ) boundsheets.get(sheetnum)) + .setSheetname(sheetname); + (( BoundSheetRecord ) boundsheets.get(sheetnum)) + .setSheetnameLength(( byte ) sheetname.length()); + } + + /** + * gets the name for a given sheet. + * + * @param sheetnum the sheet number (0 based) + * @return sheetname the name for the sheet + */ + + public String getSheetName(int sheetnum) + { + return (( BoundSheetRecord ) boundsheets.get(sheetnum)) + .getSheetname(); + } + + /** + * if we're trying to address one more sheet than we have, go ahead and add it! if we're + * trying to address >1 more than we have throw an exception! + */ + + private void checkSheets(int sheetnum) + { + if ((boundsheets.size()) <= sheetnum) + { // if we're short one add another.. + if ((boundsheets.size() + 1) <= sheetnum) + { + throw new RuntimeException("Sheet number out of bounds!"); + } + BoundSheetRecord bsr = + ( BoundSheetRecord ) createBoundSheet(sheetnum); + + records.add(++bspos, bsr); + boundsheets.add(bsr); + fixTabIdRecord(); + } + } + + public void removeSheet(int sheetnum) + { + if (boundsheets.size() > sheetnum) + { + records.remove(bspos - (boundsheets.size() - 1) + sheetnum); + bspos--; + boundsheets.remove(sheetnum); + fixTabIdRecord(); + } + } + + /** + * make the tabid record look like the current situation. + * + */ + + private void fixTabIdRecord() + { + TabIdRecord tir = ( TabIdRecord ) records.get(tabpos); + short[] tia = new short[ boundsheets.size() ]; + + for (short k = 0; k < tia.length; k++) + { + tia[ k ] = k; + } + tir.setTabIdArray(tia); + } + + /** + * returns the number of boundsheet objects contained in this workbook. + * + * @return number of BoundSheet records + */ + + public int getNumSheets() + { + log.log(DEBUG, "getNumSheets=", new Integer(boundsheets.size())); + return boundsheets.size(); + } + + /** + * get the number of ExtendedFormat records contained in this workbook. + * + * @return int count of ExtendedFormat records + */ + + public int getNumExFormats() + { + log.log(DEBUG, "getXF=", new Integer(boundsheets.size())); + return numxfs; + } + + /** + * gets the ExtendedFormatRecord at the given 0-based index + * + * @param index of the Extended format record (0-based) + * @return ExtendedFormatRecord at the given index + */ + + public ExtendedFormatRecord getExFormatAt(int index) + { + int xfptr = xfpos - (numxfs - 1); + + xfptr += index; + ExtendedFormatRecord retval = + ( ExtendedFormatRecord ) records.get(xfptr); + + return retval; + } + + /** + * creates a new Cell-type Extneded Format Record and adds it to the end of + * ExtendedFormatRecords collection + * + * @return ExtendedFormatRecord that was created + */ + + public ExtendedFormatRecord createCellXF() + { + ExtendedFormatRecord xf = createExtendedFormat(); + + ++xfpos; + ++bspos; + records.add(xfpos, xf); + numxfs++; + return xf; + } + + /** + * Adds a string to the SST table and returns its index (if its a duplicate + * just returns its index and update the counts) + * + * @param string the string to be added to the SSTRecord + * @param use16bits whether to use utf 16 or false for compressed unicode + * @return index of the string within the SSTRecord + */ + + public int addSSTString(String string, boolean use16bits) + { + log.log(DEBUG, "insert to sst string='", string, "' and use16bits= ", + new Boolean(use16bits)); + if (sst == null) + { + insertSST(); + } + return sst.addString(string, use16bits); + } + + /** + * Adds a string to the SST table and returns its index (if its a duplicate + * just returns its index and update the counts) ASSUMES compressed unicode + * (meaning 8bit) + * + * @param string the string to be added to the SSTRecord + * + * @return index of the string within the SSTRecord + */ + + public int addSSTString(String string) + { + return addSSTString(string, false); + } + + /** + * given an index into the SST table, this function returns the corresponding String value + * @return String containing the SST String + */ + + public String getSSTString(int str) + { + if (sst == null) + { + insertSST(); + } + String retval = sst.getString(str); + + log.log(DEBUG, "Returning SST for index=", new Integer(str), + " String= ", retval); + return retval; + } + + /** + * use this function to add a Shared String Table to an existing sheet (say + * generated by a different java api) without an sst.... + * @see #createSST() + * @see org.apache.poi.hssf.record.SSTRecord + */ + + public void insertSST() + { + log.log(DEBUG, "creating new SST via insertSST!"); + sst = ( SSTRecord ) createSST(); + records.add(records.size() - 1, createExtendedSST()); + records.add(records.size() - 2, sst); + } + + /** + * Serializes all records int the worksheet section into a big byte array. Use + * this to write the Workbook out. + * + * @return byte array containing the HSSF-only portions of the POIFS file. + */ + + public byte [] serialize() + { + log.log(DEBUG, "Serializing Workbook!"); + byte[] retval = null; + + // ArrayList bytes = new ArrayList(records.size()); + int arraysize = getSize(); + 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; + // } + retval = new byte[ arraysize ]; + for (int k = 0; k < records.size(); k++) + { + + // byte[] rec = (( byte [] ) bytes.get(k)); + // System.arraycopy(rec, 0, retval, pos, rec.length); + pos += (( Record ) records.get(k)).serialize(pos, + retval); // rec.length; + } + log.log(DEBUG, "Exiting serialize workbook"); + return retval; + } + + /** + * Serializes all records int the worksheet section into a big byte array. Use + * this to write the Workbook out. + * @param offset of the data to be written + * @param data array of bytes to write this to + */ + + public int serialize(int offset, byte [] data) + { + 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; + } + log.log(DEBUG, "Exiting serialize workbook"); + return pos; + } + + public int getSize() + { + int retval = 0; + + for (int k = 0; k < records.size(); k++) + { + retval += (( Record ) records.get(k)).getRecordSize(); + } + return retval; + } + + /** + * creates the BOF record + * @see org.apache.poi.hssf.record.BOFRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a BOFRecord + */ + + protected Record createBOF() + { + BOFRecord retval = new BOFRecord(); + + retval.setVersion(( short ) 0x600); + retval.setType(( short ) 5); + retval.setBuild(( short ) 0x10d3); + +// retval.setBuild((short)0x0dbb); + retval.setBuildYear(( short ) 1996); + retval.setHistoryBitMask(0x41); // was c1 before verify + retval.setRequiredVersion(0x6); + return retval; + } + + /** + * creates the InterfaceHdr record + * @see org.apache.poi.hssf.record.InterfaceHdrRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a InterfaceHdrRecord + */ + + protected Record createInterfaceHdr() + { + InterfaceHdrRecord retval = new InterfaceHdrRecord(); + + retval.setCodepage(CODEPAGE); + return retval; + } + + /** + * creates an MMS record + * @see org.apache.poi.hssf.record.MMSRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a MMSRecord + */ + + protected Record createMMS() + { + MMSRecord retval = new MMSRecord(); + + retval.setAddMenuCount(( byte ) 0); + retval.setDelMenuCount(( byte ) 0); + return retval; + } + + /** + * creates the InterfaceEnd record + * @see org.apache.poi.hssf.record.InterfaceEndRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a InterfaceEndRecord + */ + + protected Record createInterfaceEnd() + { + return new InterfaceEndRecord(); + } + + /** + * creates the WriteAccess record containing the logged in user's name + * @see org.apache.poi.hssf.record.WriteAccessRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a WriteAccessRecord + */ + + protected Record createWriteAccess() + { + WriteAccessRecord retval = new WriteAccessRecord(); + + retval.setUsername(System.getProperty("user.name")); + return retval; + } + + /** + * creates the Codepage record containing the constant stored in CODEPAGE + * @see org.apache.poi.hssf.record.CodepageRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a CodepageRecord + */ + + protected Record createCodepage() + { + CodepageRecord retval = new CodepageRecord(); + + retval.setCodepage(CODEPAGE); + return retval; + } + + /** + * creates the DSF record containing a 0 since HSSF can't even create Dual Stream Files + * @see org.apache.poi.hssf.record.DSFRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a DSFRecord + */ + + protected Record createDSF() + { + DSFRecord retval = new DSFRecord(); + + retval.setDsf( + ( short ) 0); // we don't even support double stream files + return retval; + } + + /** + * creates the TabId record containing an array of 0,1,2. This release of HSSF + * always has the default three sheets, no less, no more. + * @see org.apache.poi.hssf.record.TabIdRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a TabIdRecord + */ + + protected Record createTabId() + { + TabIdRecord retval = new TabIdRecord(); + short[] tabidarray = + { + 0 + }; + + retval.setTabIdArray(tabidarray); + return retval; + } + + /** + * creates the FnGroupCount record containing the Magic number constant of 14. + * @see org.apache.poi.hssf.record.FnGroupCountRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a FnGroupCountRecord + */ + + protected Record createFnGroupCount() + { + FnGroupCountRecord retval = new FnGroupCountRecord(); + + retval.setCount(( short ) 14); + return retval; + } + + /** + * creates the WindowProtect record with protect set to false. + * @see org.apache.poi.hssf.record.WindowProtectRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a WindowProtectRecord + */ + + protected Record createWindowProtect() + { + WindowProtectRecord retval = new WindowProtectRecord(); + + retval.setProtect( + false); // by default even when we support it we won't + return retval; // want it to be protected + } + + /** + * creates the Protect record with protect set to false. + * @see org.apache.poi.hssf.record.ProtectRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a ProtectRecord + */ + + protected Record createProtect() + { + ProtectRecord retval = new ProtectRecord(); + + retval.setProtect( + false); // by default even when we support it we won't + return retval; // want it to be protected + } + + /** + * creates the Password record with password set to 0. + * @see org.apache.poi.hssf.record.PasswordRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a PasswordRecord + */ + + protected Record createPassword() + { + PasswordRecord retval = new PasswordRecord(); + + retval.setPassword(( short ) 0); // no password by default! + return retval; + } + + /** + * creates the ProtectionRev4 record with protect set to false. + * @see org.apache.poi.hssf.record.ProtectionRev4Record + * @see org.apache.poi.hssf.record.Record + * @return record containing a ProtectionRev4Record + */ + + protected Record createProtectionRev4() + { + ProtectionRev4Record retval = new ProtectionRev4Record(); + + retval.setProtect(false); + return retval; + } + + /** + * creates the PasswordRev4 record with password set to 0. + * @see org.apache.poi.hssf.record.PasswordRev4Record + * @see org.apache.poi.hssf.record.Record + * @return record containing a PasswordRev4Record + */ + + protected Record createPasswordRev4() + { + PasswordRev4Record retval = new PasswordRev4Record(); + + retval.setPassword(( short ) 0); // no password by default! + return retval; + } + + /** + * creates the WindowOne record with the following magic values:

+ * horizontal hold - 0x168

+ * vertical hold - 0x10e

+ * width - 0x3a5c

+ * height - 0x23be

+ * options - 0x38

+ * selected tab - 0

+ * displayed tab - 0

+ * num selected tab- 0

+ * tab width ratio - 0x258

+ * @see org.apache.poi.hssf.record.WindowOneRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a WindowOneRecord + */ + + protected Record createWindowOne() + { + WindowOneRecord retval = new WindowOneRecord(); + + retval.setHorizontalHold(( short ) 0x168); + retval.setVerticalHold(( short ) 0x10e); + retval.setWidth(( short ) 0x3a5c); + retval.setHeight(( short ) 0x23be); + retval.setOptions(( short ) 0x38); + retval.setSelectedTab(( short ) 0x0); + retval.setDisplayedTab(( short ) 0x0); + retval.setNumSelectedTabs(( short ) 1); + retval.setTabWidthRatio(( short ) 0x258); + return retval; + } + + /** + * creates the Backup record with backup set to 0. (loose the data, who cares) + * @see org.apache.poi.hssf.record.BackupRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a BackupRecord + */ + + protected Record createBackup() + { + BackupRecord retval = new BackupRecord(); + + retval.setBackup( + ( short ) 0); // by default DONT save backups of files...just loose data + return retval; + } + + /** + * creates the HideObj record with hide object set to 0. (don't hide) + * @see org.apache.poi.hssf.record.HideObjRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a HideObjRecord + */ + + protected Record createHideObj() + { + HideObjRecord retval = new HideObjRecord(); + + retval.setHideObj(( short ) 0); // by default set hide object off + return retval; + } + + /** + * creates the DateWindow1904 record with windowing set to 0. (don't window) + * @see org.apache.poi.hssf.record.DateWindow1904Record + * @see org.apache.poi.hssf.record.Record + * @return record containing a DateWindow1904Record + */ + + protected Record createDateWindow1904() + { + DateWindow1904Record retval = new DateWindow1904Record(); + + retval.setWindowing( + ( short ) 0); // don't EVER use 1904 date windowing...tick tock.. + return retval; + } + + /** + * creates the Precision record with precision set to true. (full precision) + * @see org.apache.poi.hssf.record.PrecisionRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a PrecisionRecord + */ + + protected Record createPrecision() + { + PrecisionRecord retval = new PrecisionRecord(); + + retval.setFullPrecision( + true); // always use real numbers in calculations! + return retval; + } + + /** + * creates the RefreshAll record with refreshAll set to true. (refresh all calcs) + * @see org.apache.poi.hssf.record.RefreshAllRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a RefreshAllRecord + */ + + protected Record createRefreshAll() + { + RefreshAllRecord retval = new RefreshAllRecord(); + + retval.setRefreshAll(false); + return retval; + } + + /** + * creates the BookBool record with saveLinkValues set to 0. (don't save link values) + * @see org.apache.poi.hssf.record.BookBoolRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a BookBoolRecord + */ + + protected Record createBookBool() + { + BookBoolRecord retval = new BookBoolRecord(); + + retval.setSaveLinkValues(( short ) 0); + return retval; + } + + /** + * creates a Font record with the following magic values:

+ * fontheight = 0xc8

+ * attributes = 0x0

+ * color palette index = 0x7fff

+ * bold weight = 0x190

+ * Font Name Length = 5

+ * Font Name = Arial

+ * + * @see org.apache.poi.hssf.record.FontRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a FontRecord + */ + + protected Record createFont() + { + FontRecord retval = new FontRecord(); + + retval.setFontHeight(( short ) 0xc8); + retval.setAttributes(( short ) 0x0); + retval.setColorPaletteIndex(( short ) 0x7fff); + retval.setBoldWeight(( short ) 0x190); + retval.setFontNameLength(( byte ) 5); + retval.setFontName("Arial"); + return retval; + } + + /** + * Creates a FormatRecord object + * @param the number of the format record to create (meaning its position in + * a file as M$ Excel would create it.) + * @return record containing a FormatRecord + * @see org.apache.poi.hssf.record.FormatRecord + * @see org.apache.poi.hssf.record.Record + */ + + protected Record createFormat(int id) + { // we'll need multiple editions for + FormatRecord retval = new FormatRecord(); // the differnt formats + + switch (id) + { + + case 0 : + retval.setIndexCode(( short ) 5); + retval.setFormatStringLength(( byte ) 0x17); + retval.setFormatString("\"$\"#,##0_);\\(\"$\"#,##0\\)"); + break; + + case 1 : + retval.setIndexCode(( short ) 6); + retval.setFormatStringLength(( byte ) 0x1c); + retval.setFormatString("\"$\"#,##0_);[Red]\\(\"$\"#,##0\\)"); + break; + + case 2 : + retval.setIndexCode(( short ) 7); + retval.setFormatStringLength(( byte ) 0x1d); + retval.setFormatString("\"$\"#,##0.00_);\\(\"$\"#,##0.00\\)"); + break; + + case 3 : + retval.setIndexCode(( short ) 8); + retval.setFormatStringLength(( byte ) 0x22); + retval.setFormatString( + "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)"); + break; + + case 4 : + retval.setIndexCode(( short ) 0x2a); + retval.setFormatStringLength(( byte ) 0x32); + retval.setFormatString( + "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)"); + break; + + case 5 : + retval.setIndexCode(( short ) 0x29); + retval.setFormatStringLength(( byte ) 0x29); + retval.setFormatString( + "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)"); + break; + + case 6 : + retval.setIndexCode(( short ) 0x2c); + retval.setFormatStringLength(( byte ) 0x3a); + retval.setFormatString( + "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)"); + break; + + case 7 : + retval.setIndexCode(( short ) 0x2b); + retval.setFormatStringLength(( byte ) 0x31); + retval.setFormatString( + "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)"); + break; + } + return retval; + } + + /** + * Creates an ExtendedFormatRecord object + * @param the number of the extended format record to create (meaning its position in + * a file as MS Excel would create it.) + * + * @return record containing an ExtendedFormatRecord + * @see org.apache.poi.hssf.record.ExtendedFormatRecord + * @see org.apache.poi.hssf.record.Record + */ + + protected Record createExtendedFormat(int id) + { // we'll need multiple editions + ExtendedFormatRecord retval = new ExtendedFormatRecord(); + + switch (id) + { + + case 0 : + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 1 : + retval.setFontIndex(( short ) 1); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff400); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 2 : + retval.setFontIndex(( short ) 1); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff400); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 3 : + retval.setFontIndex(( short ) 2); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff400); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 4 : + retval.setFontIndex(( short ) 2); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff400); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 5 : + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff400); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 6 : + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff400); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 7 : + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff400); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 8 : + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff400); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 9 : + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff400); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 10 : + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff400); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 11 : + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff400); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 12 : + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff400); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 13 : + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff400); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 14 : + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff400); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + // cell records + case 15 : + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0); + retval.setCellOptions(( short ) 0x1); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0x0); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + // style + case 16 : + retval.setFontIndex(( short ) 1); + retval.setFormatIndex(( short ) 0x2b); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff800); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 17 : + retval.setFontIndex(( short ) 1); + retval.setFormatIndex(( short ) 0x29); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff800); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 18 : + retval.setFontIndex(( short ) 1); + retval.setFormatIndex(( short ) 0x2c); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff800); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 19 : + retval.setFontIndex(( short ) 1); + retval.setFormatIndex(( short ) 0x2a); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff800); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 20 : + retval.setFontIndex(( short ) 1); + retval.setFormatIndex(( short ) 0x9); + retval.setCellOptions(( short ) 0xfffffff5); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0xfffff800); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + // unused from this point down + case 21 : + retval.setFontIndex(( short ) 5); + retval.setFormatIndex(( short ) 0x0); + retval.setCellOptions(( short ) 0x1); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0x800); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 22 : + retval.setFontIndex(( short ) 6); + retval.setFormatIndex(( short ) 0x0); + retval.setCellOptions(( short ) 0x1); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0x5c00); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 23 : + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0x31); + retval.setCellOptions(( short ) 0x1); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0x5c00); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 24 : + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0x8); + retval.setCellOptions(( short ) 0x1); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0x5c00); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + + case 25 : + retval.setFontIndex(( short ) 6); + retval.setFormatIndex(( short ) 0x8); + retval.setCellOptions(( short ) 0x1); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0x5c00); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + break; + } + return retval; + } + + /** + * creates an default cell type ExtendedFormatRecord object. + * @return ExtendedFormatRecord with intial defaults (cell-type) + */ + + protected ExtendedFormatRecord createExtendedFormat() + { + ExtendedFormatRecord retval = new ExtendedFormatRecord(); + + retval.setFontIndex(( short ) 0); + retval.setFormatIndex(( short ) 0x0); + retval.setCellOptions(( short ) 0x1); + retval.setAlignmentOptions(( short ) 0x20); + retval.setIndentionOptions(( short ) 0); + retval.setBorderOptions(( short ) 0); + retval.setPaletteOptions(( short ) 0); + retval.setAdtlPaletteOptions(( short ) 0); + retval.setFillPaletteOptions(( short ) 0x20c0); + return retval; + } + + /** + * Creates a StyleRecord object + * @param the number of the style record to create (meaning its position in + * a file as MS Excel would create it. + * @return record containing a StyleRecord + * @see org.apache.poi.hssf.record.StyleRecord + * @see org.apache.poi.hssf.record.Record + */ + + protected Record createStyle(int id) + { // we'll need multiple editions + StyleRecord retval = new StyleRecord(); + + switch (id) + { + + case 0 : + retval.setIndex(( short ) 0xffff8010); + retval.setBuiltin(( byte ) 3); + retval.setOutlineStyleLevel(( byte ) 0xffffffff); + break; + + case 1 : + retval.setIndex(( short ) 0xffff8011); + retval.setBuiltin(( byte ) 6); + retval.setOutlineStyleLevel(( byte ) 0xffffffff); + break; + + case 2 : + retval.setIndex(( short ) 0xffff8012); + retval.setBuiltin(( byte ) 4); + retval.setOutlineStyleLevel(( byte ) 0xffffffff); + break; + + case 3 : + retval.setIndex(( short ) 0xffff8013); + retval.setBuiltin(( byte ) 7); + retval.setOutlineStyleLevel(( byte ) 0xffffffff); + break; + + case 4 : + retval.setIndex(( short ) 0xffff8000); + retval.setBuiltin(( byte ) 0); + retval.setOutlineStyleLevel(( byte ) 0xffffffff); + break; + + case 5 : + retval.setIndex(( short ) 0xffff8014); + retval.setBuiltin(( byte ) 5); + retval.setOutlineStyleLevel(( byte ) 0xffffffff); + break; + } + return retval; + } + + /** + * Creates the UseSelFS object with the use natural language flag set to 0 (false) + * @return record containing a UseSelFSRecord + * @see org.apache.poi.hssf.record.UseSelFSRecord + * @see org.apache.poi.hssf.record.Record + */ + + protected Record createUseSelFS() + { + UseSelFSRecord retval = new UseSelFSRecord(); + + retval.setFlag(( short ) 0); + return retval; + } + + /** + * create a "bound sheet" or "bundlesheet" (depending who you ask) record + * Always sets the sheet's bof to 0. You'll need to set that yourself. + * @param id either sheet 0,1 or 2. + * @return record containing a BoundSheetRecord + * @see org.apache.poi.hssf.record.BoundSheetRecord + * @see org.apache.poi.hssf.record.Record + */ + + protected Record createBoundSheet(int id) + { // 1,2,3 sheets + BoundSheetRecord retval = new BoundSheetRecord(); + + switch (id) + { + + case 0 : + retval.setPositionOfBof(0x0); // should be set later + retval.setOptionFlags(( short ) 0); + retval.setSheetnameLength(( byte ) 0x6); + retval.setCompressedUnicodeFlag(( byte ) 0); + retval.setSheetname("Sheet1"); + break; + + case 1 : + retval.setPositionOfBof(0x0); // should be set later + retval.setOptionFlags(( short ) 0); + retval.setSheetnameLength(( byte ) 0x6); + retval.setCompressedUnicodeFlag(( byte ) 0); + retval.setSheetname("Sheet2"); + break; + + case 2 : + retval.setPositionOfBof(0x0); // should be set later + retval.setOptionFlags(( short ) 0); + retval.setSheetnameLength(( byte ) 0x6); + retval.setCompressedUnicodeFlag(( byte ) 0); + retval.setSheetname("Sheet3"); + break; + } + return retval; + } + + /** + * Creates the Country record with the default and current country set to 1 + * @return record containing a CountryRecord + * @see org.apache.poi.hssf.record.CountryRecord + * @see org.apache.poi.hssf.record.Record + */ + + protected Record createCountry() + { // what a novel idea, create your own! + CountryRecord retval = new CountryRecord(); + + retval.setDefaultCountry(( short ) 1); + retval.setCurrentCountry(( short ) 1); + return retval; + } + + /** + * Creates the SST record with no strings and the unique/num string set to 0 + * @return record containing a SSTRecord + * @see org.apache.poi.hssf.record.SSTRecord + * @see org.apache.poi.hssf.record.Record + */ + + protected Record createSST() + { + return new SSTRecord(); + } + + /** + * Creates the ExtendedSST record with numstrings per bucket set to 0x8. HSSF + * doesn't yet know what to do with this thing, but we create it with nothing in + * it hardly just to make Excel happy and our sheets look like Excel's + * + * @return record containing an ExtSSTRecord + * @see org.apache.poi.hssf.record.ExtSSTRecord + * @see org.apache.poi.hssf.record.Record + */ + + protected Record createExtendedSST() + { + ExtSSTRecord retval = new ExtSSTRecord(); + + retval.setNumStringsPerBucket(( short ) 0x8); + return retval; + } + + /** + * creates the EOF record + * @see org.apache.poi.hssf.record.EOFRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a EOFRecord + */ + + protected Record createEOF() + { + return new EOFRecord(); + } + + /** + * Returns the first occurance of a record matching a particular sid. + */ + + public Record findFirstRecordBySid(short sid) + { + for (Iterator iterator = records.iterator(); iterator.hasNext(); ) + { + Record record = ( Record ) iterator.next(); + + if (record.getSid() == sid) + { + return record; + } + } + return null; + } +} diff --git a/src/java/org/apache/poi/hssf/model/package.html b/src/java/org/apache/poi/hssf/model/package.html new file mode 100755 index 000000000..d952ad30b --- /dev/null +++ b/src/java/org/apache/poi/hssf/model/package.html @@ -0,0 +1,20 @@ + + + + + + +Provides low level API structures for reading, writing, modifying XLS files. + +

Related Documentation

+ +For overviews, tutorials, examples, guides, and tool documentation, please see: + + + +@see net.sourceforge.hssf.usermodel + + + diff --git a/src/java/org/apache/poi/hssf/package.uml b/src/java/org/apache/poi/hssf/package.uml new file mode 100755 index 000000000..e9c4f18f1 --- /dev/null +++ b/src/java/org/apache/poi/hssf/package.uml @@ -0,0 +1,5 @@ +V[1.1:net.sourceforge.poi.hssf] +S[net.sourceforge.poi.hssf:HSSFLog,net.sourceforge.poi.util:POILogFactory]{2:(140,107),(148,329)} +P[net.sourceforge.poi.hssf:HSSFLog]{20,20} +P[net.sourceforge.poi.hssf:HSSFLog]{279,20} +P[net.sourceforge.poi.util:POILogFactory]{11,329} diff --git a/src/java/org/apache/poi/hssf/record/BOFRecord.java b/src/java/org/apache/poi/hssf/record/BOFRecord.java new file mode 100644 index 000000000..d48e37ca4 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/BOFRecord.java @@ -0,0 +1,361 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Beginning Of File

+ * Description: Somewhat of a misnomer, its used for the beginning of a set of + * records that have a particular pupose or subject. + * Used in sheets and workbooks.

+ * REFERENCE: PG 289 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver + * @version 2.0-pre + */ + +public class BOFRecord + extends Record +{ + + /** + * for BIFF8 files the BOF is 0x809. For earlier versions it was 0x09 or 0x(biffversion)09 + */ + + public final static short sid = 0x809; + private short field_1_version; + private short field_2_type; + private short field_3_build; + private short field_4_year; + private int field_5_history; + private int field_6_rversion; + + /** + * suggested default (0x06 - BIFF8) + */ + + public final static short VERSION = 0x06; + + /** + * suggested default 0x10d3 + */ + + public final static short BUILD = 0x10d3; + + /** + * suggested default 0x07CC (1996) + */ + + public final static short BUILD_YEAR = 0x07CC; // 1996 + + /** + * suggested default for a normal sheet (0x41) + */ + + public final static short HISTORY_MASK = 0x41; + public final static short TYPE_WORKBOOK = 0x05; + public final static short TYPE_VB_MODULE = 0x06; + public final static short TYPE_WORKSHEET = 0x10; + public final static short TYPE_CHART = 0x20; + public final static short TYPE_EXCEL_4_MACRO = 0x40; + public final static short TYPE_WORKSPACE_FILE = 0x100; + + /** + * Constructs an empty BOFRecord with no fields set. + */ + + public BOFRecord() + { + } + + /** + * Constructs a BOFRecord and sets its fields appropriately + * + * @param short id must be 0x809 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public BOFRecord(short id, short size, byte [] data) + { + super(id, size, data); + + // fillFields(data,size); + } + + /** + * Constructs a BOFRecord and sets its fields appropriately + * + * @param short id must be 0x809 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset the offset of the record's data + */ + + public BOFRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + + // fillFields(data,size); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A BOF RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_version = LittleEndian.getShort(data, 0 + offset); + field_2_type = LittleEndian.getShort(data, 2 + offset); + field_3_build = LittleEndian.getShort(data, 4 + offset); + field_4_year = LittleEndian.getShort(data, 6 + offset); + field_5_history = LittleEndian.getInt(data, 8 + offset); + field_6_rversion = LittleEndian.getInt(data, 12 + offset); + } + + /** + * Version number - for BIFF8 should be 0x06 + * @see #VERSION + * @param short version to be set + */ + + public void setVersion(short version) + { + field_1_version = version; + } + + /** + * type of object this marks + * @see #TYPE_WORKBOOK + * @see #TYPE_VB_MODULE + * @see #TYPE_WORKSHEET + * @see #TYPE_CHART + * @see #TYPE_EXCEL_4_MACRO + * @see #TYPE_WORKSPACE_FILE + * @param short type to be set + */ + + public void setType(short type) + { + field_2_type = type; + } + + /** + * build that wrote this file + * @see #BUILD + * @param short build number to set + */ + + public void setBuild(short build) + { + field_3_build = build; + } + + /** + * Year of the build that wrote this file + * @see #BUILD_YEAR + * @param short build year to set + */ + + public void setBuildYear(short year) + { + field_4_year = year; + } + + /** + * set the history bit mask (not very useful) + * @see #HISTORY_MASK + * @param int bitmask to set for the history + */ + + public void setHistoryBitMask(int bitmask) + { + field_5_history = bitmask; + } + + /** + * set the minimum version required to read this file + * + * @see #VERSION + * @param int version to set + */ + + public void setRequiredVersion(int version) + { + field_6_rversion = version; + } + + /** + * Version number - for BIFF8 should be 0x06 + * @see #VERSION + * @return short version number of the generator of this file + */ + + public short getVersion() + { + return field_1_version; + } + + /** + * type of object this marks + * @see #TYPE_WORKBOOK + * @see #TYPE_VB_MODULE + * @see #TYPE_WORKSHEET + * @see #TYPE_CHART + * @see #TYPE_EXCEL_4_MACRO + * @see #TYPE_WORKSPACE_FILE + * @return short type of object + */ + + public short getType() + { + return field_2_type; + } + + /** + * get the build that wrote this file + * @see #BUILD + * @return short build number of the generator of this file + */ + + public short getBuild() + { + return field_3_build; + } + + /** + * Year of the build that wrote this file + * @see #BUILD_YEAR + * @return short build year of the generator of this file + */ + + public short getBuildYear() + { + return field_4_year; + } + + /** + * get the history bit mask (not very useful) + * @see #HISTORY_MASK + * @return int bitmask showing the history of the file (who cares!) + */ + + public int getHistoryBitMask() + { + return field_5_history; + } + + /** + * get the minimum version required to read this file + * + * @see #VERSION + * @return int least version that can read the file + */ + + public int getRequiredVersion() + { + return field_6_rversion; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[BOF RECORD]\n"); + buffer.append(" .version = ") + .append(Integer.toHexString(getVersion())).append("\n"); + buffer.append(" .type = ") + .append(Integer.toHexString(getType())).append("\n"); + buffer.append(" .build = ") + .append(Integer.toHexString(getBuild())).append("\n"); + buffer.append(" .buildyear = ").append(getBuildYear()) + .append("\n"); + buffer.append(" .history = ") + .append(Integer.toHexString(getHistoryBitMask())).append("\n"); + buffer.append(" .requiredversion = ") + .append(Integer.toHexString(getRequiredVersion())).append("\n"); + buffer.append("[/BOF RECORD]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x10)); // 16 byte length + LittleEndian.putShort(data, 4 + offset, getVersion()); + LittleEndian.putShort(data, 6 + offset, getType()); + LittleEndian.putShort(data, 8 + offset, getBuild()); + LittleEndian.putShort(data, 10 + offset, getBuildYear()); + LittleEndian.putInt(data, 12 + offset, getHistoryBitMask()); + LittleEndian.putInt(data, 16 + offset, getRequiredVersion()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 20; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/BackupRecord.java b/src/java/org/apache/poi/hssf/record/BackupRecord.java new file mode 100644 index 000000000..42d1e74d2 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/BackupRecord.java @@ -0,0 +1,170 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Backup Record

+ * Description: Boolean specifying whether + * the GUI should store a backup of the file.

+ * REFERENCE: PG 287 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class BackupRecord + extends Record +{ + public final static short sid = 0x40; + private short field_1_backup; // = 0; + + public BackupRecord() + { + } + + /** + * Constructs a BackupRecord and sets its fields appropriately + * + * @param short id must be 0x40 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public BackupRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a BackupRecord and sets its fields appropriately + * + * @param short id must be 0x40 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the start of the record's data + */ + + public BackupRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A BACKUP RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_backup = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set the backup flag (0,1) + * + * @param short backup flag + */ + + public void setBackup(short backup) + { + field_1_backup = backup; + } + + /** + * get the backup flag + * + * @return short 0/1 (off/on) + */ + + public short getBackup() + { + return field_1_backup; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[BACKUP]\n"); + buffer.append(" .backup = ") + .append(Integer.toHexString(getBackup())).append("\n"); + buffer.append("[/BACKUP]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, getBackup()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/BeginRecord.java b/src/java/org/apache/poi/hssf/record/BeginRecord.java new file mode 100644 index 000000000..ff2d82ee5 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/BeginRecord.java @@ -0,0 +1,143 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * The begin record defines the start of a block of records for a (grpahing + * data object. This record is matched with a corresponding EndRecord. + * + * @see EndRecord + * + * @author Glen Stampoultzis (gstamp at iprimus dot com dot au) + */ + +public class BeginRecord + extends Record +{ + public static final short sid = 0x1033; + + public BeginRecord() + { + } + + /** + * Constructs a BeginRecord record and sets its fields appropriately. + * + * @param short id must be 0x1033 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public BeginRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a BeginRecord record and sets its fields appropriately. + * + * @param short id must be 0x1033 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public BeginRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A BEGIN RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[BEGIN]\n"); + buffer.append("[/BEGIN]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0)); // no record info + return getRecordSize(); + } + + public int getRecordSize() + { + return 4; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/BlankRecord.java b/src/java/org/apache/poi/hssf/record/BlankRecord.java new file mode 100644 index 000000000..f01f95c82 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/BlankRecord.java @@ -0,0 +1,347 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * BlankRecord.java + * + * Created on December 10, 2001, 12:07 PM + */ +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Blank cell record

+ * Description: Represents a column in a row with no value but with styling.

+ * REFERENCE: PG 287 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class BlankRecord + extends Record + implements CellValueRecordInterface, Comparable +{ + public final static short sid = 0x201; + private short field_1_row; + private short field_2_col; + private short field_3_xf; + + /** Creates a new instance of BlankRecord */ + + public BlankRecord() + { + } + + /** + * Constructs a BlankRecord and sets its fields appropriately + * + * @param short id must be 0x201 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public BlankRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a BlankRecord and sets its fields appropriately + * + * @param short id must be 0x201 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public BlankRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_row = LittleEndian.getShort(data, 0 + offset); + field_2_col = LittleEndian.getShort(data, 2 + offset); + field_3_xf = LittleEndian.getShort(data, 4 + offset); + } + + /** + * called by constructor, should throw runtime exception in the event of a + * record passed with a differing ID. + * + * @param id alleged id for this record + */ + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A BLANKRECORD!"); + } + } + + /** + * set the row this cell occurs on + * @param row the row this cell occurs within + */ + + public void setRow(short row) + { + field_1_row = row; + } + + /** + * get the row this cell occurs on + * + * @return the row + */ + + public short getRow() + { + return field_1_row; + } + + /** + * get the column this cell defines within the row + * + * @return the column + */ + + public short getColumn() + { + return field_2_col; + } + + /** + * set the index of the extended format record to style this cell with + * + * @param xf - the 0-based index of the extended format + * @see org.apache.poi.hssf.record.ExtendedFormatRecord + */ + + public void setXFIndex(short xf) + { + field_3_xf = xf; + } + + /** + * get the index of the extended format record to style this cell with + * + * @return extended format index + */ + + public short getXFIndex() + { + return field_3_xf; + } + + /** + * set the column this cell defines within the row + * + * @param col the column this cell defines + */ + + public void setColumn(short col) + { + field_2_col = col; + } + + public boolean isBefore(CellValueRecordInterface i) + { + if (this.getRow() > i.getRow()) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() > i.getColumn())) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())) + { + return false; + } + return true; + } + + public boolean isAfter(CellValueRecordInterface i) + { + if (this.getRow() < i.getRow()) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() < i.getColumn())) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())) + { + return false; + } + return true; + } + + public boolean isEqual(CellValueRecordInterface i) + { + return ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())); + } + + public boolean isInValueSection() + { + return true; + } + + public boolean isValue() + { + return true; + } + + /** + * return the non static version of the id for this record. + */ + + public short getSid() + { + return BlankRecord.sid; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[BLANK]\n"); + buffer.append("row = ").append(Integer.toHexString(getRow())) + .append("\n"); + buffer.append("col = ").append(Integer.toHexString(getColumn())) + .append("\n"); + buffer.append("xf = ") + .append(Integer.toHexString(getXFIndex())).append("\n"); + buffer.append("[/BLANK]\n"); + return buffer.toString(); + } + + /** + * 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 + */ + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 6); + LittleEndian.putShort(data, 4 + offset, getRow()); + LittleEndian.putShort(data, 6 + offset, getColumn()); + LittleEndian.putShort(data, 8 + offset, getXFIndex()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 10; + } + + public int compareTo(Object obj) + { + CellValueRecordInterface loc = ( CellValueRecordInterface ) obj; + + if ((this.getRow() == loc.getRow()) + && (this.getColumn() == loc.getColumn())) + { + return 0; + } + if (this.getRow() < loc.getRow()) + { + return -1; + } + if (this.getRow() > loc.getRow()) + { + return 1; + } + if (this.getColumn() < loc.getColumn()) + { + return -1; + } + if (this.getColumn() > loc.getColumn()) + { + return 1; + } + return -1; + } + + public boolean equals(Object obj) + { + if (!(obj instanceof CellValueRecordInterface)) + { + return false; + } + CellValueRecordInterface loc = ( CellValueRecordInterface ) obj; + + if ((this.getRow() == loc.getRow()) + && (this.getColumn() == loc.getColumn())) + { + return true; + } + return false; + } +} diff --git a/src/java/org/apache/poi/hssf/record/BookBoolRecord.java b/src/java/org/apache/poi/hssf/record/BookBoolRecord.java new file mode 100644 index 000000000..df273d5c7 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/BookBoolRecord.java @@ -0,0 +1,170 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Save External Links record (BookBool)

+ * Description: Contains a flag specifying whether the Gui should save externally + * linked values from other workbooks.

+ * REFERENCE: PG 289 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class BookBoolRecord + extends Record +{ + public final static short sid = 0xDA; + private short field_1_save_link_values; + + public BookBoolRecord() + { + } + + /** + * Constructs a BookBoolRecord and sets its fields appropriately + * + * @param short id must be 0xDA or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public BookBoolRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a BookBoolRecord and sets its fields appropriately + * + * @param short id must be 0xDA or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public BookBoolRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A BOOKBOOL RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_save_link_values = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set the save ext links flag + * + * @param short flag (0/1 -off/on) + */ + + public void setSaveLinkValues(short flag) + { + field_1_save_link_values = flag; + } + + /** + * get the save ext links flag + * + * @return short 0/1 (off/on) + */ + + public short getSaveLinkValues() + { + return field_1_save_link_values; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[BOOKBOOL]\n"); + buffer.append(" .savelinkvalues = ") + .append(Integer.toHexString(getSaveLinkValues())).append("\n"); + buffer.append("[/BOOKBOOL]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, field_1_save_link_values); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/BoolErrRecord.java b/src/java/org/apache/poi/hssf/record/BoolErrRecord.java new file mode 100644 index 000000000..9777c29f4 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/BoolErrRecord.java @@ -0,0 +1,411 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * BoolErrRecord.java + * + * Created on January 19, 2002, 9:30 AM + */ +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Creates new BoolErrRecord.

+ * REFERENCE: PG ??? Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Michael P. Harhen + * @version 2.0-pre + */ + +public class BoolErrRecord + extends Record + implements CellValueRecordInterface, Comparable +{ + public final static short sid = 0x205; + private short field_1_row; + private short field_2_column; + private short field_3_xf_index; + private byte field_4_bBoolErr; + private byte field_5_fError; + + /** Creates new BoolErrRecord */ + + public BoolErrRecord() + { + } + + /** + * Constructs a BoolErr record and sets its fields appropriately. + * + * @param short id must be 0x205 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public BoolErrRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a BoolErr record and sets its fields appropriately. + * + * @param short id must be 0x205 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record + */ + + public BoolErrRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + /** + * called by the constructor, should set class level fields. Should throw + * runtime exception for bad/icomplete data. + * + * @param data raw data + * @param size size of data + */ + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_row = LittleEndian.getShort(data, 0 + offset); + field_2_column = LittleEndian.getShort(data, 2 + offset); + field_3_xf_index = LittleEndian.getShort(data, 4 + offset); + field_4_bBoolErr = data[ 6 + offset ]; + field_5_fError = data[ 7 + offset ]; + } + + public void setRow(short row) + { + field_1_row = row; + } + + public void setColumn(short col) + { + field_2_column = col; + } + + /** + * set the index to the ExtendedFormat + * @see org.apache.poi.hssf.record.ExtendedFormatRecord + * @param index to the XF record + */ + + public void setXFIndex(short xf) + { + field_3_xf_index = xf; + } + + /** + * set the boolean value for the cell + * + * @param boolean representing the boolean value + */ + + public void setValue(boolean value) + { + field_4_bBoolErr = value ? ( byte ) 1 + : ( byte ) 0; + field_5_fError = ( byte ) 0; + } + + /** + * set the error value for the cell + * + * @param error representing the error value + */ + + public void setValue(byte value) + { + field_4_bBoolErr = value; + field_5_fError = ( byte ) 1; + } + + public short getRow() + { + return field_1_row; + } + + public short getColumn() + { + return field_2_column; + } + + /** + * get the index to the ExtendedFormat + * @see org.apache.poi.hssf.record.ExtendedFormatRecord + * @return index to the XF record + */ + + public short getXFIndex() + { + return field_3_xf_index; + } + + /** + * get the value for the cell + * + * @return boolean representing the boolean value + */ + + public boolean getBooleanValue() + { + return (field_4_bBoolErr != 0); + } + + /** + * get the error value for the cell + * + * @return byte representing the error value + */ + + public byte getErrorValue() + { + return field_4_bBoolErr; + } + + /** + * Indicates whether the call holds a boolean value + * + * @return boolean true if the cell holds a boolean value + */ + + public boolean isBoolean() + { + return (field_5_fError == ( byte ) 0); + } + + /** + * Indicates whether the call holds an error value + * + * @return boolean true if the cell holds an error value + */ + + public boolean isError() + { + return (field_5_fError != ( byte ) 0); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[BOOLERR]\n"); + buffer.append(" .row = ") + .append(Integer.toHexString(getRow())).append("\n"); + buffer.append(" .col = ") + .append(Integer.toHexString(getColumn())).append("\n"); + buffer.append(" .xfindex = ") + .append(Integer.toHexString(getXFIndex())).append("\n"); + if (isBoolean()) + { + buffer.append(" .booleanValue = ").append(getBooleanValue()) + .append("\n"); + } + else + { + buffer.append(" .errorValue = ").append(getErrorValue()) + .append("\n"); + } + buffer.append("[/BOOLERR]\n"); + return buffer.toString(); + } + + /** + * 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 + */ + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 8); + LittleEndian.putShort(data, 4 + offset, getRow()); + LittleEndian.putShort(data, 6 + offset, getColumn()); + LittleEndian.putShort(data, 8 + offset, getXFIndex()); + data[ 10 + offset ] = field_4_bBoolErr; + data[ 11 + offset ] = field_5_fError; + return getRecordSize(); + } + + public int getRecordSize() + { + return 12; + } + + /** + * called by constructor, should throw runtime exception in the event of a + * record passed with a differing ID. + * + * @param id alleged id for this record + */ + + protected void validateSid(short id) + { + if (id != this.sid) + { + throw new RecordFormatException("Not a valid BoolErrRecord"); + } + } + + public short getSid() + { + return this.sid; + } + + public boolean isBefore(CellValueRecordInterface i) + { + if (this.getRow() > i.getRow()) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() > i.getColumn())) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())) + { + return false; + } + return true; + } + + public boolean isAfter(CellValueRecordInterface i) + { + if (this.getRow() < i.getRow()) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() < i.getColumn())) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())) + { + return false; + } + return true; + } + + public boolean isEqual(CellValueRecordInterface i) + { + return ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())); + } + + public boolean isInValueSection() + { + return true; + } + + public boolean isValue() + { + return true; + } + + public int compareTo(Object obj) + { + CellValueRecordInterface loc = ( CellValueRecordInterface ) obj; + + if ((this.getRow() == loc.getRow()) + && (this.getColumn() == loc.getColumn())) + { + return 0; + } + if (this.getRow() < loc.getRow()) + { + return -1; + } + if (this.getRow() > loc.getRow()) + { + return 1; + } + if (this.getColumn() < loc.getColumn()) + { + return -1; + } + if (this.getColumn() > loc.getColumn()) + { + return 1; + } + return -1; + } + + public boolean equals(Object obj) + { + if (!(obj instanceof CellValueRecordInterface)) + { + return false; + } + CellValueRecordInterface loc = ( CellValueRecordInterface ) obj; + + if ((this.getRow() == loc.getRow()) + && (this.getColumn() == loc.getColumn())) + { + return true; + } + return false; + } +} diff --git a/src/java/org/apache/poi/hssf/record/BoundSheetRecord.java b/src/java/org/apache/poi/hssf/record/BoundSheetRecord.java new file mode 100644 index 000000000..d6228cd3a --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/BoundSheetRecord.java @@ -0,0 +1,286 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.StringUtil; + +/** + * Title: Bound Sheet Record (aka BundleSheet)

+ * Description: Defines a sheet within a workbook. Basically stores the sheetname + * and tells where the Beginning of file record is within the HSSF + * file.

+ * REFERENCE: PG 291 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class BoundSheetRecord + extends Record +{ + public final static short sid = 0x85; + private int field_1_position_of_BOF; + private short field_2_option_flags; + private byte field_3_sheetname_length; + private byte field_4_compressed_unicode_flag; // not documented + private String field_5_sheetname; + + public BoundSheetRecord() + { + } + + /** + * Constructs a BoundSheetRecord and sets its fields appropriately + * + * @param short id must be 0x85 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public BoundSheetRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a BoundSheetRecord and sets its fields appropriately + * + * @param short id must be 0x85 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public BoundSheetRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A Bound Sheet RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_position_of_BOF = LittleEndian.getInt(data, + 0 + offset); + field_2_option_flags = LittleEndian.getShort(data, + 4 + offset); + field_3_sheetname_length = data[ 6 + offset ]; + field_4_compressed_unicode_flag = data[ 7 + offset ]; + field_5_sheetname = new String(data, 8 + offset, + ( int ) field_3_sheetname_length); + } + + /** + * set the offset in bytes of the Beginning of File Marker within the HSSF Stream part of the POIFS file + * + * @param offset in bytes + */ + + public void setPositionOfBof(int pos) + { + field_1_position_of_BOF = pos; + } + + /** + * set the option flags (unimportant for HSSF supported sheets) + * + * @param flags to set + */ + + public void setOptionFlags(short flags) + { + field_2_option_flags = flags; + } + + /** + * Set the length of the sheetname in characters + * + * @param number of characters in the sheet name + * @see #setSheetname(String) + */ + + public void setSheetnameLength(byte len) + { + field_3_sheetname_length = len; + } + + /** + * set whether or not to interperate the Sheetname as compressed unicode (8/16 bit) + * (This is undocumented but can be found as Q187919 on the Microsoft(tm) Support site) + * @param flag (0/1) 0- compressed, 1 - uncompressed (16-bit) + */ + + public void setCompressedUnicodeFlag(byte flag) + { + field_4_compressed_unicode_flag = flag; + } + + /** + * Set the sheetname for this sheet. (this appears in the tabs at the bottom) + * @param sheetname the name of the sheet + */ + + public void setSheetname(String sheetname) + { + field_5_sheetname = sheetname; + } + + /** + * get the offset in bytes of the Beginning of File Marker within the HSSF Stream part of the POIFS file + * + * @return offset in bytes + */ + + public int getPositionOfBof() + { + return field_1_position_of_BOF; + } + + /** + * get the option flags (unimportant for HSSF supported sheets) + * + * @return flags to set + */ + + public short getOptionFlags() + { + return field_2_option_flags; + } + + /** + * get the length of the sheetname in characters + * + * @return number of characters in the sheet name + * @see #getSheetname() + */ + + public byte getSheetnameLength() + { + return field_3_sheetname_length; + } + + /** + * get whether or not to interperate the Sheetname as compressed unicode (8/16 bit) + * (This is undocumented but can be found as Q187919 on the Microsoft(tm) Support site) + * @return flag (0/1) 0- compressed, 1 - uncompressed (16-bit) + */ + + public byte getCompressedUnicodeFlag() + { + return field_4_compressed_unicode_flag; + } + + /** + * get the sheetname for this sheet. (this appears in the tabs at the bottom) + * @return sheetname the name of the sheet + */ + + public String getSheetname() + { + return field_5_sheetname; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[BOUNDSHEET]\n"); + buffer.append(" .bof = ") + .append(Integer.toHexString(getPositionOfBof())).append("\n"); + buffer.append(" .optionflags = ") + .append(Integer.toHexString(getOptionFlags())).append("\n"); + buffer.append(" .sheetname length= ") + .append(Integer.toHexString(getSheetnameLength())).append("\n"); + buffer.append(" .unicodeflag = ") + .append(Integer.toHexString(getCompressedUnicodeFlag())) + .append("\n"); + buffer.append(" .sheetname = ").append(getSheetname()) + .append("\n"); + buffer.append("[/BOUNDSHEET]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + ( short ) (0x08 + getSheetnameLength())); + LittleEndian.putInt(data, 4 + offset, getPositionOfBof()); + LittleEndian.putShort(data, 8 + offset, getOptionFlags()); + data[ 10 + offset ] = getSheetnameLength(); + data[ 11 + offset ] = getCompressedUnicodeFlag(); + + // we assume compressed unicode (bein the dern americans we are ;-p) + StringUtil.putCompressedUnicode(getSheetname(), data, 12 + offset); + return getRecordSize(); + } + + public int getRecordSize() + { + return 12 + getSheetnameLength(); + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/CalcCountRecord.java b/src/java/org/apache/poi/hssf/record/CalcCountRecord.java new file mode 100644 index 000000000..7b4fcc813 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/CalcCountRecord.java @@ -0,0 +1,172 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Calc Count Record + * Description: Specifies the maximum times the gui should perform a formula + * recalculation. For instance: in the case a formula includes + * cells that are themselves a result of a formula and a value + * changes. This is essentially a failsafe against an infinate + * loop in the event the formulas are not independant.

+ * REFERENCE: PG 292 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + * @see org.apache.poi.hssf.record.CalcModeRecord + */ + +public class CalcCountRecord + extends Record +{ + public final static short sid = 0xC; + private short field_1_iterations; + + public CalcCountRecord() + { + } + + /** + * Constructs a CalcCountRecord and sets its fields appropriately + * + * @param short id must be 0xC or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * + */ + + public CalcCountRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a CalcCountRecord and sets its fields appropriately + * + * @param short id must be 0xC or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public CalcCountRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT An Calc Count RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_iterations = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set the number of iterations to perform + * @param iterations to perform + */ + + public void setIterations(short iterations) + { + field_1_iterations = iterations; + } + + /** + * get the number of iterations to perform + * @return iterations + */ + + public short getIterations() + { + return field_1_iterations; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[CALCCOUNT]\n"); + buffer.append(" .iterations = ") + .append(Integer.toHexString(getIterations())).append("\n"); + buffer.append("[/CALCCOUNT]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x2); + LittleEndian.putShort(data, 4 + offset, getIterations()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/CalcModeRecord.java b/src/java/org/apache/poi/hssf/record/CalcModeRecord.java new file mode 100644 index 000000000..c2ec3be5e --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/CalcModeRecord.java @@ -0,0 +1,197 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Calc Mode Record

+ * Description: Tells the gui whether to calculate formulas + * automatically, manually or automatically + * except for tables.

+ * REFERENCE: PG 292 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + * @see org.apache.poi.hssf.record.CalcCountRecord + */ + +public class CalcModeRecord + extends Record +{ + public final static short sid = 0xD; + + /** + * manually calculate formulas (0) + */ + + public final static short MANUAL = 0; + + /** + * automatically calculate formulas (1) + */ + + public final static short AUTOMATIC = 1; + + /** + * automatically calculate formulas except for tables (-1) + */ + + public final static short AUTOMATIC_EXCEPT_TABLES = -1; + private short field_1_calcmode; + + public CalcModeRecord() + { + } + + /** + * Constructs a CalcModeRecord and sets its fields appropriately + * + * @param short id must be 0xD or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public CalcModeRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a CalcModeRecord and sets its fields appropriately + * + * @param short id must be 0xD or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's start data + */ + + public CalcModeRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT An Calc Mode RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_calcmode = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set the calc mode flag for formulas + * + * @see #MANUAL + * @see #AUTOMATIC + * @see #AUTOMATIC_EXCEPT_TABLES + * + * @param calcmode one of the three flags above + */ + + public void setCalcMode(short calcmode) + { + field_1_calcmode = calcmode; + } + + /** + * get the calc mode flag for formulas + * + * @see #MANUAL + * @see #AUTOMATIC + * @see #AUTOMATIC_EXCEPT_TABLES + * + * @return calcmode one of the three flags above + */ + + public short getCalcMode() + { + return field_1_calcmode; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[CALCMODE]\n"); + buffer.append(" .calcmode = ") + .append(Integer.toHexString(getCalcMode())).append("\n"); + buffer.append("[/CALCMODE]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x2); + LittleEndian.putShort(data, 4 + offset, getCalcMode()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/CellValueRecordInterface.java b/src/java/org/apache/poi/hssf/record/CellValueRecordInterface.java new file mode 100644 index 000000000..97703a246 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/CellValueRecordInterface.java @@ -0,0 +1,139 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * CellValueRecordInterface.java + * + * Created on October 2, 2001, 8:27 PM + */ +package org.apache.poi.hssf.record; + +/** + * The cell value record interface is implemented by all classes of type Record that + * contain cell values. It allows the containing sheet to move through them and compare + * them. + * + * @author Andrew C. Oliver (acoliver at apache dot org) + * + * @see org.apache.poi.hssf.model.Sheet + * @see org.apache.poi.hssf.record.Record + * @see org.apache.poi.hssf.record.RecordFactory + */ + +public interface CellValueRecordInterface +{ + + /** + * get the row this cell occurs on + * + * @return the row + */ + + public short getRow(); + + /** + * get the column this cell defines within the row + * + * @return the column + */ + + public short getColumn(); + + /** + * set the row this cell occurs on + * @param row the row this cell occurs within + */ + + public void setRow(short row); + + /** + * set the column this cell defines within the row + * + * @param col the column this cell defines + */ + + public void setColumn(short col); + + public void setXFIndex(short xf); + + public short getXFIndex(); + + /** + * returns whether this cell is before the passed in cell + * + * @param cellinterface another cell interface record to compare + * @return true if the cells is before, or false if not + */ + + public boolean isBefore(CellValueRecordInterface i); + + /** + * returns whether this cell is after the passed in cell + * + * @param cellinterface record to compare + * @return true if the cell is after, false if not + */ + + public boolean isAfter(CellValueRecordInterface i); + + /** + * returns whether this cell represents the same cell (NOT VALUE) + * + * @param cellinterface record to compare + * @return true if the cells are the same cell (positionally), false if not. + */ + + public boolean isEqual(CellValueRecordInterface i); +} diff --git a/src/java/org/apache/poi/hssf/record/ChartFormatRecord.java b/src/java/org/apache/poi/hssf/record/ChartFormatRecord.java new file mode 100644 index 000000000..d86573418 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/ChartFormatRecord.java @@ -0,0 +1,222 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.BitField; + +/** + * Class ChartFormatRecord + * + * + * @author + * @version %I%, %G% + */ + +public class ChartFormatRecord + extends Record +{ + public static final short sid = 0x1014; + + // ignored? + private int field1_x_position; // lower left + private int field2_y_position; // lower left + private int field3_width; + private int field4_height; + private short field5_grbit; + private BitField varyDisplayPattern = new BitField(0x01); + + public ChartFormatRecord() + { + } + + /** + * Constructs a ChartFormatRecord record and sets its fields appropriately. + * + * @param short id must equal the sid or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public ChartFormatRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a ChartFormatRecord record and sets its fields appropriately. + * + * @param short id must equal the sid or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public ChartFormatRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A CHARTFORMAT RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field1_x_position = LittleEndian.getInt(data, 0 + offset); + field2_y_position = LittleEndian.getInt(data, 4 + offset); + field3_width = LittleEndian.getInt(data, 8 + offset); + field4_height = LittleEndian.getInt(data, 12 + offset); + field5_grbit = LittleEndian.getShort(data, 16 + offset); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[CHARTFORMAT]\n"); + buffer.append(" .xPosition = ").append(getXPosition()) + .append("\n"); + buffer.append(" .yPosition = ").append(getYPosition()) + .append("\n"); + buffer.append(" .width = ").append(getWidth()) + .append("\n"); + buffer.append(" .height = ").append(getHeight()) + .append("\n"); + buffer.append(" .grBit = ") + .append(Integer.toHexString(field5_grbit)).append("\n"); + buffer.append("[/CHARTFORMAT]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 22)); // 22 byte length + LittleEndian.putInt(data, 4 + offset, getXPosition()); + LittleEndian.putInt(data, 8 + offset, getYPosition()); + LittleEndian.putInt(data, 12 + offset, getWidth()); + LittleEndian.putInt(data, 16 + offset, getHeight()); + LittleEndian.putShort(data, 20 + offset, field5_grbit); + return getRecordSize(); + } + + public int getRecordSize() + { + return 22; + } + + public short getSid() + { + return this.sid; + } + + public int getXPosition() + { + return field1_x_position; + } + + public void setXPosition(int xPosition) + { + this.field1_x_position = xPosition; + } + + public int getYPosition() + { + return field2_y_position; + } + + public void setYPosition(int yPosition) + { + this.field2_y_position = yPosition; + } + + public int getWidth() + { + return field3_width; + } + + public void setWidth(int width) + { + this.field3_width = width; + } + + public int getHeight() + { + return field4_height; + } + + public void setHeight(int height) + { + this.field4_height = height; + } + + public boolean getVaryDisplayPattern() + { + return varyDisplayPattern.isSet(field5_grbit); + } + + public void setVaryDisplayPattern(boolean value) + { + field5_grbit = varyDisplayPattern.setShortBoolean(field5_grbit, + value); + } +} diff --git a/src/java/org/apache/poi/hssf/record/ChartRecord.java b/src/java/org/apache/poi/hssf/record/ChartRecord.java new file mode 100644 index 000000000..bc425b528 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/ChartRecord.java @@ -0,0 +1,205 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * The CHART record defines the location of a chart an it's size. + *

+ * This record supports the charting capability of the program. + *

+ * This is currently based on BIFF4 but will up updated to take into + * account changed required by BIFF8. + * + * @author Glen Stampoultzis (gstamp at iprimus dot com dot au) + */ + +public class ChartRecord + extends Record +{ + public static final short sid = 0x1002; + private int field1_x_position; + private int field2_y_position; + private int field3_x_size; + private int field4_y_size; + + public ChartRecord() + { + } + + /** + * Constructs a ChartRecord record and sets its fields appropriately. + * + * @param short id must be 0x1002 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public ChartRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a SeriesRecord record and sets its fields appropriately. + * + * @param short id must be 0x1002 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public ChartRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A CHART RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field1_x_position = LittleEndian.getInt(data, 0 + offset); + field2_y_position = LittleEndian.getInt(data, 4 + offset); + field3_x_size = LittleEndian.getInt(data, 8 + offset); + field4_y_size = LittleEndian.getInt(data, 12 + offset); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[CHART]\n"); + buffer.append(" .xPosition = ").append(getXPosition()) + .append("\n"); + buffer.append(" .yPosition = ").append(getYPosition()) + .append("\n"); + buffer.append(" .xSize = ").append(getXSize()) + .append("\n"); + buffer.append(" .ySize = ").append(getYSize()) + .append("\n"); + buffer.append("[/CHART]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 20)); // 20 byte length + LittleEndian.putInt(data, 4 + offset, getXPosition()); + LittleEndian.putInt(data, 8 + offset, getYPosition()); + LittleEndian.putInt(data, 12 + offset, getXSize()); + LittleEndian.putInt(data, 16 + offset, getYSize()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 20; + } + + public short getSid() + { + return this.sid; + } + + public int getXPosition() + { + return field1_x_position; + } + + public void setXPosition(int xPosition) + { + this.field1_x_position = xPosition; + } + + public int getYPosition() + { + return field2_y_position; + } + + public void setYPosition(int yPosition) + { + this.field2_y_position = yPosition; + } + + public int getXSize() + { + return field3_x_size; + } + + public void setXSize(int xSize) + { + this.field3_x_size = xSize; + } + + public int getYSize() + { + return field4_y_size; + } + + public void setYSize(int ySize) + { + this.field4_y_size = ySize; + } +} diff --git a/src/java/org/apache/poi/hssf/record/CodepageRecord.java b/src/java/org/apache/poi/hssf/record/CodepageRecord.java new file mode 100644 index 000000000..41ac712c3 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/CodepageRecord.java @@ -0,0 +1,179 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Codepage Record

+ * Description: the default characterset. for the workbook

+ * REFERENCE: PG 293 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class CodepageRecord + extends Record +{ + public final static short sid = 0x42; + private short field_1_codepage; // = 0; + + /** + * the likely correct value for CODEPAGE (at least for US versions). We could use + * some help with international versions (which we do not have access to documentation + * for) + */ + + public final static short CODEPAGE = ( short ) 0x4b0; + + public CodepageRecord() + { + } + + /** + * Constructs a CodepageRecord and sets its fields appropriately + * + * @param short id must be 0x42 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public CodepageRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a CodepageRecord and sets its fields appropriately + * + * @param short id must be 0x42 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param int offset of the record + */ + + public CodepageRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A CODEPAGE RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_codepage = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set the codepage for this workbook + * + * @see #CODEPAGE + * @param codepage - the codepage to set + */ + + public void setCodepage(short cp) + { + field_1_codepage = cp; + } + + /** + * get the codepage for this workbook + * + * @see #CODEPAGE + * @return codepage - the codepage to set + */ + + public short getCodepage() + { + return field_1_codepage; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[CODEPAGE]\n"); + buffer.append(" .codepage = ") + .append(Integer.toHexString(getCodepage())).append("\n"); + buffer.append("[/CODEPAGE]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, getCodepage()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java b/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java new file mode 100644 index 000000000..f274a7574 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java @@ -0,0 +1,358 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * ColumnInfoRecord.java + * + * Created on December 8, 2001, 8:44 AM + */ +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.BitField; + +/** + * Title: ColumnInfo Record

+ * Description: Defines with width and formatting for a range of columns

+ * REFERENCE: PG 293 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class ColumnInfoRecord + extends Record +{ + public static final short sid = 0x7d; + private short field_1_first_col; + private short field_2_last_col; + private short field_3_col_width; + private short field_4_xf_index; + private short field_5_options; + static final private BitField hidden = new BitField(0x01); + static final private BitField outlevel = new BitField(0x0700); + static final private BitField collapsed = new BitField(0x1000); + private short field_6_reserved; + + public ColumnInfoRecord() + { + } + + /** + * Constructs a ColumnInfo record and sets its fields appropriately + * + * @param short id must be 0x7d or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public ColumnInfoRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a ColumnInfo record and sets its fields appropriately + * + * @param short id must be 0x7d or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public ColumnInfoRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data); + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_first_col = LittleEndian.getShort(data, 0 + offset); + field_2_last_col = LittleEndian.getShort(data, 2 + offset); + field_3_col_width = LittleEndian.getShort(data, 4 + offset); + field_4_xf_index = LittleEndian.getShort(data, 6 + offset); + field_5_options = LittleEndian.getShort(data, 8 + offset); + field_6_reserved = data[ 10 + offset ]; + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A COLINFO RECORD!!"); + } + } + + /** + * set the first column this record defines formatting info for + * @param fc - the first column index (0-based) + */ + + public void setFirstColumn(short fc) + { + field_1_first_col = fc; + } + + /** + * set the last column this record defines formatting info for + * @param lc - the last column index (0-based) + */ + + public void setLastColumn(short lc) + { + field_2_last_col = lc; + } + + /** + * set the columns' width in 1/256 of a character width + * @param cw - column width + */ + + public void setColumnWidth(short cw) + { + field_3_col_width = cw; + } + + /** + * set the columns' default format info + * @param xfi - the extended format index + * @see org.apache.poi.hssf.record.ExtendedFormatRecord + */ + + public void setXFIndex(short xfi) + { + field_4_xf_index = xfi; + } + + /** + * set the options bitfield - use the bitsetters instead + * @param options - the bitfield raw value + */ + + public void setOptions(short options) + { + field_5_options = options; + } + + // start options bitfield + + /** + * set whether or not these cells are hidden + * @param ishidden - whether the cells are hidden. + * @see #setOptions(short) + */ + + public void setHidden(boolean ishidden) + { + field_5_options = hidden.setShortBoolean(field_5_options, ishidden); + } + + /** + * set the outline level for the cells + * @see #setOptions(short) + * @param olevel -outline level for the cells + */ + + public void setOutlineLevel(short olevel) + { + field_5_options = outlevel.setShortValue(field_5_options, olevel); + } + + /** + * set whether the cells are collapsed + * @param iscollapsed - wether the cells are collapsed + * @see #setOptions(short) + */ + + public void setCollapsed(boolean iscollapsed) + { + field_5_options = collapsed.setShortBoolean(field_5_options, + iscollapsed); + } + + // end options bitfield + + /** + * get the first column this record defines formatting info for + * @return the first column index (0-based) + */ + + public short getFirstColumn() + { + return field_1_first_col; + } + + /** + * get the last column this record defines formatting info for + * @return the last column index (0-based) + */ + + public short getLastColumn() + { + return field_2_last_col; + } + + /** + * get the columns' width in 1/256 of a character width + * @return column width + */ + + public short getColumnWidth() + { + return field_3_col_width; + } + + /** + * get the columns' default format info + * @return the extended format index + * @see org.apache.poi.hssf.record.ExtendedFormatRecord + */ + + public short getXFIndex() + { + return field_4_xf_index; + } + + /** + * get the options bitfield - use the bitsetters instead + * @return the bitfield raw value + */ + + public short getOptions() + { + return field_5_options; + } + + // start options bitfield + + /** + * get whether or not these cells are hidden + * @return whether the cells are hidden. + * @see #setOptions(short) + */ + + public boolean getHidden() + { + return hidden.isSet(field_5_options); + } + + /** + * get the outline level for the cells + * @see #setOptions(short) + * @return outline level for the cells + */ + + public short getOutlineLevel() + { + return outlevel.getShortValue(field_5_options); + } + + /** + * get whether the cells are collapsed + * @return wether the cells are collapsed + * @see #setOptions(short) + */ + + public boolean getCollapsed() + { + return collapsed.isSet(field_5_options); + } + + // end options bitfield + public short getSid() + { + return sid; + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 12); + LittleEndian.putShort(data, 4 + offset, getFirstColumn()); + LittleEndian.putShort(data, 6 + offset, getLastColumn()); + LittleEndian.putShort(data, 8 + offset, getColumnWidth()); + LittleEndian.putShort(data, 10 + offset, getXFIndex()); + LittleEndian.putShort(data, 12 + offset, getOptions()); + LittleEndian.putShort(data, 14 + offset, + ( short ) 0x0); // retval[14] = 0; + return getRecordSize(); + } + + public int getRecordSize() + { + return 16; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[COLINFO]\n"); + buffer.append("colfirst = ").append(getFirstColumn()) + .append("\n"); + buffer.append("collast = ").append(getLastColumn()) + .append("\n"); + buffer.append("colwidth = ").append(getColumnWidth()) + .append("\n"); + buffer.append("xfindex = ").append(getXFIndex()).append("\n"); + buffer.append("options = ").append(getOptions()).append("\n"); + buffer.append(" hidden = ").append(getHidden()).append("\n"); + buffer.append(" olevel = ").append(getOutlineLevel()) + .append("\n"); + buffer.append(" collapsed = ").append(getCollapsed()) + .append("\n"); + buffer.append("[/COLINFO]\n"); + return buffer.toString(); + } +} diff --git a/src/java/org/apache/poi/hssf/record/ContinueRecord.java b/src/java/org/apache/poi/hssf/record/ContinueRecord.java new file mode 100644 index 000000000..81819cdb0 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/ContinueRecord.java @@ -0,0 +1,269 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import java.util.ArrayList; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Continue Record - Helper class used primarily for SST Records

+ * Description: handles overflow for prior record in the input + * stream; content is tailored to that prior record

+ * @author Marc Johnson (mjohnson at apache dot org) + * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class ContinueRecord + extends Record +{ + public final static short sid = 0x003C; + private byte[] field_1_data; + + /** + * default constructor + */ + + public ContinueRecord() + { + } + + /** + * Main constructor -- kinda dummy because we don't validate or fill fields + * + * @param id record id + * @param size record size + * @param data raw data + */ + + public ContinueRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Main constructor -- kinda dummy because we don't validate or fill fields + * + * @param id record id + * @param size record size + * @param data raw data + * @param offset of the record's data + */ + + public ContinueRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + /** + * USE ONLY within "processContinue" + */ + + public byte [] serialize() + { + byte[] retval = new byte[ field_1_data.length + 4 ]; + + LittleEndian.putShort(retval, 0, sid); + LittleEndian.putShort(retval, 2, ( short ) field_1_data.length); + System.arraycopy(field_1_data, 0, retval, 4, field_1_data.length); + return retval; + } + + public int serialize(int offset, byte [] data) + { + throw new RecordFormatException( + "You're not supposed to serialize Continue records like this directly"); + } + + /** + * set the data for continuation + * @param data - a byte array containing all of the continued data + */ + + public void setData(byte [] data) + { + field_1_data = data; + } + + /** + * get the data for continuation + * @return byte array containing all of the continued data + */ + + public byte [] getData() + { + return field_1_data; + } + + /** + * Use to serialize records that are too big for their britches (>8228..why 8228 and + * not 8192 aka 8k? Those folks in washington don't ususally make sense... + * or at least to anyone outside fo marketing... + * @deprecated handle this within the record...this didn't actualyl work out + */ + + public static byte [] processContinue(byte [] data) + { // could do this recursively but that seems hard to debug + + // 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 offset = 8214; + + // System.out.println("we have "+records+" continue records to process"); + ArrayList crs = new ArrayList(records); + int totalsize = 8214; + byte[] retval = null; + + for (int cr = 0; cr < records; cr++) + { + ContinueRecord contrec = new ContinueRecord(); + int arraysize = Math.min((8214 - 4), + (data.length - offset)); + byte[] crdata = new byte[ arraysize ]; + + System.arraycopy(data, offset, crdata, 0, arraysize); + + // System.out.println("arraycopy(data,"+offset+",crdata,"+0+","+arraysize+");"); + offset += crdata.length; + contrec.setData(crdata); + crs.add(contrec.serialize()); + } + for (int cr = 0; cr < records; cr++) + { + totalsize += (( byte [] ) crs.get(cr)).length; + } + + // System.out.println("totalsize="+totalsize); + retval = new byte[ totalsize ]; + offset = 8214; + System.arraycopy(data, 0, retval, 0, 8214); + for (int cr = 0; cr < records; cr++) + { + byte[] src = ( byte [] ) crs.get(cr); + + System.arraycopy(src, 0, retval, offset, src.length); + + // System.out.println("arraycopy(src,"+0+",retval,"+offset+","+src.length+");"); + offset += src.length; + } + return retval; + } + + /** + * Fill the fields. Only thing is, this record has no fields -- + * + * @param ignored_parm1 + * @param ignored_parm2 + */ + + protected void fillFields(byte [] data, short ignored_parm2) + { + + // throw new RecordFormatException("Are you crazy? Don't fill a continue record"); + // do nothing + } + + /** + * Make sure we have a good id + * + * @param id the alleged id + */ + + protected void validateSid(short id) + { + if (id != ContinueRecord.sid) + { + throw new RecordFormatException("Not a Continue Record"); + } + } + + /** + * Debugging toString + * + * @return string representation + */ + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[CONTINUE RECORD]\n"); + buffer.append(" .id = ").append(Integer.toHexString(sid)) + .append("\n"); + buffer.append("[/CONTINUE RECORD]\n"); + return buffer.toString(); + } + + public short getSid() + { + return this.sid; + } + + /** + * Fill the fields. Only thing is, this record has no fields -- + * + * @param ignored_parm1 + * @param ignored_parm2 + */ + + protected void fillFields(byte [] data, short size, int offset) + { + } +} diff --git a/src/java/org/apache/poi/hssf/record/CountryRecord.java b/src/java/org/apache/poi/hssf/record/CountryRecord.java new file mode 100644 index 000000000..184bf981e --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/CountryRecord.java @@ -0,0 +1,200 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Country Record (aka WIN.INI country)

+ * Description: used for localization. Currently HSSF always sets this to 1 + * and it seems to work fine even in Germany. (es geht's auch fuer Deutschland)

+ * + * REFERENCE: PG 298 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class CountryRecord + extends Record +{ + public final static short sid = 0x8c; + + // 1 for US + private short field_1_default_country; + private short field_2_current_country; + + public CountryRecord() + { + } + + /** + * Constructs a CountryRecord and sets its fields appropriately + * + * @param short id must be 0x8c or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public CountryRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a CountryRecord and sets its fields appropriately + * + * @param short id must be 0x8c or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public CountryRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A Country RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_default_country = LittleEndian.getShort(data, 0 + offset); + field_2_current_country = LittleEndian.getShort(data, 2 + offset); + } + + /** + * sets the default country + * + * @param country ID to set (1 = US) + */ + + public void setDefaultCountry(short country) + { + field_1_default_country = country; + } + + /** + * sets the current country + * + * @param country ID to set (1 = US) + */ + + public void setCurrentCountry(short country) + { + field_2_current_country = country; + } + + /** + * gets the default country + * + * @return country ID (1 = US) + */ + + public short getDefaultCountry() + { + return field_1_default_country; + } + + /** + * gets the current country + * + * @return country ID (1 = US) + */ + + public short getCurrentCountry() + { + return field_2_current_country; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[COUNTRY]\n"); + buffer.append(" .defaultcountry = ") + .append(Integer.toHexString(getDefaultCountry())).append("\n"); + buffer.append(" .currentcountry = ") + .append(Integer.toHexString(getCurrentCountry())).append("\n"); + buffer.append("[/COUNTRY]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x04)); // 4 bytes (8 total) + LittleEndian.putShort(data, 4 + offset, getDefaultCountry()); + LittleEndian.putShort(data, 6 + offset, getCurrentCountry()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 8; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/DBCellRecord.java b/src/java/org/apache/poi/hssf/record/DBCellRecord.java new file mode 100644 index 000000000..d267be248 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/DBCellRecord.java @@ -0,0 +1,241 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +import java.util.ArrayList; + +/** + * Title: DBCell Record (Currently read only. Not required.) + * Description: Used to find rows in blocks...TODO

+ * REFERENCE: PG 299/440 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class DBCellRecord + extends Record +{ + public final static short sid = 0xd7; + private int field_1_row_offset; + private short[] field_2_cell_offsets; + + public DBCellRecord() + { + } + + /** + * Constructs a DBCellRecord and sets its fields appropriately + * + * @param short id must be 0xd7 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public DBCellRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a DBCellRecord and sets its fields appropriately + * + * @param short id must be 0xd7 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public DBCellRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A valid DBCell RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_row_offset = LittleEndian.getShort(data, 0 + offset); + field_2_cell_offsets = new short[ (size - 4) / 2 ]; + int element = 0; + + for (int k = 4; k < data.length; k += 2) + { + field_2_cell_offsets[ element++ ] = LittleEndian.getShort(data, + k + offset); + } + } + + /** + * sets offset from the start of this DBCellRecord to the start of the first cell in + * the next DBCell block. + * + * @param rowoffset to the start of the first cell in the next DBCell block + */ + + public void setRowOffset(int offset) + { + field_1_row_offset = offset; + } + + // need short list impl. + public void addCellOffset(short offset) + { + if (field_2_cell_offsets == null) + { + field_2_cell_offsets = new short[ 1 ]; + } + else + { + short[] temp = new short[ field_2_cell_offsets.length + 1 ]; + + System.arraycopy(field_2_cell_offsets, 0, temp, 0, + field_2_cell_offsets.length); + field_2_cell_offsets = temp; + } + field_2_cell_offsets[ field_2_cell_offsets.length - 1 ] = offset; + } + + /** + * gets offset from the start of this DBCellRecord to the start of the first cell in + * the next DBCell block. + * + * @return rowoffset to the start of the first cell in the next DBCell block + */ + + public int getRowOffset() + { + return field_1_row_offset; + } + + /** + * return the cell offset in the array + * + * @param index of the cell offset to retrieve + * @return celloffset from the celloffset array + */ + + public short getCellOffsetAt(int index) + { + return field_2_cell_offsets[ index ]; + } + + /** + * get the number of cell offsets in the celloffset array + * + * @return number of cell offsets + */ + + public int getNumCellOffsets() + { + return field_2_cell_offsets.length; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[DBCELL]\n"); + buffer.append(" .rowoffset = ") + .append(Integer.toHexString(getRowOffset())).append("\n"); + for (int k = 0; k < getNumCellOffsets(); k++) + { + buffer.append(" .cell_" + k + " = ") + .append(Integer.toHexString(getCellOffsetAt(k))).append("\n"); + } + buffer.append("[/DBCELL]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + if (field_2_cell_offsets == null) + { + field_2_cell_offsets = new short[ 0 ]; + } + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) (4 + (getNumCellOffsets() * 2)))); + LittleEndian.putInt(data, 4 + offset, getRowOffset()); + for (int k = 0; k < getNumCellOffsets(); k++) + { + LittleEndian.putShort(data, 8 + k + offset, getCellOffsetAt(k)); + } + return getRecordSize(); + } + + public int getRecordSize() + { + return 8 + (getNumCellOffsets() * 2); + } + + public short getSid() + { + return this.sid; + } + + public boolean isInValueSection() + { + return true; + } +} diff --git a/src/java/org/apache/poi/hssf/record/DSFRecord.java b/src/java/org/apache/poi/hssf/record/DSFRecord.java new file mode 100644 index 000000000..5f7048ee6 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/DSFRecord.java @@ -0,0 +1,168 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Double Stream Flag Record

+ * Description: tells if this is a double stream file. (always no for HSSF generated files)

+ * Double Stream files contain both BIFF8 and BIFF7 workbooks.

+ * REFERENCE: PG 305 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class DSFRecord + extends Record +{ + public final static short sid = 0x161; + private short field_1_dsf; + + public DSFRecord() + { + } + + /** + * Constructs a DBCellRecord and sets its fields appropriately. + * + * @param short id must be 0x161 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public DSFRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a DBCellRecord and sets its fields appropriately. + * + * @param short id must be 0x161 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public DSFRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A DSF RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_dsf = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set the DSF flag + * @param dsfflag (0-off,1-on) + */ + + public void setDsf(short dsfflag) + { + field_1_dsf = dsfflag; + } + + /** + * get the DSF flag + * @return dsfflag (0-off,1-on) + */ + + public short getDsf() + { + return field_1_dsf; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[DSF]\n"); + buffer.append(" .isDSF = ") + .append(Integer.toHexString(getDsf())).append("\n"); + buffer.append("[/DSF]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, getDsf()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/DateWindow1904Record.java b/src/java/org/apache/poi/hssf/record/DateWindow1904Record.java new file mode 100644 index 000000000..14f43bf34 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/DateWindow1904Record.java @@ -0,0 +1,169 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Date Window 1904 Flag record

+ * Description: Flag specifying whether 1904 date windowing is used. + * (tick toc tick toc...BOOM!)

+ * REFERENCE: PG 280 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class DateWindow1904Record + extends Record +{ + public final static short sid = 0x22; + private short field_1_window; + + public DateWindow1904Record() + { + } + + /** + * Constructs a DateWindow1904 record and sets its fields appropriately. + * + * @param short id must be 0x22 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public DateWindow1904Record(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a DateWindow1904 record and sets its fields appropriately. + * + * @param short id must be 0x22 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public DateWindow1904Record(short id, short size, byte [] data, + int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A 1904 RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_window = LittleEndian.getShort(data, 0 + offset); + } + + /** + * sets whether or not to use 1904 date windowing (which means you'll be screwed in 2004) + * @param window flag - 0/1 (false,true) + */ + + public void setWindowing(short window) + { // I hate using numbers in method names so I wont! + field_1_window = window; + } + + /** + * gets whether or not to use 1904 date windowing (which means you'll be screwed in 2004) + * @return window flag - 0/1 (false,true) + */ + + public short getWindowing() + { + return field_1_window; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[1904]\n"); + buffer.append(" .is1904 = ") + .append(Integer.toHexString(getWindowing())).append("\n"); + buffer.append("[/1904]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, getWindowing()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/DefaultColWidthRecord.java b/src/java/org/apache/poi/hssf/record/DefaultColWidthRecord.java new file mode 100644 index 000000000..33fd6ceab --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/DefaultColWidthRecord.java @@ -0,0 +1,168 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Default Column Width Record

+ * Description: Specifies the default width for columns that have no specific + * width set.

+ * REFERENCE: PG 302 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class DefaultColWidthRecord + extends Record +{ + public final static short sid = 0x55; + private short field_1_col_width; + + public DefaultColWidthRecord() + { + } + + /** + * Constructs a DefaultColumnWidth record and sets its fields appropriately. + * + * @param short id must be 0x55 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public DefaultColWidthRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a DefaultColumnWidth record and sets its fields appropriately. + * + * @param short id must be 0x55 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public DefaultColWidthRecord(short id, short size, byte [] data, + int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A DefaultColWidth RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_col_width = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set the default column width + * @param defaultwidth for columns + */ + + public void setColWidth(short height) + { + field_1_col_width = height; + } + + /** + * get the default column width + * @return defaultwidth for columns + */ + + public short getColWidth() + { + return field_1_col_width; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[DEFAULTCOLWIDTH]\n"); + buffer.append(" .colwidth = ") + .append(Integer.toHexString(getColWidth())).append("\n"); + buffer.append("[/DEFAULTCOLWIDTH]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x2); + LittleEndian.putShort(data, 4 + offset, getColWidth()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/DefaultRowHeightRecord.java b/src/java/org/apache/poi/hssf/record/DefaultRowHeightRecord.java new file mode 100644 index 000000000..b4088e4cd --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/DefaultRowHeightRecord.java @@ -0,0 +1,193 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Default Row Height Record + * Description: Row height for rows with undefined or not explicitly defined + * heights. + * REFERENCE: PG 301 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class DefaultRowHeightRecord + extends Record +{ + public final static short sid = 0x225; + private short field_1_option_flags; + private short field_2_row_height; + + public DefaultRowHeightRecord() + { + } + + /** + * Constructs a DefaultRowHeight record and sets its fields appropriately. + * + * @param short id must be 0x225 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public DefaultRowHeightRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a DefaultRowHeight record and sets its fields appropriately. + * + * @param short id must be 0x225 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the records data + */ + + public DefaultRowHeightRecord(short id, short size, byte [] data, + int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A DefaultRowHeight RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_option_flags = LittleEndian.getShort(data, 0 + offset); + field_2_row_height = LittleEndian.getShort(data, 2 + offset); + } + + /** + * set the (currently unimportant to HSSF) option flags + * @param flags the bitmask to set + */ + + public void setOptionFlags(short flags) + { + field_1_option_flags = flags; + } + + /** + * set the default row height + * @param rowheight for undefined rows/rows w/undefined height + */ + + public void setRowHeight(short height) + { + field_2_row_height = height; + } + + /** + * get the (currently unimportant to HSSF) option flags + * @return flags - the current bitmask + */ + + public short getOptionFlags() + { + return field_1_option_flags; + } + + /** + * get the default row height + * @return rowheight for undefined rows/rows w/undefined height + */ + + public short getRowHeight() + { + return field_2_row_height; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[DEFAULTROWHEIGHT]\n"); + buffer.append(" .optionflags = ") + .append(Integer.toHexString(getOptionFlags())).append("\n"); + buffer.append(" .rowheight = ") + .append(Integer.toHexString(getRowHeight())).append("\n"); + buffer.append("[/DEFAULTROWHEIGHT]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x4); + LittleEndian.putShort(data, 4 + offset, getOptionFlags()); + LittleEndian.putShort(data, 6 + offset, getRowHeight()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 8; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/DeltaRecord.java b/src/java/org/apache/poi/hssf/record/DeltaRecord.java new file mode 100644 index 000000000..b54ecda5b --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/DeltaRecord.java @@ -0,0 +1,170 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Delta Record

+ * Description: controls the accuracy of the calculations

+ * REFERENCE: PG 303 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class DeltaRecord + extends Record +{ + public final static short sid = 0x10; + public final static double DEFAULT_VALUE = 0.0010; // should be .001 + + // a double is an IEEE 8-byte float...damn IEEE and their goofy standards an + // ambiguous numeric identifiers + private double field_1_max_change; + + public DeltaRecord() + { + } + + /** + * Constructs a Delta record and sets its fields appropriately. + * + * @param short id must be 0x10 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public DeltaRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a Delta record and sets its fields appropriately. + * + * @param short id must be 0x10 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of record data + */ + + public DeltaRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A DELTA RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_max_change = LittleEndian.getDouble(data, 0 + offset); + } + + /** + * set the maximum change + * @param maxChange - maximum rounding error + */ + + public void setMaxChange(double maxChange) + { + field_1_max_change = maxChange; + } + + /** + * get the maximum change + * @return maxChange - maximum rounding error + */ + + public double getMaxChange() + { + return field_1_max_change; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[DELTA]\n"); + buffer.append(" .maxchange = ").append(getMaxChange()) + .append("\n"); + buffer.append("[/DELTA]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x8); + LittleEndian.putDouble(data, 4 + offset, getMaxChange()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 12; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/DimensionsRecord.java b/src/java/org/apache/poi/hssf/record/DimensionsRecord.java new file mode 100644 index 000000000..f1ccba5ae --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/DimensionsRecord.java @@ -0,0 +1,247 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Dimensions Record

+ * Description: provides the minumum and maximum bounds + * of a sheet.

+ * REFERENCE: PG 303 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class DimensionsRecord + extends Record +{ + public final static short sid = 0x200; + private int field_1_first_row; + private int field_2_last_row; // plus 1 + private short field_3_first_col; + private short field_4_last_col; + private short field_5_zero; // must be 0 (reserved) + + public DimensionsRecord() + { + } + + /** + * Constructs a Dimensions record and sets its fields appropriately. + * + * @param short id must be 0x200 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public DimensionsRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a Dimensions record and sets its fields appropriately. + * + * @param short id must be 0x200 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public DimensionsRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A valid DIMENSIONS RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_first_row = LittleEndian.getInt(data, 0 + offset); + field_2_last_row = LittleEndian.getInt(data, 4 + offset); + field_3_first_col = LittleEndian.getShort(data, 8 + offset); + field_4_last_col = LittleEndian.getShort(data, 10 + offset); + field_5_zero = LittleEndian.getShort(data, 12 + offset); + } + + /** + * set the first row number for the sheet + * @param row - first row on the sheet + */ + + public void setFirstRow(int row) + { + field_1_first_row = row; + } + + /** + * set the last row number for the sheet + * @param row - last row on the sheet + */ + + public void setLastRow(int row) + { + field_2_last_row = row; + } + + /** + * set the first column number for the sheet + * @param column - first column on the sheet + */ + + public void setFirstCol(short col) + { + field_3_first_col = col; + } + + /** + * set the last col number for the sheet + * @param column - last column on the sheet + */ + + public void setLastCol(short col) + { + field_4_last_col = col; + } + + /** + * get the first row number for the sheet + * @return row - first row on the sheet + */ + + public int getFirstRow() + { + return field_1_first_row; + } + + /** + * get the last row number for the sheet + * @return row - last row on the sheet + */ + + public int getLastRow() + { + return field_2_last_row; + } + + /** + * get the first column number for the sheet + * @return column - first column on the sheet + */ + + public short getFirstCol() + { + return field_3_first_col; + } + + /** + * get the last col number for the sheet + * @return column - last column on the sheet + */ + + public short getLastCol() + { + return field_4_last_col; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[DIMENSIONS]\n"); + buffer.append(" .firstrow = ") + .append(Integer.toHexString(getFirstRow())).append("\n"); + buffer.append(" .lastrow = ") + .append(Integer.toHexString(getLastRow())).append("\n"); + buffer.append(" .firstcol = ") + .append(Integer.toHexString(getFirstCol())).append("\n"); + buffer.append(" .lastcol = ") + .append(Integer.toHexString(getLastCol())).append("\n"); + buffer.append(" .zero = ") + .append(Integer.toHexString(field_5_zero)).append("\n"); + buffer.append("[/DIMENSIONS]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 14); + LittleEndian.putInt(data, 4 + offset, getFirstRow()); + LittleEndian.putInt(data, 8 + offset, getLastRow()); + LittleEndian.putShort(data, 12 + offset, getFirstCol()); + LittleEndian.putShort(data, 14 + offset, getLastCol()); + LittleEndian.putShort(data, 16 + offset, ( short ) 0); + return getRecordSize(); + } + + public int getRecordSize() + { + return 18; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/EOFRecord.java b/src/java/org/apache/poi/hssf/record/EOFRecord.java new file mode 100644 index 000000000..294422a18 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/EOFRecord.java @@ -0,0 +1,144 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * End Of File record. + *

+ * Description: Marks the end of records belonging to a particular object in the + * HSSF File

+ * REFERENCE: PG 307 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class EOFRecord + extends Record +{ + public final static short sid = 0x0A; + + public EOFRecord() + { + } + + /** + * Constructs a EOFRecord record and sets its fields appropriately. + * + * @param short id must be 0x0A or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public EOFRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a EOFRecord record and sets its fields appropriately. + * + * @param short id must be 0x0A or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public EOFRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT An EOF RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[EOF]\n"); + buffer.append("[/EOF]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0)); // no record info + return getRecordSize(); + } + + public int getRecordSize() + { + return 4; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/EndRecord.java b/src/java/org/apache/poi/hssf/record/EndRecord.java new file mode 100644 index 000000000..c6615e4de --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/EndRecord.java @@ -0,0 +1,143 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * The end record defines the end of a block of records for a (Graphing) + * data object. This record is matched with a corresponding BeginRecord. + * + * @see BeginRecord + * + * @author Glen Stampoultzis (gstamp at iprimus dot com dot au) + */ + +public class EndRecord + extends Record +{ + public static final short sid = 0x1034; + + public EndRecord() + { + } + + /** + * Constructs a EndRecord record and sets its fields appropriately. + * + * @param short id must be 0x1034 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public EndRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a EndRecord record and sets its fields appropriately. + * + * @param short id must be 0x1034 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public EndRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT An END RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[END]\n"); + buffer.append("[/END]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0)); // no record info + return getRecordSize(); + } + + public int getRecordSize() + { + return 4; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/ExtSSTInfoSubRecord.java b/src/java/org/apache/poi/hssf/record/ExtSSTInfoSubRecord.java new file mode 100644 index 000000000..e4ead5302 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/ExtSSTInfoSubRecord.java @@ -0,0 +1,164 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * ExtSSTInfoSubRecord.java + * + * Created on September 8, 2001, 8:37 PM + */ +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Extended SST table info subrecord

+ * contains the elements of "info" in the SST's array field

+ * WE HAVE VERY LITTLE INFORMATION ON HOW TO IMPLEMENT THIS RECORD! (EXTSSST)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + * @see org.apache.poi.hssf.record.ExtSSTRecord + */ + +public class ExtSSTInfoSubRecord + extends Record +{ + public final static short sid = + 0xFFF; // only here for conformance, doesn't really have an sid + private int field_1_stream_pos; // stream pointer to the SST record + private short field_2_bucket_sst_offset; // don't really understand this yet. + private short field_3_zero; // must be 0; + + /** Creates new ExtSSTInfoSubRecord */ + + public ExtSSTInfoSubRecord() + { + } + + public ExtSSTInfoSubRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + public ExtSSTInfoSubRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + + // do nothing + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_stream_pos = LittleEndian.getInt(data, 0 + offset); + field_2_bucket_sst_offset = LittleEndian.getShort(data, 4 + offset); + field_3_zero = LittleEndian.getShort(data, 6 + offset); + } + + public void setStreamPos(int pos) + { + field_1_stream_pos = pos; + } + + public void setBucketSSTOffset(short offset) + { + field_2_bucket_sst_offset = offset; + } + + public int getStreamPos() + { + return field_1_stream_pos; + } + + public short getBucketSSTOffset() + { + return field_2_bucket_sst_offset; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[EXTSST]\n"); + buffer.append(" .streampos = ") + .append(Integer.toHexString(getStreamPos())).append("\n"); + buffer.append(" .bucketsstoffset= ") + .append(Integer.toHexString(getBucketSSTOffset())).append("\n"); + buffer.append(" .zero = ") + .append(Integer.toHexString(field_3_zero)).append("\n"); + buffer.append("[/EXTSST]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putInt(data, 0 + offset, getStreamPos()); + LittleEndian.putShort(data, 4 + offset, getBucketSSTOffset()); + LittleEndian.putShort(data, 6 + offset, ( short ) 0); + return getRecordSize(); + } + + public int getRecordSize() + { + return 8; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/ExtSSTRecord.java b/src/java/org/apache/poi/hssf/record/ExtSSTRecord.java new file mode 100644 index 000000000..2221e6fab --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/ExtSSTRecord.java @@ -0,0 +1,214 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +import java.util.ArrayList; + +/** + * Title: Extended Static String Table

+ * Description: I really don't understand this thing... its supposed to be "a hash + * table for optimizing external copy operations" -- + *

+ * This sounds like a job for Marc "BitMaster" Johnson aka the + * "Hawaiian Master Chef".

+ * REFERENCE: PG 313 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + * @see org.apache.poi.hssf.record.ExtSSTInfoSubRecord + */ + +public class ExtSSTRecord + extends Record +{ + public final static short sid = 0xff; + private short field_1_strings_per_bucket; + private ArrayList field_2_sst_info; + + public ExtSSTRecord() + { + field_2_sst_info = new ArrayList(); + } + + /** + * Constructs a EOFRecord record and sets its fields appropriately. + * + * @param short id must be 0xff or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public ExtSSTRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a EOFRecord record and sets its fields appropriately. + * + * @param short id must be 0xff or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public ExtSSTRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT An EXTSST RECORD"); + } + } + + // this probably doesn't work but we don't really care at this point + protected void fillFields(byte [] data, short size, int offset) + { + field_2_sst_info = new ArrayList(); + field_1_strings_per_bucket = LittleEndian.getShort(data, 0 + offset); + for (int k = 2; k < ((data.length - offset) - size); k += 8) + { + byte[] tempdata = new byte[ 8 + offset ]; + + System.arraycopy(data, k, tempdata, 0, 8); + ExtSSTInfoSubRecord rec = new ExtSSTInfoSubRecord(( short ) 0, + ( short ) 8, tempdata); + + field_2_sst_info.add(rec); + } + } + + public void setNumStringsPerBucket(short numStrings) + { + field_1_strings_per_bucket = numStrings; + } + + public void addInfoRecord(ExtSSTInfoSubRecord rec) + { + field_2_sst_info.add(rec); + } + + public short getNumStringsPerBucket() + { + return field_1_strings_per_bucket; + } + + public int getNumInfoRecords() + { + return field_2_sst_info.size(); + } + + public ExtSSTInfoSubRecord getInfoRecordAt(int elem) + { + return ( ExtSSTInfoSubRecord ) field_2_sst_info.get(elem); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[EXTSST]\n"); + buffer.append(" .dsst = ") + .append(Integer.toHexString(getNumStringsPerBucket())) + .append("\n"); + buffer.append(" .numInfoRecords = ").append(getNumInfoRecords()) + .append("\n"); + for (int k = 0; k < getNumInfoRecords(); k++) + { + buffer.append(" .inforecord = ").append(k).append("\n"); + buffer.append(" .streampos = ") + .append(Integer + .toHexString(getInfoRecordAt(k).getStreamPos())).append("\n"); + buffer.append(" .sstoffset = ") + .append(Integer + .toHexString(getInfoRecordAt(k).getBucketSSTOffset())) + .append("\n"); + } + buffer.append("[/EXTSST]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + +// LittleEndian.putShort(data,2,(short)(2 + (getNumInfoRecords() *8))); + LittleEndian.putShort(data, 2 + offset, ( short ) (2 + (0x3fa - 2))); + int pos = 4; + + for (int k = 0; k < getNumInfoRecords(); k++) + { + System.arraycopy(getInfoRecordAt(k).serialize(), 0, data, + pos + offset, 8); + } + return getRecordSize(); + } + + public int getRecordSize() + { + return 6 + 0x3fa - 2; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/ExtendedFormatRecord.java b/src/java/org/apache/poi/hssf/record/ExtendedFormatRecord.java new file mode 100644 index 000000000..0d2fb0711 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/ExtendedFormatRecord.java @@ -0,0 +1,1826 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.BitField; +import org.apache.poi.util.LittleEndian; + +/** + * Title: Extended Format Record + * Description: Probably one of the more complex records. There are two breeds: + * Style and Cell. + *

+ * It should be noted that fields in the extended format record are + * somewhat arbitrary. Almost all of the fields are bit-level, but + * we name them as best as possible by functional group. In some + * places this is better than others. + *

+ * + * REFERENCE: PG 426 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class ExtendedFormatRecord + extends Record +{ + public final static short sid = 0xE0; + + // null constant + public final static short NULL = 0xfffffff0; + + // xf type + public final static short XF_STYLE = 1; + public final static short XF_CELL = 0; + + // borders + public final static short NONE = 0x0; + public final static short THIN = 0x1; + public final static short MEDIUM = 0x2; + public final static short DASHED = 0x3; + public final static short DOTTED = 0x4; + public final static short THICK = 0x5; + public final static short DOUBLE = 0x6; + public final static short HAIR = 0x7; + public final static short MEDIUM_DASHED = 0x8; + public final static short DASH_DOT = 0x9; + public final static short MEDIUM_DASH_DOT = 0xA; + public final static short DASH_DOT_DOT = 0xB; + public final static short MEDIUM_DASH_DOT_DOT = 0xC; + public final static short SLANTED_DASH_DOT = 0xD; + + // alignment + public final static short GENERAL = 0x0; + public final static short LEFT = 0x1; + public final static short CENTER = 0x2; + public final static short RIGHT = 0x3; + public final static short FILL = 0x4; + public final static short JUSTIFY = 0x5; + public final static short CENTER_SELECTION = 0x6; + + // vertical alignment + public final static short VERTICAL_TOP = 0x0; + public final static short VERTICAL_CENTER = 0x1; + public final static short VERTICAL_BOTTOM = 0x2; + public final static short VERTICAL_JUSTIFY = 0x3; + + // fields in BOTH style and Cell XF records + private short field_1_font_index; // not bit-mapped + private short field_2_format_index; // not bit-mapped + + // field_3_cell_options bit map + static final private BitField _locked = new BitField(0x0001); + static final private BitField _hidden = new BitField(0x0002); + static final private BitField _xf_type = new BitField(0x0004); + static final private BitField _123_prefix = new BitField(0x0008); + static final private BitField _parent_index = new BitField(0xFFF0); + private short field_3_cell_options; + + // field_4_alignment_options bit map + static final private BitField _alignment = new BitField(0x0007); + static final private BitField _wrap_text = new BitField(0x0008); + static final private BitField _vertical_alignment = new BitField(0x0070); + static final private BitField _justify_last = new BitField(0x0080); + static final private BitField _rotation = new BitField(0xFF00); + private short field_4_alignment_options; + + // field_5_indention_options + static final private BitField _indent = + new BitField(0x000F); + static final private BitField _shrink_to_fit = + new BitField(0x0010); + static final private BitField _merge_cells = + new BitField(0x0020); + static final private BitField _reading_order = + new BitField(0x00C0); + + // apparently bits 8 and 9 are unused + static final private BitField _indent_not_parent_format = + new BitField(0x0400); + static final private BitField _indent_not_parent_font = + new BitField(0x0800); + static final private BitField _indent_not_parent_alignment = + new BitField(0x1000); + static final private BitField _indent_not_parent_border = + new BitField(0x2000); + static final private BitField _indent_not_parent_pattern = + new BitField(0x4000); + static final private BitField _indent_not_parent_cell_options = + new BitField(0x8000); + private short field_5_indention_options; + + // field_6_border_options bit map + static final private BitField _border_left = new BitField(0x000F); + static final private BitField _border_right = new BitField(0x00F0); + static final private BitField _border_top = new BitField(0x0F00); + static final private BitField _border_bottom = new BitField(0xF000); + private short field_6_border_options; + + // all three of the following attributes are palette options + // field_7_palette_options bit map + static final private BitField _left_border_palette_idx = + new BitField(0x007F); + static final private BitField _right_border_palette_idx = + new BitField(0x3F80); + static final private BitField _diag = + new BitField(0xC000); + private short field_7_palette_options; + + // field_8_adtl_palette_options bit map + static final private BitField _top_border_palette_idx = + new BitField(0x0000007F); + static final private BitField _bottom_border_palette_idx = + new BitField(0x00003F80); + static final private BitField _adtl_diag = + new BitField(0x001fc000); + static final private BitField _adtl_diag_line_style = + new BitField(0x01e00000); + + // apparently bit 25 is unused + static final private BitField _adtl_fill_pattern = + new BitField(0xfc000000); + private int field_8_adtl_palette_options; // additional to avoid 2 + + // field_9_fill_palette_options bit map + static final private BitField _fill_foreground = new BitField(0x007F); + static final private BitField _fill_background = new BitField(0x3f80); + + // apparently bits 15 and 14 are unused + private short field_9_fill_palette_options; + + /** + * Constructor ExtendedFormatRecord + * + * + */ + + public ExtendedFormatRecord() + { + } + + /** + * Constructs an ExtendedFormat record and sets its fields appropriately. + * + * @param short id must be 0xE0 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public ExtendedFormatRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs an ExtendedFormat record and sets its fields appropriately. + * + * @param short id must be 0xE0 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public ExtendedFormatRecord(short id, short size, byte [] data, + int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A EXTENDED FORMAT RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_font_index = LittleEndian.getShort(data, + 0 + offset); + field_2_format_index = LittleEndian.getShort(data, + 2 + offset); + field_3_cell_options = LittleEndian.getShort(data, + 4 + offset); + field_4_alignment_options = LittleEndian.getShort(data, + 6 + offset); + field_5_indention_options = LittleEndian.getShort(data, + 8 + offset); + field_6_border_options = LittleEndian.getShort(data, + 10 + offset); + field_7_palette_options = LittleEndian.getShort(data, + 12 + offset); + field_8_adtl_palette_options = LittleEndian.getInt(data, 14 + offset); + field_9_fill_palette_options = LittleEndian.getShort(data, + 18 + offset); + } + + /** + * set the index to the FONT record (which font to use 0 based) + * + * + * @param index to the font + * @see org.apache.poi.hssf.record.FontRecord + */ + + public void setFontIndex(short index) + { + field_1_font_index = index; + } + + /** + * set the index to the Format record (which FORMAT to use 0-based) + * + * + * @param index to the format record + * @see org.apache.poi.hssf.record.FormatRecord + */ + + public void setFormatIndex(short index) + { + field_2_format_index = index; + } + + /** + * sets the options bitmask - you can also use corresponding option bit setters + * (see other methods that reference this one) + * + * + * @param options bitmask to set + * + */ + + public void setCellOptions(short options) + { + field_3_cell_options = options; + } + + // These are the bit fields in cell options + + /** + * set whether the cell is locked or not + * + * + * @param locked - if the cell is locked + * @see #setCellOptions(short) + */ + + public void setLocked(boolean locked) + { + field_3_cell_options = _locked.setShortBoolean(field_3_cell_options, + locked); + } + + /** + * set whether the cell is hidden or not + * + * + * @param hidden - if the cell is hidden + * @see #setCellOptions(short) + */ + + public void setHidden(boolean hidden) + { + field_3_cell_options = _hidden.setShortBoolean(field_3_cell_options, + hidden); + } + + /** + * set whether the cell is a cell or style XFRecord + * + * + * @param type - cell or style (0/1) + * @see #XF_STYLE + * @see #XF_CELL + * @see #setCellOptions(short) + */ + + public void setXFType(short type) + { + field_3_cell_options = _xf_type.setShortValue(field_3_cell_options, + type); + } + + /** + * set some old holdover from lotus 123. Who cares, its all over for Lotus. + * RIP Lotus. + * + * @param prefix - the lotus thing to set. + * @see #setCellOptions(short) + */ + + public void set123Prefix(boolean prefix) + { + field_3_cell_options = + _123_prefix.setShortBoolean(field_3_cell_options, prefix); + } + + // present in both but NULL except in cell records + + /** + * for cell XF types this is the parent style (usually 0/normal). For + * style this should be NULL. + * + * @param index of parent XF + * @see #NULL + * @see #setCellOptions(short) + */ + + public void setParentIndex(short parent) + { + field_3_cell_options = + _parent_index.setShortValue(field_3_cell_options, parent); + } + + // end bitfields in cell options + + /** + * set the alignment options bitmask. See corresponding bitsetter methods + * that reference this one. + * + * + * @param options - the bitmask to set + */ + + public void setAlignmentOptions(short options) + { + field_4_alignment_options = options; + } + + /** + * set the horizontal alignment of the cell. + * + * + * @param align - how to align the cell (see constants) + * @see #GENERAL + * @see #LEFT + * @see #CENTER + * @see #RIGHT + * @see #FILL + * @see #JUSTIFY + * @see #CENTER_SELECTION + * @see #setAlignmentOptions(short) + */ + + public void setAlignment(short align) + { + field_4_alignment_options = + _alignment.setShortValue(field_4_alignment_options, align); + } + + /** + * set whether to wrap the text in the cell + * + * + * @param wrapped - whether or not to wrap the cell text + * @see #setAlignmentOptions(short) + */ + + public void setWrapText(boolean wrapped) + { + field_4_alignment_options = + _wrap_text.setShortBoolean(field_4_alignment_options, wrapped); + } + + /** + * set the vertical alignment of text in the cell + * + * + * @param where to align the text + * @see #VERTICAL_TOP + * @see #VERTICAL_CENTER + * @see #VERTICAL_BOTTOM + * @see #VERTICAL_JUSTIFY + * + * @see #setAlignmentOptions(short) + */ + + public void setVerticalAlignment(short align) + { + field_4_alignment_options = + _vertical_alignment.setShortValue(field_4_alignment_options, + align); + } + + /** + * Dunno. Docs just say this is for far east versions.. (I'm guessing it + * justifies for right-to-left read languages) + * + * + * @param justify + * @see #setAlignmentOptions(short) + */ + + public void setJustifyLast(short justify) + { // for far east languages supported only for format always 0 for US + field_4_alignment_options = + _justify_last.setShortValue(field_4_alignment_options, justify); + } + + /** + * set the degree of rotation. (I've not actually seen this used anywhere) + * + * + * @param rotation the degree of rotation + * @see #setAlignmentOptions(short) + */ + + public void setRotation(short rotation) + { + field_4_alignment_options = + _rotation.setShortValue(field_4_alignment_options, rotation); + } + + /** + * set the indent options bitmask (see corresponding bitmask setters that reference + * this field) + * + * + * @param options bitmask to set. + * + */ + + public void setIndentionOptions(short options) + { + field_5_indention_options = options; + } + + // set bitfields for indention options + + /** + * set indention (not sure of the units, think its spaces) + * + * @param indent - how far to indent the cell + * @see #setIndentionOptions(short) + */ + + public void setIndent(short indent) + { + field_5_indention_options = + _indent.setShortValue(field_5_indention_options, indent); + } + + /** + * set whether to shrink the text to fit + * + * + * @param shrink - shrink to fit or not + * @see #setIndentionOptions(short) + */ + + public void setShrinkToFit(boolean shrink) + { + field_5_indention_options = + _shrink_to_fit.setShortBoolean(field_5_indention_options, shrink); + } + + /** + * set whether to merge cells + * + * + * @param merge - merge cells or not + * @see #setIndentionOptions(short) + */ + + public void setMergeCells(boolean merge) + { + field_5_indention_options = + _merge_cells.setShortBoolean(field_5_indention_options, merge); + } + + /** + * set the reading order for far east versions (0 - Context, 1 - Left to right, + * 2 - right to left) - We could use some help with support for the far east. + * + * @param order - the reading order (0,1,2) + * @see #setIndentionOptions(short) + */ + + public void setReadingOrder(short order) + { // only for far east always 0 in US + field_5_indention_options = + _reading_order.setShortValue(field_5_indention_options, order); + } + + /** + * set whether or not to use the format in this XF instead of the parent XF. + * + * + * @param parent - true if this XF has a different format value than its parent, + * false otherwise. + * @see #setIndentionOptions(short) + */ + + public void setIndentNotParentFormat(boolean parent) + { + field_5_indention_options = + _indent_not_parent_format + .setShortBoolean(field_5_indention_options, parent); + } + + /** + * set whether or not to use the font in this XF instead of the parent XF. + * + * + * @param font - true if this XF has a different font value than its parent, + * false otherwise. + * @see #setIndentionOptions(short) + */ + + public void setIndentNotParentFont(boolean font) + { + field_5_indention_options = + _indent_not_parent_font.setShortBoolean(field_5_indention_options, + font); + } + + /** + * set whether or not to use the alignment in this XF instead of the parent XF. + * + * + * @param alignment true if this XF has a different alignment value than its parent, + * false otherwise. + * @see #setIndentionOptions(short) + */ + + public void setIndentNotParentAlignment(boolean alignment) + { + field_5_indention_options = + _indent_not_parent_alignment + .setShortBoolean(field_5_indention_options, alignment); + } + + /** + * set whether or not to use the border in this XF instead of the parent XF. + * + * + * @param border - true if this XF has a different border value than its parent, + * false otherwise. + * @see #setIndentionOptions(short) + */ + + public void setIndentNotParentBorder(boolean border) + { + field_5_indention_options = + _indent_not_parent_border + .setShortBoolean(field_5_indention_options, border); + } + + /** + * set whether or not to use the pattern in this XF instead of the parent XF. + * (foregrount/background) + * + * @param pattern- true if this XF has a different pattern value than its parent, + * false otherwise. + * @see #setIndentionOptions(short) + */ + + public void setIndentNotParentPattern(boolean pattern) + { + field_5_indention_options = + _indent_not_parent_pattern + .setShortBoolean(field_5_indention_options, pattern); + } + + /** + * set whether or not to use the locking/hidden in this XF instead of the parent XF. + * + * + * @param options- true if this XF has a different locking or hidden value than its parent, + * false otherwise. + * @see #setIndentionOptions(short) + */ + + public void setIndentNotParentCellOptions(boolean options) + { + field_5_indention_options = + _indent_not_parent_cell_options + .setShortBoolean(field_5_indention_options, options); + } + + // end indention options bitmask sets + + /** + * set the border options bitmask (see the corresponding bitsetter methods + * that reference back to this one) + * + * @param options - the bit mask to set + * + */ + + public void setBorderOptions(short options) + { + field_6_border_options = options; + } + + // border options bitfields + + /** + * set the borderline style for the left border + * + * + * @param border - type of border for the left side of the cell + * @see #NONE + * @see #THIN + * @see #MEDIUM + * @see #DASHED + * @see #DOTTED + * @see #THICK + * @see #DOUBLE + * @see #HAIR + * @see #MEDIUM_DASHED + * @see #DASH_DOT + * @see #MEDIUM_DASH_DOT + * @see #DASH_DOT_DOT + * @see #MEDIUM_DASH_DOT_DOT + * @see #SLANTED_DASH_DOT + * @see #setBorderOptions(short) + */ + + public void setBorderLeft(short border) + { + field_6_border_options = + _border_left.setShortValue(field_6_border_options, border); + } + + /** + * set the border line style for the right border + * + * + * @param border - type of border for the right side of the cell + * @see #NONE + * @see #THIN + * @see #MEDIUM + * @see #DASHED + * @see #DOTTED + * @see #THICK + * @see #DOUBLE + * @see #HAIR + * @see #MEDIUM_DASHED + * @see #DASH_DOT + * @see #MEDIUM_DASH_DOT + * @see #DASH_DOT_DOT + * @see #MEDIUM_DASH_DOT_DOT + * @see #SLANTED_DASH_DOT + * @see #setBorderOptions(short) + */ + + public void setBorderRight(short border) + { + field_6_border_options = + _border_right.setShortValue(field_6_border_options, border); + } + + /** + * set the border line style for the top border + * + * + * @param border - type of border for the top of the cell + * @see #NONE + * @see #THIN + * @see #MEDIUM + * @see #DASHED + * @see #DOTTED + * @see #THICK + * @see #DOUBLE + * @see #HAIR + * @see #MEDIUM_DASHED + * @see #DASH_DOT + * @see #MEDIUM_DASH_DOT + * @see #DASH_DOT_DOT + * @see #MEDIUM_DASH_DOT_DOT + * @see #SLANTED_DASH_DOT + * @see #setBorderOptions(short) + */ + + public void setBorderTop(short border) + { + field_6_border_options = + _border_top.setShortValue(field_6_border_options, border); + } + + /** + * set the border line style for the bottom border + * + * + * @param border - type of border for the bottom of the cell + * @see #NONE + * @see #THIN + * @see #MEDIUM + * @see #DASHED + * @see #DOTTED + * @see #THICK + * @see #DOUBLE + * @see #HAIR + * @see #MEDIUM_DASHED + * @see #DASH_DOT + * @see #MEDIUM_DASH_DOT + * @see #DASH_DOT_DOT + * @see #MEDIUM_DASH_DOT_DOT + * @see #SLANTED_DASH_DOT + * @see #setBorderOptions(short) + */ + + public void setBorderBottom(short border) + { + field_6_border_options = + _border_bottom.setShortValue(field_6_border_options, border); + } + + // end border option bitfields + + /** + * set the palette options bitmask (see the individual bitsetter methods that + * reference this one) + * + * + * @param options - the bitmask to set + * + */ + + public void setPaletteOptions(short options) + { + field_7_palette_options = options; + } + + // bitfields for palette options + + /** + * set the palette index for the left border color + * + * + * @param border - palette index + * @see #setPaletteOptions(short) + */ + + public void setLeftBorderPaletteIdx(short border) + { + field_7_palette_options = + _left_border_palette_idx.setShortValue(field_7_palette_options, + border); + } + + /** + * set the palette index for the right border color + * + * + * @param border - palette index + * @see #setPaletteOptions(short) + */ + + public void setRightBorderPaletteIdx(short border) + { + field_7_palette_options = + _right_border_palette_idx.setShortValue(field_7_palette_options, + border); + } + + // i've no idea.. possible values are 1 for down, 2 for up and 3 for both...0 for none.. + // maybe a diagnal line? + + /** + * Not sure what this is for (maybe fill lines?) 1 = down, 2 = up, 3 = both, 0 for none.. + * + * + * @param diag - set whatever it is that this is. + * @see #setPaletteOptions(short) + */ + + public void setDiag(short diag) + { + field_7_palette_options = _diag.setShortValue(field_7_palette_options, + diag); + } + + // end of palette options + + /** + * set the additional palette options bitmask (see individual bitsetter methods + * that reference this method) + * + * + * @param options - bitmask to set + * + */ + + public void setAdtlPaletteOptions(short options) + { + field_8_adtl_palette_options = options; + } + + // bitfields for additional palette options + + /** + * set the palette index for the top border + * + * + * @param border - palette index + * @see #setAdtlPaletteOptions(short) + */ + + public void setTopBorderPaletteIdx(short border) + { + field_8_adtl_palette_options = + _top_border_palette_idx.setValue(field_8_adtl_palette_options, + border); + } + + /** + * set the palette index for the bottom border + * + * + * @param border - palette index + * @see #setAdtlPaletteOptions(short) + */ + + public void setBottomBorderPaletteIdx(short border) + { + field_8_adtl_palette_options = + _bottom_border_palette_idx.setValue(field_8_adtl_palette_options, + border); + } + + /** + * set for diagonal borders? No idea (its a palette color for the other function + * we didn't know what was?) + * + * + * @param diag - the palette index? + * @see #setAdtlPaletteOptions(short) + */ + + public void setAdtlDiag(short diag) + { + field_8_adtl_palette_options = + _adtl_diag.setValue(field_8_adtl_palette_options, diag); + } + + /** + * set the diagonal border line style? Who the heck ever heard of a diagonal border? + * + * + * @param diag - the line style + * @see #NONE + * @see #THIN + * @see #MEDIUM + * @see #DASHED + * @see #DOTTED + * @see #THICK + * @see #DOUBLE + * @see #HAIR + * @see #MEDIUM_DASHED + * @see #DASH_DOT + * @see #MEDIUM_DASH_DOT + * @see #DASH_DOT_DOT + * @see #MEDIUM_DASH_DOT_DOT + * @see #SLANTED_DASH_DOT + * @see #setAdtlPaletteOptions(short) + */ + + public void setAdtlDiagLineStyle(short diag) + { + field_8_adtl_palette_options = + _adtl_diag_line_style.setValue(field_8_adtl_palette_options, + diag); + } + + /** + * set the fill pattern - ??? + * + * + * @param fill - fill pattern?? + * @see #setAdtlPaletteOptions(short) + */ + + public void setAdtlFillPattern(short fill) + { + field_8_adtl_palette_options = + _adtl_fill_pattern.setValue(field_8_adtl_palette_options, fill); + } + + // end bitfields for additional palette options + + /** + * set the fill palette options bitmask (see + * + * + * @param options + * + */ + + public void setFillPaletteOptions(short options) + { + field_9_fill_palette_options = options; + } + + /** + * set the foreground palette color index + * + * + * @param color - palette index + * @see #setFillPaletteOptions(short) + */ + + public void setFillForeground(short color) + { + field_9_fill_palette_options = + _fill_foreground.setShortValue(field_9_fill_palette_options, + color); + } + + /** + * set the background palette color index + * + * + * @param color - palette index + * @see #setFillPaletteOptions(short) + */ + + public void setFillBackground(short color) + { + field_9_fill_palette_options = + _fill_background.setShortValue(field_9_fill_palette_options, + color); + } + + /** + * get the index to the FONT record (which font to use 0 based) + * + * + * @return index to the font + * @see org.apache.poi.hssf.record.FontRecord + */ + + public short getFontIndex() + { + return field_1_font_index; + } + + /** + * get the index to the Format record (which FORMAT to use 0-based) + * + * + * @return index to the format record + * @see org.apache.poi.hssf.record.FormatRecord + */ + + public short getFormatIndex() + { + return field_2_format_index; + } + + /** + * gets the options bitmask - you can also use corresponding option bit getters + * (see other methods that reference this one) + * + * + * @return options bitmask + * + */ + + public short getCellOptions() + { + return field_3_cell_options; + } + + // These are the bit fields in cell options + + /** + * get whether the cell is locked or not + * + * + * @return locked - if the cell is locked + * @see #getCellOptions() + */ + + public boolean isLocked() + { + return _locked.isSet(field_3_cell_options); + } + + /** + * get whether the cell is hidden or not + * + * + * @return hidden - if the cell is hidden + * @see #getCellOptions() + */ + + public boolean isHidden() + { + return _hidden.isSet(field_3_cell_options); + } + + /** + * get whether the cell is a cell or style XFRecord + * + * + * @return type - cell or style (0/1) + * @see #XF_STYLE + * @see #XF_CELL + * @see #getCellOptions() + */ + + public short getXFType() + { + return _xf_type.getShortValue(field_3_cell_options); + } + + /** + * get some old holdover from lotus 123. Who cares, its all over for Lotus. + * RIP Lotus. + * + * @return prefix - the lotus thing + * @see #getCellOptions() + */ + + public boolean get123Prefix() + { + return _123_prefix.isSet(field_3_cell_options); + } + + /** + * for cell XF types this is the parent style (usually 0/normal). For + * style this should be NULL. + * + * @return index of parent XF + * @see #NULL + * @see #getCellOptions() + */ + + public short getParentIndex() + { + return _parent_index.getShortValue(field_3_cell_options); + } + + // end bitfields in cell options + + /** + * get the alignment options bitmask. See corresponding bitgetter methods + * that reference this one. + * + * + * @return options - the bitmask + */ + + public short getAlignmentOptions() + { + return field_4_alignment_options; + } + + // bitfields in alignment options + + /** + * get the horizontal alignment of the cell. + * + * + * @return align - how to align the cell (see constants) + * @see #GENERAL + * @see #LEFT + * @see #CENTER + * @see #RIGHT + * @see #FILL + * @see #JUSTIFY + * @see #CENTER_SELECTION + * @see #getAlignmentOptions() + */ + + public short getAlignment() + { + return _alignment.getShortValue(field_4_alignment_options); + } + + /** + * get whether to wrap the text in the cell + * + * + * @return wrapped - whether or not to wrap the cell text + * @see #getAlignmentOptions() + */ + + public boolean getWrapText() + { + return _wrap_text.isSet(field_4_alignment_options); + } + + /** + * get the vertical alignment of text in the cell + * + * + * @return where to align the text + * @see #VERTICAL_TOP + * @see #VERTICAL_CENTER + * @see #VERTICAL_BOTTOM + * @see #VERTICAL_JUSTIFY + * + * @see #getAlignmentOptions() + */ + + public short getVerticalAlignment() + { + return _vertical_alignment.getShortValue(field_4_alignment_options); + } + + /** + * Dunno. Docs just say this is for far east versions.. (I'm guessing it + * justifies for right-to-left read languages) + * + * + * @return justify + * @see #getAlignmentOptions() + */ + + public short getJustifyLast() + { // for far east languages supported only for format always 0 for US + return _justify_last.getShortValue(field_4_alignment_options); + } + + /** + * get the degree of rotation. (I've not actually seen this used anywhere) + * + * + * @return rotation - the degree of rotation + * @see #getAlignmentOptions() + */ + + public short getRotation() + { + return _rotation.getShortValue(field_4_alignment_options); + } + + // end alignment options bitfields + + /** + * get the indent options bitmask (see corresponding bit getters that reference + * this field) + * + * + * @return options bitmask + * + */ + + public short getIndentionOptions() + { + return field_5_indention_options; + } + + // bitfields for indention options + + /** + * get indention (not sure of the units, think its spaces) + * + * @return indent - how far to indent the cell + * @see #getIndentionOptions() + */ + + public short getIndent() + { + return _indent.getShortValue(field_5_indention_options); + } + + /** + * get whether to shrink the text to fit + * + * + * @return shrink - shrink to fit or not + * @see #getIndentionOptions() + */ + + public boolean getShrinkToFit() + { + return _shrink_to_fit.isSet(field_5_indention_options); + } + + /** + * get whether to merge cells + * + * + * @return merge - merge cells or not + * @see #getIndentionOptions() + */ + + public boolean getMergeCells() + { + return _merge_cells.isSet(field_5_indention_options); + } + + /** + * get the reading order for far east versions (0 - Context, 1 - Left to right, + * 2 - right to left) - We could use some help with support for the far east. + * + * @return order - the reading order (0,1,2) + * @see #getIndentionOptions() + */ + + public short getReadingOrder() + { // only for far east always 0 in US + return _reading_order.getShortValue(field_5_indention_options); + } + + /** + * get whether or not to use the format in this XF instead of the parent XF. + * + * + * @return parent - true if this XF has a different format value than its parent, + * false otherwise. + * @see #getIndentionOptions() + */ + + public boolean isIndentNotParentFormat() + { + return _indent_not_parent_format.isSet(field_5_indention_options); + } + + /** + * get whether or not to use the font in this XF instead of the parent XF. + * + * + * @return font - true if this XF has a different font value than its parent, + * false otherwise. + * @see #getIndentionOptions() + */ + + public boolean isIndentNotParentFont() + { + return _indent_not_parent_font.isSet(field_5_indention_options); + } + + /** + * get whether or not to use the alignment in this XF instead of the parent XF. + * + * + * @return alignment true if this XF has a different alignment value than its parent, + * false otherwise. + * @see #getIndentionOptions() + */ + + public boolean isIndentNotParentAlignment() + { + return _indent_not_parent_alignment.isSet(field_5_indention_options); + } + + /** + * get whether or not to use the border in this XF instead of the parent XF. + * + * + * @return border - true if this XF has a different border value than its parent, + * false otherwise. + * @see #getIndentionOptions() + */ + + public boolean isIndentNotParentBorder() + { + return _indent_not_parent_border.isSet(field_5_indention_options); + } + + /** + * get whether or not to use the pattern in this XF instead of the parent XF. + * (foregrount/background) + * + * @return pattern- true if this XF has a different pattern value than its parent, + * false otherwise. + * @see #getIndentionOptions() + */ + + public boolean isIndentNotParentPattern() + { + return _indent_not_parent_pattern.isSet(field_5_indention_options); + } + + /** + * get whether or not to use the locking/hidden in this XF instead of the parent XF. + * + * + * @return options- true if this XF has a different locking or hidden value than its parent, + * false otherwise. + * @see #getIndentionOptions() + */ + + public boolean isIndentNotParentCellOptions() + { + return _indent_not_parent_cell_options + .isSet(field_5_indention_options); + } + + // end of bitfields for indention options + // border options + + /** + * get the border options bitmask (see the corresponding bit getter methods + * that reference back to this one) + * + * @return options - the bit mask to set + * + */ + + public short getBorderOptions() + { + return field_6_border_options; + } + + // bitfields for border options + + /** + * get the borderline style for the left border + * + * + * @return border - type of border for the left side of the cell + * @see #NONE + * @see #THIN + * @see #MEDIUM + * @see #DASHED + * @see #DOTTED + * @see #THICK + * @see #DOUBLE + * @see #HAIR + * @see #MEDIUM_DASHED + * @see #DASH_DOT + * @see #MEDIUM_DASH_DOT + * @see #DASH_DOT_DOT + * @see #MEDIUM_DASH_DOT_DOT + * @see #SLANTED_DASH_DOT + * @see #getBorderOptions() + */ + + public short getBorderLeft() + { + return _border_left.getShortValue(field_6_border_options); + } + + /** + * get the borderline style for the right border + * + * + * @return border - type of border for the right side of the cell + * @see #NONE + * @see #THIN + * @see #MEDIUM + * @see #DASHED + * @see #DOTTED + * @see #THICK + * @see #DOUBLE + * @see #HAIR + * @see #MEDIUM_DASHED + * @see #DASH_DOT + * @see #MEDIUM_DASH_DOT + * @see #DASH_DOT_DOT + * @see #MEDIUM_DASH_DOT_DOT + * @see #SLANTED_DASH_DOT + * @see #getBorderOptions() + */ + + public short getBorderRight() + { + return _border_right.getShortValue(field_6_border_options); + } + + /** + * get the borderline style for the top border + * + * + * @return border - type of border for the top of the cell + * @see #NONE + * @see #THIN + * @see #MEDIUM + * @see #DASHED + * @see #DOTTED + * @see #THICK + * @see #DOUBLE + * @see #HAIR + * @see #MEDIUM_DASHED + * @see #DASH_DOT + * @see #MEDIUM_DASH_DOT + * @see #DASH_DOT_DOT + * @see #MEDIUM_DASH_DOT_DOT + * @see #SLANTED_DASH_DOT + * @see #getBorderOptions() + */ + + public short getBorderTop() + { + return _border_top.getShortValue(field_6_border_options); + } + + /** + * get the borderline style for the bottom border + * + * + * @return border - type of border for the bottom of the cell + * @see #NONE + * @see #THIN + * @see #MEDIUM + * @see #DASHED + * @see #DOTTED + * @see #THICK + * @see #DOUBLE + * @see #HAIR + * @see #MEDIUM_DASHED + * @see #DASH_DOT + * @see #MEDIUM_DASH_DOT + * @see #DASH_DOT_DOT + * @see #MEDIUM_DASH_DOT_DOT + * @see #SLANTED_DASH_DOT + * @see #getBorderOptions() + */ + + public short getBorderBottom() + { + return _border_bottom.getShortValue(field_6_border_options); + } + + // record types -- palette options + + /** + * get the palette options bitmask (see the individual bit getter methods that + * reference this one) + * + * + * @return options - the bitmask + * + */ + + public short getPaletteOptions() + { + return field_7_palette_options; + } + + // bitfields for palette options + + /** + * get the palette index for the left border color + * + * + * @return border - palette index + * @see #getPaletteOptions() + */ + + public short getLeftBorderPaletteIdx() + { + return _left_border_palette_idx + .getShortValue(field_7_palette_options); + } + + /** + * get the palette index for the right border color + * + * + * @return border - palette index + * @see #getPaletteOptions() + */ + + public short getRightBorderPaletteIdx() + { + return _right_border_palette_idx + .getShortValue(field_7_palette_options); + } + + // i've no idea.. possible values are 1 for down, 2 for up and 3 for both...0 for none.. + // maybe a diagnal line? + + /** + * Not sure what this is for (maybe fill lines?) 1 = down, 2 = up, 3 = both, 0 for none.. + * + * + * @return diag - whatever it is that this is. + * @see #getPaletteOptions() + */ + + public short getDiag() + { + return _diag.getShortValue(field_7_palette_options); + } + + // end of style palette options + // additional palette options + + /** + * get the additional palette options bitmask (see individual bit getter methods + * that reference this method) + * + * + * @return options - bitmask to set + * + */ + + public int getAdtlPaletteOptions() + { + return field_8_adtl_palette_options; + } + + // bitfields for additional palette options + + /** + * get the palette index for the top border + * + * + * @return border - palette index + * @see #getAdtlPaletteOptions() + */ + + public short getTopBorderPaletteIdx() + { + return ( short ) _top_border_palette_idx + .getValue(field_8_adtl_palette_options); + } + + /** + * get the palette index for the bottom border + * + * + * @return border - palette index + * @see #getAdtlPaletteOptions() + */ + + public short getBottomBorderPaletteIdx() + { + return ( short ) _bottom_border_palette_idx + .getValue(field_8_adtl_palette_options); + } + + /** + * get for diagonal borders? No idea (its a palette color for the other function + * we didn't know what was?) + * + * + * @return diag - the palette index? + * @see #getAdtlPaletteOptions() + */ + + public short getAdtlDiag() + { + return ( short ) _adtl_diag.getValue(field_8_adtl_palette_options); + } + + /** + * get the diagonal border line style? Who the heck ever heard of a diagonal border? + * + * + * @return diag - the line style + * @see #NONE + * @see #THIN + * @see #MEDIUM + * @see #DASHED + * @see #DOTTED + * @see #THICK + * @see #DOUBLE + * @see #HAIR + * @see #MEDIUM_DASHED + * @see #DASH_DOT + * @see #MEDIUM_DASH_DOT + * @see #DASH_DOT_DOT + * @see #MEDIUM_DASH_DOT_DOT + * @see #SLANTED_DASH_DOT + * @see #getAdtlPaletteOptions() + */ + + public short getAdtlDiagLineStyle() + { + return ( short ) _adtl_diag_line_style + .getValue(field_8_adtl_palette_options); + } + + /** + * get the additional fill pattern - ??? + * + * + * @return fill - fill pattern?? + * @see #getAdtlPaletteOptions() + */ + + public short getAdtlFillPattern() + { + return ( short ) _adtl_fill_pattern + .getValue(field_8_adtl_palette_options); + } + + // end bitfields for additional palette options + // fill palette options + + /** + * get the fill palette options bitmask (see indivdual bit getters that + * reference this method) + * + * @return options + * + */ + + public short getFillPaletteOptions() + { + return field_9_fill_palette_options; + } + + // bitfields for fill palette options + + /** + * get the foreground palette color index + * + * + * @return color - palette index + * @see #getFillPaletteOptions() + */ + + public short getFillForeground() + { + return _fill_foreground.getShortValue(field_9_fill_palette_options); + } + + /** + * get the background palette color index + * + * + * @param color - palette index + * @see #getFillPaletteOptions() + */ + + public short getFillBackground() + { + return _fill_background.getShortValue(field_9_fill_palette_options); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[EXTENDEDFORMAT]\n"); + if (getXFType() == XF_STYLE) + { + buffer.append(" STYLE_RECORD_TYPE\n"); + } + else if (getXFType() == XF_CELL) + { + buffer.append(" CELL_RECORD_TYPE\n"); + } + buffer.append(" .fontindex = ") + .append(Integer.toHexString(getFontIndex())).append("\n"); + buffer.append(" .formatindex = ") + .append(Integer.toHexString(getFormatIndex())).append("\n"); + buffer.append(" .celloptions = ") + .append(Integer.toHexString(getCellOptions())).append("\n"); + buffer.append(" .islocked = ").append(isLocked()) + .append("\n"); + buffer.append(" .ishidden = ").append(isHidden()) + .append("\n"); + buffer.append(" .recordtype= ") + .append(Integer.toHexString(getXFType())).append("\n"); + buffer.append(" .parentidx = ") + .append(Integer.toHexString(getParentIndex())).append("\n"); + buffer.append(" .alignmentoptions= ") + .append(Integer.toHexString(getAlignmentOptions())).append("\n"); + buffer.append(" .alignment = ").append(getAlignment()) + .append("\n"); + buffer.append(" .wraptext = ").append(getWrapText()) + .append("\n"); + buffer.append(" .valignment= ") + .append(Integer.toHexString(getVerticalAlignment())).append("\n"); + buffer.append(" .justlast = ") + .append(Integer.toHexString(getJustifyLast())).append("\n"); + buffer.append(" .rotation = ") + .append(Integer.toHexString(getRotation())).append("\n"); + buffer.append(" .indentionoptions= ") + .append(Integer.toHexString(getIndentionOptions())).append("\n"); + buffer.append(" .indent = ") + .append(Integer.toHexString(getIndent())).append("\n"); + buffer.append(" .shrinktoft= ").append(getShrinkToFit()) + .append("\n"); + buffer.append(" .mergecells= ").append(getMergeCells()) + .append("\n"); + buffer.append(" .readngordr= ") + .append(Integer.toHexString(getReadingOrder())).append("\n"); + buffer.append(" .formatflag= ") + .append(isIndentNotParentFormat()).append("\n"); + buffer.append(" .fontflag = ") + .append(isIndentNotParentFont()).append("\n"); + buffer.append(" .prntalgnmt= ") + .append(isIndentNotParentAlignment()).append("\n"); + buffer.append(" .borderflag= ") + .append(isIndentNotParentBorder()).append("\n"); + buffer.append(" .paternflag= ") + .append(isIndentNotParentPattern()).append("\n"); + buffer.append(" .celloption= ") + .append(isIndentNotParentCellOptions()).append("\n"); + buffer.append(" .borderoptns = ") + .append(Integer.toHexString(getBorderOptions())).append("\n"); + buffer.append(" .lftln = ") + .append(Integer.toHexString(getBorderLeft())).append("\n"); + buffer.append(" .rgtln = ") + .append(Integer.toHexString(getBorderRight())).append("\n"); + buffer.append(" .topln = ") + .append(Integer.toHexString(getBorderTop())).append("\n"); + buffer.append(" .btmln = ") + .append(Integer.toHexString(getBorderBottom())).append("\n"); + buffer.append(" .paleteoptns = ") + .append(Integer.toHexString(getPaletteOptions())).append("\n"); + buffer.append(" .leftborder= ") + .append(Integer.toHexString(getLeftBorderPaletteIdx())) + .append("\n"); + buffer.append(" .rghtborder= ") + .append(Integer.toHexString(getRightBorderPaletteIdx())) + .append("\n"); + buffer.append(" .diag = ") + .append(Integer.toHexString(getDiag())).append("\n"); + buffer.append(" .paleteoptn2 = ") + .append(Integer.toHexString(getAdtlPaletteOptions())) + .append("\n"); + buffer.append(" .topborder = ") + .append(Integer.toHexString(getTopBorderPaletteIdx())) + .append("\n"); + buffer.append(" .botmborder= ") + .append(Integer.toHexString(getBottomBorderPaletteIdx())) + .append("\n"); + buffer.append(" .adtldiag = ") + .append(Integer.toHexString(getAdtlDiag())).append("\n"); + buffer.append(" .diaglnstyl= ") + .append(Integer.toHexString(getAdtlDiagLineStyle())).append("\n"); + buffer.append(" .fillpattrn= ") + .append(Integer.toHexString(getAdtlFillPattern())).append("\n"); + buffer.append(" .fillpaloptn = ") + .append(Integer.toHexString(getFillPaletteOptions())) + .append("\n"); + buffer.append(" .foreground= ") + .append(Integer.toHexString(getFillForeground())).append("\n"); + buffer.append(" .background= ") + .append(Integer.toHexString(getFillBackground())).append("\n"); + buffer.append("[/EXTENDEDFORMAT]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + ( short ) (20)); // 24 - 4(sid/len) + LittleEndian.putShort(data, 4 + offset, getFontIndex()); + LittleEndian.putShort(data, 6 + offset, getFormatIndex()); + LittleEndian.putShort(data, 8 + offset, getCellOptions()); + LittleEndian.putShort(data, 10 + offset, getAlignmentOptions()); + LittleEndian.putShort(data, 12 + offset, getIndentionOptions()); + LittleEndian.putShort(data, 14 + offset, getBorderOptions()); + LittleEndian.putShort(data, 16 + offset, getPaletteOptions()); + LittleEndian.putInt(data, 18 + offset, getAdtlPaletteOptions()); + LittleEndian.putShort(data, 22 + offset, getFillPaletteOptions()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 24; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/FnGroupCountRecord.java b/src/java/org/apache/poi/hssf/record/FnGroupCountRecord.java new file mode 100644 index 000000000..069df5544 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/FnGroupCountRecord.java @@ -0,0 +1,176 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Function Group Count Record

+ * Description: Number of built in function groups in the current version of the + * Spreadsheet (probably only used on Windoze)

+ * REFERENCE: PG 315 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class FnGroupCountRecord + extends Record +{ + public final static short sid = 0x9c; + + /** + * suggested default (14 dec) + */ + + public final static short COUNT = 14; + private short field_1_count; + + public FnGroupCountRecord() + { + } + + /** + * Constructs a FnGroupCount record and sets its fields appropriately. + * + * @param short id must be 0x9c or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public FnGroupCountRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a FnGroupCount record and sets its fields appropriately. + * + * @param short id must be 0x9c or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public FnGroupCountRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A FNGROUPCOUNT RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_count = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set the number of built-in functions + * + * @param count - number of functions + */ + + public void setCount(short count) + { + field_1_count = count; + } + + /** + * get the number of built-in functions + * + * @return number of built-in functions + */ + + public short getCount() + { + return field_1_count; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[FNGROUPCOUNT]\n"); + buffer.append(" .count = ").append(getCount()) + .append("\n"); + buffer.append("[/FNGROUPCOUNT]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, getCount()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/FontRecord.java b/src/java/org/apache/poi/hssf/record/FontRecord.java new file mode 100644 index 000000000..9996a8be5 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/FontRecord.java @@ -0,0 +1,594 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.StringUtil; +import org.apache.poi.util.BitField; + +/** + * Title: Font Record - descrbes a font in the workbook (index = 0-3,5-infinity - skip 4)

+ * Description: An element in the Font Table

+ * REFERENCE: PG 315 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class FontRecord + extends Record +{ + public final static short sid = + 0x31; // docs are wrong (0x231 Microsoft Support site article Q184647) + public final static short SS_NONE = 0; + public final static short SS_SUPER = 1; + public final static short SS_SUB = 2; + public final static byte U_NONE = 0; + public final static byte U_SINGLE = 1; + public final static byte U_DOUBLE = 2; + public final static byte U_SINGLE_ACCOUNTING = 0x21; + public final static byte U_DOUBLE_ACCOUNTING = 0x22; + private short field_1_font_height; // in units of .05 of a point + private short field_2_attributes; + + // 0 0x01 - Reserved bit must be 0 + static final private BitField italic = + new BitField(0x02); // is this font in italics + + // 2 0x04 - reserved bit must be 0 + static final private BitField strikeout = + new BitField(0x08); // is this font has a line through the center + static final private BitField macoutline = new BitField( + 0x10); // some weird macintosh thing....but who understands those mac people anyhow + static final private BitField macshadow = new BitField( + 0x20); // some weird macintosh thing....but who understands those mac people anyhow + + // 7-6 - reserved bits must be 0 + // the rest is unused + private short field_3_color_palette_index; + private short field_4_bold_weight; + private short field_5_super_sub_script; // 00none/01super/02sub + private byte field_6_underline; // 00none/01single/02double/21singleaccounting/22doubleaccounting + private byte field_7_family; // ?? defined by windows api logfont structure? + private byte field_8_charset; // ?? defined by windows api logfont structure? + private byte field_9_zero = 0; // must be 0 + private byte field_10_font_name_len; // length of the font name + private String field_11_font_name; // whoa...the font name + + public FontRecord() + { + } + + /** + * Constructs a Font record and sets its fields appropriately. + * + * @param short id must be 0x31 (NOT 0x231 see MSKB #Q184647 for an "explanation of + * this bug in the documentation) or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public FontRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a Font record and sets its fields appropriately. + * + * @param short id must be 0x31 (NOT 0x231 see MSKB #Q184647 for an "explanation of + * this bug in the documentation) or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public FontRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A FONT RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_font_height = LittleEndian.getShort(data, 0 + offset); + field_2_attributes = LittleEndian.getShort(data, 2 + offset); + field_3_color_palette_index = LittleEndian.getShort(data, 4 + offset); + field_4_bold_weight = LittleEndian.getShort(data, 6 + offset); + field_5_super_sub_script = LittleEndian.getShort(data, 8 + offset); + field_6_underline = data[ 10 + offset ]; + field_7_family = data[ 11 + offset ]; + field_8_charset = data[ 12 + offset ]; + field_9_zero = data[ 13 + offset ]; + field_10_font_name_len = data[ 14 + offset ]; + if (field_10_font_name_len > 0) + { + if (data[ 15 ] == 0) + { // is compressed unicode + field_11_font_name = new String(data, 16, + field_10_font_name_len); + } + else + { // is not compressed unicode + field_11_font_name = StringUtil.getFromUnicode(data, 15, + field_10_font_name_len); + } + } + } + + /** + * sets the height of the font in 1/20th point units + * + * @param fontheight (in points/20) + */ + + public void setFontHeight(short height) + { + field_1_font_height = height; + } + + /** + * set the font attributes (see individual bit setters that reference this method) + * + * @param attribute the bitmask to set + */ + + public void setAttributes(short attributes) + { + field_2_attributes = attributes; + } + + // attributes bitfields + + /** + * set the font to be italics or not + * + * @param italics - whether the font is italics or not + * @see #setAttributes(short) + */ + + public void setItalic(boolean italics) + { + italic.setShortBoolean(field_2_attributes, italics); + } + + /** + * set the font to be stricken out or not + * + * @param strike - whether the font is stricken out or not + * @see #setAttributes(short) + */ + + public void setStrikeout(boolean strike) + { + strikeout.setShortBoolean(field_2_attributes, strike); + } + + /** + * whether to use the mac outline font style thing (mac only) - Some mac person + * should comment this instead of me doing it (since I have no idea) + * + * @param mac - whether to do that mac font outline thing or not + * @see #setAttributes(short) + */ + + public void setMacoutline(boolean mac) + { + macoutline.setShortBoolean(field_2_attributes, mac); + } + + /** + * whether to use the mac shado font style thing (mac only) - Some mac person + * should comment this instead of me doing it (since I have no idea) + * + * @param mac - whether to do that mac font shadow thing or not + * @see #setAttributes(short) + */ + + public void setMacshadow(boolean mac) + { + macshadow.setShortBoolean(field_2_attributes, mac); + } + + /** + * set the font's color palette index + * + * @param cpi - font color index + */ + + public void setColorPaletteIndex(short cpi) + { + field_3_color_palette_index = cpi; + } + + /** + * set the bold weight for this font (100-1000dec or 0x64-0x3e8). Default is + * 0x190 for normal and 0x2bc for bold + * + * @param bw - a number between 100-1000 for the fonts "boldness" + */ + + public void setBoldWeight(short bw) + { + field_4_bold_weight = bw; + } + + /** + * set the type of super or subscript for the font + * + * @param super or subscript option + * @see #SS_NONE + * @see #SS_SUPER + * @see #SS_SUB + */ + + public void setSuperSubScript(short sss) + { + field_5_super_sub_script = sss; + } + + /** + * set the type of underlining for the font + * + * @param super or subscript option + * + * @see #U_NONE + * @see #U_SINGLE + * @see #U_DOUBLE + * @see #U_SINGLE_ACCOUNTING + * @see #U_DOUBLE_ACCOUNTING + */ + + public void setUnderline(byte u) + { + field_6_underline = u; + } + + /** + * set the font family (TODO) + * + * @param family + */ + + public void setFamily(byte f) + { + field_7_family = f; + } + + /** + * set the character set + * + * @param charset - characterset + */ + + public void setCharset(byte charset) + { + field_8_charset = charset; + } + + /** + * set the length of the fontname string + * + * @param length of the font name + * @see #setFontName(String) + */ + + public void setFontNameLength(byte len) + { + field_10_font_name_len = len; + } + + /** + * set the name of the font + * + * @param fn - name of the font (i.e. "Arial") + */ + + public void setFontName(String fn) + { + field_11_font_name = fn; + } + + /** + * gets the height of the font in 1/20th point units + * + * @return fontheight (in points/20) + */ + + public short getFontHeight() + { + return field_1_font_height; + } + + /** + * get the font attributes (see individual bit getters that reference this method) + * + * @return attribute - the bitmask + */ + + public short getAttributes() + { + return field_2_attributes; + } + + /** + * get whether the font is to be italics or not + * + * @return italics - whether the font is italics or not + * @see #getAttributes() + */ + + public boolean isItalic() + { + return italic.isSet(field_2_attributes); + } + + /** + * get whether the font is to be stricken out or not + * + * @return strike - whether the font is stricken out or not + * @see #getAttributes() + */ + + public boolean isStruckout() + { + return strikeout.isSet(field_2_attributes); + } + + /** + * whether to use the mac outline font style thing (mac only) - Some mac person + * should comment this instead of me doing it (since I have no idea) + * + * @return mac - whether to do that mac font outline thing or not + * @see #getAttributes() + */ + + public boolean isMacoutlined() + { + return macoutline.isSet(field_2_attributes); + } + + /** + * whether to use the mac shado font style thing (mac only) - Some mac person + * should comment this instead of me doing it (since I have no idea) + * + * @return mac - whether to do that mac font shadow thing or not + * @see #getAttributes() + */ + + public boolean isMacshadowed() + { + return macshadow.isSet(field_2_attributes); + } + + /** + * get the font's color palette index + * + * @return cpi - font color index + */ + + public short getColorPaletteIndex() + { + return field_3_color_palette_index; + } + + /** + * get the bold weight for this font (100-1000dec or 0x64-0x3e8). Default is + * 0x190 for normal and 0x2bc for bold + * + * @return bw - a number between 100-1000 for the fonts "boldness" + */ + + public short getBoldWeight() + { + return field_4_bold_weight; + } + + /** + * get the type of super or subscript for the font + * + * @return super or subscript option + * @see #SS_NONE + * @see #SS_SUPER + * @see #SS_SUB + */ + + public short getSuperSubScript() + { + return field_5_super_sub_script; + } + + /** + * get the type of underlining for the font + * + * @return super or subscript option + * + * @see #U_NONE + * @see #U_SINGLE + * @see #U_DOUBLE + * @see #U_SINGLE_ACCOUNTING + * @see #U_DOUBLE_ACCOUNTING + */ + + public byte getUnderline() + { + return field_6_underline; + } + + /** + * get the font family (TODO) + * + * @return family + */ + + public byte getFamily() + { + return field_7_family; + } + + /** + * get the character set + * + * @return charset - characterset + */ + + public byte getCharset() + { + return field_8_charset; + } + + /** + * get the length of the fontname string + * + * @return length of the font name + * @see #getFontName() + */ + + public byte getFontNameLength() + { + return field_10_font_name_len; + } + + /** + * get the name of the font + * + * @return fn - name of the font (i.e. "Arial") + */ + + public String getFontName() + { + return field_11_font_name; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[FONT]\n"); + buffer.append(" .fontheight = ") + .append(Integer.toHexString(getFontHeight())).append("\n"); + buffer.append(" .attributes = ") + .append(Integer.toHexString(getAttributes())).append("\n"); + buffer.append(" .italic = ").append(isItalic()) + .append("\n"); + buffer.append(" .strikout = ").append(isStruckout()) + .append("\n"); + buffer.append(" .macoutlined= ").append(isMacoutlined()) + .append("\n"); + buffer.append(" .macshadowed= ").append(isMacshadowed()) + .append("\n"); + buffer.append(" .colorpalette = ") + .append(Integer.toHexString(getColorPaletteIndex())).append("\n"); + buffer.append(" .boldweight = ") + .append(Integer.toHexString(getBoldWeight())).append("\n"); + buffer.append(" .supersubscript = ") + .append(Integer.toHexString(getSuperSubScript())).append("\n"); + buffer.append(" .underline = ") + .append(Integer.toHexString(getUnderline())).append("\n"); + buffer.append(" .family = ") + .append(Integer.toHexString(getFamily())).append("\n"); + buffer.append(" .charset = ") + .append(Integer.toHexString(getCharset())).append("\n"); + buffer.append(" .namelength = ") + .append(Integer.toHexString(getFontNameLength())).append("\n"); + buffer.append(" .fontname = ").append(getFontName()) + .append("\n"); + buffer.append("[/FONT]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + int realflen = getFontNameLength() * 2; + + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort( + data, 2 + offset, + ( short ) (15 + realflen + + 1)); // 19 - 4 (sid/len) + font name length = datasize + + // undocumented single byte (1) + LittleEndian.putShort(data, 4 + offset, getFontHeight()); + LittleEndian.putShort(data, 6 + offset, getAttributes()); + LittleEndian.putShort(data, 8 + offset, getColorPaletteIndex()); + LittleEndian.putShort(data, 10 + offset, getBoldWeight()); + LittleEndian.putShort(data, 12 + offset, getSuperSubScript()); + data[ 14 + offset ] = getUnderline(); + data[ 15 + offset ] = getFamily(); + data[ 16 + offset ] = getCharset(); + data[ 17 + offset ] = (( byte ) 0); + data[ 18 + offset ] = getFontNameLength(); + data[ 19 + offset ] = ( byte ) 1; + StringUtil.putUncompressedUnicode(getFontName(), data, 20 + offset); + return getRecordSize(); + } + + public int getRecordSize() + { + return (getFontNameLength() * 2) + 20; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/FooterRecord.java b/src/java/org/apache/poi/hssf/record/FooterRecord.java new file mode 100644 index 000000000..20e8aff77 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/FooterRecord.java @@ -0,0 +1,220 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.StringUtil; + +/** + * Title: Footer Record

+ * Description: Specifies the footer for a sheet

+ * REFERENCE: PG 317 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class FooterRecord + extends Record +{ + public final static short sid = 0x15; + private byte field_1_footer_len; + private String field_2_footer; + + public FooterRecord() + { + } + + /** + * Constructs a FooterRecord record and sets its fields appropriately. + * + * @param short id must be 0x15 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public FooterRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a FooterRecord record and sets its fields appropriately. + * + * @param short id must be 0x15 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public FooterRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A FooterRECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + if (size > 0) + { + field_1_footer_len = data[ 0 + offset ]; + field_2_footer = new String(data, 1 + offset, + ( int ) field_1_footer_len); + } + } + + /** + * set the length of the footer string + * + * @param length of the footer string + * @see #setFooter(String) + */ + + public void setFooterLength(byte len) + { + field_1_footer_len = len; + } + + /** + * set the footer string + * + * @param footer string to display + * @see #setFooterLength(byte) + */ + + public void setFooter(String footer) + { + field_2_footer = footer; + } + + /** + * get the length of the footer string + * + * @return length of the footer string + * @see #getFooter() + */ + + public byte getFooterLength() + { + return field_1_footer_len; + } + + /** + * get the footer string + * + * @return footer string to display + * @see #getFooterLength() + */ + + public String getFooter() + { + return field_2_footer; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[FOOTER]\n"); + buffer.append(" .footerlen = ") + .append(Integer.toHexString(getFooterLength())).append("\n"); + buffer.append(" .footer = ").append(getFooter()) + .append("\n"); + buffer.append("[/FOOTER]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + int len = 4; + + if (getFooterLength() > 0) + { + len++; + } + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + ( short ) ((len - 4) + getFooterLength())); + if (getFooterLength() > 0) + { + data[ 4 + offset ] = getFooterLength(); + StringUtil.putCompressedUnicode(getFooter(), data, 5 + offset); + } + return getRecordSize(); + } + + public int getRecordSize() + { + int retval = 4; + + if (getFooterLength() > 0) + { + retval++; + } + return retval + getFooterLength(); + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/FormatRecord.java b/src/java/org/apache/poi/hssf/record/FormatRecord.java new file mode 100644 index 000000000..d42177d45 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/FormatRecord.java @@ -0,0 +1,240 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.StringUtil; + +/** + * Title: Format Record

+ * Description: describes a number format -- those goofy strings like $(#,###)

+ * + * REFERENCE: PG 317 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class FormatRecord + extends Record +{ + public final static short sid = 0x41e; + private short field_1_index_code; + private byte field_2_formatstring_len; + private short field_3_zero; // undocumented 2 bytes of 0 + private String field_4_formatstring; + + public FormatRecord() + { + } + + /** + * Constructs a Format record and sets its fields appropriately. + * + * @param short id must be 0x41e or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public FormatRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a Format record and sets its fields appropriately. + * + * @param short id must be 0x41e or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public FormatRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A FORMAT RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_index_code = LittleEndian.getShort(data, 0 + offset); + field_2_formatstring_len = data[ 2 + offset ]; + field_3_zero = LittleEndian.getShort(data, 3 + offset); + field_4_formatstring = new String(data, 5 + offset, + field_2_formatstring_len); + } + + /** + * set the format index code (for built in formats) + * + * @param the format index code + * @see org.apache.poi.hssf.model.Workbook + */ + + public void setIndexCode(short index) + { + field_1_index_code = index; + } + + /** + * set the format string length + * + * @param the length of the format string + * @see #setFormatString(String) + */ + + public void setFormatStringLength(byte len) + { + field_2_formatstring_len = len; + } + + /** + * set the format string + * + * @param the format string + * @see #setFormatStringLength(byte) + */ + + public void setFormatString(String fs) + { + field_4_formatstring = fs; + } + + /** + * get the format index code (for built in formats) + * + * @return the format index code + * @see org.apache.poi.hssf.model.Workbook + */ + + public short getIndexCode() + { + return field_1_index_code; + } + + /** + * get the format string length + * + * @return the length of the format string + * @see #getFormatString() + */ + + public byte getFormatStringLength() + { + return field_2_formatstring_len; + } + + /** + * get the format string + * + * @return the format string + * @see #getFormatStringLength() + */ + + public String getFormatString() + { + return field_4_formatstring; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[FORMAT]\n"); + buffer.append(" .indexcode = ") + .append(Integer.toHexString(getIndexCode())).append("\n"); + buffer.append(" .formatstringlen = ") + .append(Integer.toHexString(getFormatStringLength())) + .append("\n"); + buffer.append(" .zero = ") + .append(Integer.toHexString(field_3_zero)).append("\n"); + buffer.append(" .formatstring = ").append(getFormatString()) + .append("\n"); + buffer.append("[/FORMAT]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + ( short ) (5 + getFormatStringLength())); + + // 9 - 4(len/sid) + format string length + LittleEndian.putShort(data, 4 + offset, getIndexCode()); + data[ 6 + offset ] = getFormatStringLength(); + LittleEndian.putShort(data, 7 + offset, ( short ) 0); + StringUtil.putCompressedUnicode(getFormatString(), data, 9 + offset); + return getRecordSize(); + } + + public int getRecordSize() + { + return 9 + getFormatStringLength(); + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/FormulaRecord.java b/src/java/org/apache/poi/hssf/record/FormulaRecord.java new file mode 100644 index 000000000..94470102d --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/FormulaRecord.java @@ -0,0 +1,482 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * FormulaRecord.java + * + * Created on October 28, 2001, 5:44 PM + */ +package org.apache.poi.hssf.record; + +import java.util.Stack; +import java.util.List; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.hssf.record.formula.*; + +/** + * Formula Record - This is not really supported in this release. Its here for future use.

+ * REFERENCE: PG 317/444 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class FormulaRecord + extends Record + implements CellValueRecordInterface, Comparable +{ + public static final short sid = + 0x06; // docs say 406...because of a bug Microsoft support site article #Q184647) + private short field_1_row; + private short field_2_column; + private short field_3_xf; + private double field_4_value; + private short field_5_options; + private int field_6_zero; + private short field_7_expression_len; + private Stack field_8_parsed_expr; + + /** Creates new FormulaRecord */ + + public FormulaRecord() + { + field_8_parsed_expr = new Stack(); + } + + /** + * Constructs a Formula record and sets its fields appropriately. + * + * @param short id must be 0x06 (NOT 0x406 see MSKB #Q184647 for an "explanation of + * this bug in the documentation) or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public FormulaRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a Formula record and sets its fields appropriately. + * + * @param short id must be 0x06 (NOT 0x406 see MSKB #Q184647 for an "explanation of + * this bug in the documentation) or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public FormulaRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_row = LittleEndian.getShort(data, 0 + offset); + field_2_column = LittleEndian.getShort(data, 2 + offset); + field_3_xf = LittleEndian.getShort(data, 4 + offset); + field_4_value = LittleEndian.getDouble(data, 6 + offset); + field_5_options = LittleEndian.getShort(data, 14 + offset); + field_6_zero = LittleEndian.getInt(data, 16 + offset); + field_7_expression_len = LittleEndian.getShort(data, 20 + offset); + + // field_8_parsed_expr = getParsedExpressionTokens(data, size, + // offset); + } + + private Stack getParsedExpressionTokens(byte [] data, short size, + int offset) + { + Stack stack = new Stack(); + int pos = 22 + offset; + + while (pos < size) + { + Ptg ptg = Ptg.createPtg(data, pos); + + pos += ptg.getSize(); + stack.push(ptg); + } + return stack; + } + + public void setRow(short row) + { + field_1_row = row; + } + + public void setColumn(short column) + { + field_2_column = column; + } + + public void setXFIndex(short xf) + { + field_3_xf = xf; + } + + /** + * set the calculated value of the formula + * + * @param calculated value + */ + + public void setValue(double value) + { + field_4_value = value; + } + + /** + * set the option flags + * + * @param bitmask + */ + + public void setOptions(short options) + { + field_5_options = options; + } + + /** + * set the length (in number of tokens) of the expression + * @param length + */ + + public void setExpressionLength(short len) + { + field_7_expression_len = len; + } + + public short getRow() + { + return field_1_row; + } + + public short getColumn() + { + return field_2_column; + } + + public short getXFIndex() + { + return field_3_xf; + } + + /** + * get the calculated value of the formula + * + * @return calculated value + */ + + public double getValue() + { + return field_4_value; + } + + /** + * get the option flags + * + * @return bitmask + */ + + public short getOptions() + { + return field_5_options; + } + + /** + * get the length (in number of tokens) of the expression + * @return expression length + */ + + public short getExpressionLength() + { + return field_7_expression_len; + } + + /** + * push a token onto the stack + * + * @param Ptg - the token + */ + + public void pushExpressionToken(Ptg ptg) + { + field_8_parsed_expr.push(ptg); + } + + /** + * pop a token off of the stack + * + * @return Ptg - the token + */ + + public Ptg popExpressionToken() + { + return ( Ptg ) field_8_parsed_expr.pop(); + } + + /** + * peek at the token on the top of stack + * + * @return Ptg - the token + */ + + public Ptg peekExpressionToken() + { + return ( Ptg ) field_8_parsed_expr.peek(); + } + + /** + * get the size of the stack + * @return size of the stack + */ + + public int getNumberOfExpressionTokens() + { + return field_8_parsed_expr.size(); + } + + /** + * get the stack as a list + * + * @return list of tokens (casts stack to a list and returns it!) + */ + + public List getParsedExpression() + { + return ( List ) field_8_parsed_expr; + } + + /** + * called by constructor, should throw runtime exception in the event of a + * record passed with a differing ID. + * + * @param id alleged id for this record + */ + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A FORMULA RECORD"); + } + } + + public short getSid() + { + return sid; + } + + /** + * 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 + */ + + public int serialize(int offset, byte [] data) + { + int ptgSize = getTotalPtgSize(); + + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) (24 + ptgSize)); + LittleEndian.putShort(data, 4 + offset, getRow()); + LittleEndian.putShort(data, 6 + offset, getColumn()); + LittleEndian.putShort(data, 8 + offset, getXFIndex()); + LittleEndian.putDouble(data, 10 + offset, getValue()); + LittleEndian.putShort(data, 18 + offset, getOptions()); + LittleEndian.putInt(data, 20 + offset, field_6_zero); + LittleEndian.putShort(data, 24 + offset, getExpressionLength()); + + // serializePtgs(data, 26+offset); + return getRecordSize(); + } + + public int getRecordSize() + { + return 0; + + // return getTotalPtgSize() + 28; + } + + private int getTotalPtgSize() + { + List list = getParsedExpression(); + int retval = 0; + + for (int k = 0; k < list.size(); k++) + { + Ptg ptg = ( Ptg ) list.get(k); + + retval += ptg.getSize(); + } + return retval; + } + + private void serializePtgs(byte [] data, int offset) + { + int pos = offset; + + for (int k = 0; k < field_8_parsed_expr.size(); k++) + { + Ptg ptg = ( Ptg ) field_8_parsed_expr.get(k); + + ptg.writeBytes(data, pos); + pos += ptg.getSize(); + } + } + + public boolean isBefore(CellValueRecordInterface i) + { + if (this.getRow() > i.getRow()) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() > i.getColumn())) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())) + { + return false; + } + return true; + } + + public boolean isAfter(CellValueRecordInterface i) + { + if (this.getRow() < i.getRow()) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() < i.getColumn())) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())) + { + return false; + } + return true; + } + + public boolean isEqual(CellValueRecordInterface i) + { + return ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())); + } + + public boolean isInValueSection() + { + return true; + } + + public boolean isValue() + { + return true; + } + + public int compareTo(Object obj) + { + CellValueRecordInterface loc = ( CellValueRecordInterface ) obj; + + if ((this.getRow() == loc.getRow()) + && (this.getColumn() == loc.getColumn())) + { + return 0; + } + if (this.getRow() < loc.getRow()) + { + return -1; + } + if (this.getRow() > loc.getRow()) + { + return 1; + } + if (this.getColumn() < loc.getColumn()) + { + return -1; + } + if (this.getColumn() > loc.getColumn()) + { + return 1; + } + return -1; + } + + public boolean equals(Object obj) + { + if (!(obj instanceof CellValueRecordInterface)) + { + return false; + } + CellValueRecordInterface loc = ( CellValueRecordInterface ) obj; + + if ((this.getRow() == loc.getRow()) + && (this.getColumn() == loc.getColumn())) + { + return true; + } + return false; + } +} diff --git a/src/java/org/apache/poi/hssf/record/GridsetRecord.java b/src/java/org/apache/poi/hssf/record/GridsetRecord.java new file mode 100644 index 000000000..da4463425 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/GridsetRecord.java @@ -0,0 +1,179 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Gridset Record.

+ * Description: flag denoting whether the user specified that gridlines are used when + * printing.

+ * REFERENCE: PG 320 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * + * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Glen Stampoultzis (gstamp at iprimus dot com dot au) + * + * @version 2.0-pre + */ + +public class GridsetRecord + extends Record +{ + public final static short sid = 0x82; + public short field_1_gridset_flag; + + public GridsetRecord() + { + } + + /** + * Constructs a GridSet record and sets its fields appropriately. + * + * @param short id must be 0x82 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public GridsetRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a GridSet record and sets its fields appropriately. + * + * @param short id must be 0x82 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public GridsetRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A Gridset RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_gridset_flag = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set whether gridlines are visible when printing + * + * @param gridset - true if no gridlines are print, false if gridlines are not print. + */ + + public void setGridset(boolean gridset) + { + if (gridset == true) + { + field_1_gridset_flag = 1; + } + else + { + field_1_gridset_flag = 0; + } + } + + /** + * get whether the gridlines are shown during printing. + * + * @return gridset - true if gridlines are NOT printed, false if they are. + */ + + public boolean getGridset() + { + return (field_1_gridset_flag == 1); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[GRIDSET]\n"); + buffer.append(" .gridset = ").append(getGridset()) + .append("\n"); + buffer.append("[/GRIDSET]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x2); + LittleEndian.putShort(data, 4 + offset, field_1_gridset_flag); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/GutsRecord.java b/src/java/org/apache/poi/hssf/record/GutsRecord.java new file mode 100644 index 000000000..eff89e9ca --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/GutsRecord.java @@ -0,0 +1,249 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Guts Record

+ * Description: Row/column gutter sizes

+ * REFERENCE: PG 320 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class GutsRecord + extends Record +{ + public final static short sid = 0x80; + private short field_1_left_row_gutter; // size of the row gutter to the left of the rows + private short field_2_top_col_gutter; // size of the column gutter above the columns + private short field_3_row_level_max; // maximum outline level for row gutters + private short field_4_col_level_max; // maximum outline level for column gutters + + public GutsRecord() + { + } + + /** + * Constructs a Guts record and sets its fields appropriately. + * + * @param short id must be 0x80 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public GutsRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a Guts record and sets its fields appropriately. + * + * @param short id must be 0x80 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public GutsRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A Guts RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_left_row_gutter = LittleEndian.getShort(data, 0 + offset); + field_2_top_col_gutter = LittleEndian.getShort(data, 2 + offset); + field_3_row_level_max = LittleEndian.getShort(data, 4 + offset); + field_4_col_level_max = LittleEndian.getShort(data, 6 + offset); + } + + /** + * set the size of the gutter that appears at the left of the rows + * + * @param gutter size in screen units + */ + + public void setLeftRowGutter(short gut) + { + field_1_left_row_gutter = gut; + } + + /** + * set the size of the gutter that appears at the above the columns + * + * @param gutter size in screen units + */ + + public void setTopColGutter(short gut) + { + field_2_top_col_gutter = gut; + } + + /** + * set the maximum outline level for the row gutter. + * + * @param maximum outline level + */ + + public void setRowLevelMax(short max) + { + field_3_row_level_max = max; + } + + /** + * set the maximum outline level for the col gutter. + * + * @param maximum outline level + */ + + public void setColLevelMax(short max) + { + field_4_col_level_max = max; + } + + /** + * get the size of the gutter that appears at the left of the rows + * + * @return gutter size in screen units + */ + + public short getLeftRowGutter() + { + return field_1_left_row_gutter; + } + + /** + * get the size of the gutter that appears at the above the columns + * + * @return gutter size in screen units + */ + + public short getTopColGutter() + { + return field_2_top_col_gutter; + } + + /** + * get the maximum outline level for the row gutter. + * + * @return maximum outline level + */ + + public short getRowLevelMax() + { + return field_3_row_level_max; + } + + /** + * get the maximum outline level for the col gutter. + * + * @return maximum outline level + */ + + public short getColLevelMax() + { + return field_4_col_level_max; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[GUTS]\n"); + buffer.append(" .leftgutter = ") + .append(Integer.toHexString(getLeftRowGutter())).append("\n"); + buffer.append(" .topgutter = ") + .append(Integer.toHexString(getTopColGutter())).append("\n"); + buffer.append(" .rowlevelmax = ") + .append(Integer.toHexString(getRowLevelMax())).append("\n"); + buffer.append(" .collevelmax = ") + .append(Integer.toHexString(getColLevelMax())).append("\n"); + buffer.append("[/GUTS]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x8); + LittleEndian.putShort(data, 4 + offset, getLeftRowGutter()); + LittleEndian.putShort(data, 6 + offset, getTopColGutter()); + LittleEndian.putShort(data, 8 + offset, getRowLevelMax()); + LittleEndian.putShort(data, 10 + offset, getColLevelMax()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 12; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/HCenterRecord.java b/src/java/org/apache/poi/hssf/record/HCenterRecord.java new file mode 100644 index 000000000..446451c04 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/HCenterRecord.java @@ -0,0 +1,173 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: HCenter record

+ * Description: whether to center between horizontal margins

+ * REFERENCE: PG 320 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class HCenterRecord + extends Record +{ + public final static short sid = 0x83; + private short field_1_hcenter; + + public HCenterRecord() + { + } + + /** + * Constructs an HCenter record and sets its fields appropriately. + * + * @param short id must be 0x83 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public HCenterRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs an HCenter record and sets its fields appropriately. + * + * @param short id must be 0x83 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public HCenterRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A HCenter RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_hcenter = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set whether or not to horizonatally center this sheet. + * @param center - t/f + */ + + public void setHCenter(boolean hc) + { + if (hc == true) + { + field_1_hcenter = 1; + } + else + { + field_1_hcenter = 0; + } + } + + /** + * get whether or not to horizonatally center this sheet. + * @return center - t/f + */ + + public boolean getHCenter() + { + return (field_1_hcenter == 1); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[HCENTER]\n"); + buffer.append(" .hcenter = ").append(getHCenter()) + .append("\n"); + buffer.append("[/HCENTER]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x2); + LittleEndian.putShort(data, 4 + offset, ( short ) field_1_hcenter); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/HeaderRecord.java b/src/java/org/apache/poi/hssf/record/HeaderRecord.java new file mode 100644 index 000000000..14a9127ba --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/HeaderRecord.java @@ -0,0 +1,221 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.StringUtil; + +/** + * Title: Header Record

+ * Description: Specifies a header for a sheet

+ * REFERENCE: PG 321 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class HeaderRecord + extends Record +{ + public final static short sid = 0x14; + private byte field_1_header_len; + private String field_2_header; + + public HeaderRecord() + { + } + + /** + * Constructs an Header record and sets its fields appropriately. + * + * @param short id must be 0x14 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public HeaderRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs an Header record and sets its fields appropriately. + * + * @param short id must be 0x14 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public HeaderRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A HEADERRECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + if (size > 0) + { + field_1_header_len = data[ 0 + offset ]; + field_2_header = new String(data, 1 + offset, + ( int ) field_1_header_len); + } + } + + /** + * set the length of the header string + * + * @param length of the header string + * @see #setHeader(String) + */ + + public void setHeaderLength(byte len) + { + field_1_header_len = len; + } + + /** + * set the header string + * + * @param header string to display + * @see #setHeaderLength(byte) + */ + + public void setHeader(String header) + { + field_2_header = header; + } + + /** + * get the length of the header string + * + * @return length of the header string + * @see #getHeader() + */ + + public byte getHeaderLength() + { + return field_1_header_len; + } + + /** + * get the header string + * + * @return header string to display + * @see #getHeaderLength() + */ + + public String getHeader() + { + return field_2_header; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[HEADER]\n"); + buffer.append(" .length = ").append(getHeaderLength()) + .append("\n"); + buffer.append(" .header = ").append(getHeader()) + .append("\n"); + buffer.append("[/HEADER]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + int len = 4; + + if (getHeaderLength() != 0) + { + len++; + } + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + ( short ) ((len - 4) + getHeaderLength())); + if (getHeaderLength() > 0) + { + data[ 4 + offset ] = getHeaderLength(); + StringUtil.putCompressedUnicode(getHeader(), data, 5 + offset); + } + return getRecordSize(); + } + + public int getRecordSize() + { + int retval = 4; + + if (getHeaderLength() != 0) + { + retval++; + } + retval += getHeaderLength(); + return retval; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/HideObjRecord.java b/src/java/org/apache/poi/hssf/record/HideObjRecord.java new file mode 100644 index 000000000..a5d7dcd48 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/HideObjRecord.java @@ -0,0 +1,178 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Hide Object Record

+ * Description: flag defines whether to hide placeholders and object

+ * REFERENCE: PG 321 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class HideObjRecord + extends Record +{ + public final static short sid = 0x8d; + public final static short HIDE_ALL = 2; + public final static short SHOW_PLACEHOLDERS = 1; + public final static short SHOW_ALL = 0; + private short field_1_hide_obj; + + public HideObjRecord() + { + } + + /** + * Constructs an HideObj record and sets its fields appropriately. + * + * @param short id must be 0x8d or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public HideObjRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs an HideObj record and sets its fields appropriately. + * + * @param short id must be 0x8d or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public HideObjRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A HIDEOBJ RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_hide_obj = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set hide object options + * + * @param hide options + * @see #HIDE_ALL + * @see #SHOW_PLACEHOLDERS + * @see #SHOW_ALL + */ + + public void setHideObj(short hide) + { + field_1_hide_obj = hide; + } + + /** + * get hide object options + * + * @return hide options + * @see #HIDE_ALL + * @see #SHOW_PLACEHOLDERS + * @see #SHOW_ALL + */ + + public short getHideObj() + { + return field_1_hide_obj; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[HIDEOBJ]\n"); + buffer.append(" .hideobj = ") + .append(Integer.toHexString(getHideObj())).append("\n"); + buffer.append("[/HIDEOBJ]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, getHideObj()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/IndexRecord.java b/src/java/org/apache/poi/hssf/record/IndexRecord.java new file mode 100644 index 000000000..114eb8fee --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/IndexRecord.java @@ -0,0 +1,228 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.IntList; +import org.apache.poi.util.LittleEndian; + +/** + * Title: Index Record

+ * Description: Occurs right after BOF, tells you where the DBCELL records are for a sheet + * Important for locating cells

+ * NOT USED IN THIS RELEASE + * REFERENCE: PG 323 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class IndexRecord + extends Record +{ + public final static short sid = 0x20B; + public final static int DBCELL_CAPACITY = 30; + public int field_1_zero; // reserved must be 0 + public int field_2_first_row; // first row on the sheet + public int field_3_last_row_add1; // last row + public int field_4_zero; // reserved must be 0 + public IntList field_5_dbcells; // array of offsets to DBCELL records + + public IndexRecord() + { + } + + /** + * Constructs an Index record and sets its fields appropriately. + * + * @param short id must be 0x208 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public IndexRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs an Index record and sets its fields appropriately. + * + * @param short id must be 0x208 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of record data + */ + + public IndexRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT An Index RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_5_dbcells = + new IntList(DBCELL_CAPACITY); // initial capacity of 30 + field_1_zero = LittleEndian.getInt(data, 0 + offset); + field_2_first_row = LittleEndian.getInt(data, 4 + offset); + field_3_last_row_add1 = LittleEndian.getInt(data, 8 + offset); + field_4_zero = LittleEndian.getInt(data, 12 + offset); + for (int k = 16; k < size; k = k + 4) + { + + // System.out.println("getting " + k); + field_5_dbcells.add(LittleEndian.getInt(data, k + offset)); + } + } + + public void setFirstRow(int row) + { + field_2_first_row = row; + } + + public void setLastRowAdd1(int row) + { + field_3_last_row_add1 = row; + } + + public void addDbcell(int cell) + { + if (field_5_dbcells == null) + { + field_5_dbcells = new IntList(); + } + field_5_dbcells.add(cell); + } + + public void setDbcell(int cell, int value) + { + field_5_dbcells.set(cell, value); + } + + public int getFirstRow() + { + return field_2_first_row; + } + + public int getLastRowAdd1() + { + return field_3_last_row_add1; + } + + public int getNumDbcells() + { + if (field_5_dbcells == null) + { + return 0; + } + return field_5_dbcells.size(); + } + + public int getDbcellAt(int cellnum) + { + return field_5_dbcells.get(cellnum); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[INDEX]\n"); + buffer.append(" .firstrow = ") + .append(Integer.toHexString(getFirstRow())).append("\n"); + buffer.append(" .lastrowadd1 = ") + .append(Integer.toHexString(getLastRowAdd1())).append("\n"); + for (int k = 0; k < getNumDbcells(); k++) + { + buffer.append(" .dbcell_" + k + " = ") + .append(Integer.toHexString(getDbcellAt(k))).append("\n"); + } + buffer.append("[/INDEX]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + ( short ) (16 + (getNumDbcells() * 4))); + LittleEndian.putInt(data, 4 + offset, 0); + LittleEndian.putInt(data, 8 + offset, getFirstRow()); + LittleEndian.putInt(data, 12 + offset, getLastRowAdd1()); + LittleEndian.putInt(data, 16 + offset, 0); + for (int k = 0; k < getNumDbcells(); k++) + { + LittleEndian.putInt(data, (k * 4) + 20 + offset, getDbcellAt(k)); + } + return getRecordSize(); + } + + public int getRecordSize() + { + return 20 + (getNumDbcells() * 4); + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/InterfaceEndRecord.java b/src/java/org/apache/poi/hssf/record/InterfaceEndRecord.java new file mode 100644 index 000000000..d8de44916 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/InterfaceEndRecord.java @@ -0,0 +1,143 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Interface End Record

+ * Description: Shows where the Interface Records end (MMS) + * (has no fields)

+ * REFERENCE: PG 324 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class InterfaceEndRecord + extends Record +{ + public final static short sid = 0xe2; + + public InterfaceEndRecord() + { + } + + /** + * Constructs an InterfaceEnd record and sets its fields appropriately. + * + * @param short id must be 0xe2 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public InterfaceEndRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs an InterfaceEnd record and sets its fields appropriately. + * + * @param short id must be 0xe2 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the data + */ + + public InterfaceEndRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A INTERFACEEND RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[INTERFACEEND]\n"); + buffer.append("[/INTERFACEEND]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x00)); // 0 bytes (4 total) + return getRecordSize(); + } + + public int getRecordSize() + { + return 4; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/InterfaceHdrRecord.java b/src/java/org/apache/poi/hssf/record/InterfaceHdrRecord.java new file mode 100644 index 000000000..af7493549 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/InterfaceHdrRecord.java @@ -0,0 +1,177 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Interface Header Record

+ * Description: Defines the beginning of Interface records (MMS)

+ * REFERENCE: PG 324 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class InterfaceHdrRecord + extends Record +{ + public final static short sid = 0xe1; + private short field_1_codepage; // = 0; + + /** + * suggested (and probably correct) default + */ + + public final static short CODEPAGE = ( short ) 0x4b0; + + public InterfaceHdrRecord() + { + } + + /** + * Constructs an Codepage record and sets its fields appropriately. + * + * @param short id must be 0xe1 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public InterfaceHdrRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs an Codepage record and sets its fields appropriately. + * + * @param short id must be 0xe1 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public InterfaceHdrRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A INTERFACEHDR RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_codepage = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set the codepage for the file + * + * @param cp - the codepage + * @see #CODEPAGE + */ + + public void setCodepage(short cp) + { + field_1_codepage = cp; + } + + /** + * get the codepage for the file + * + * @return the codepage + * @see #CODEPAGE + */ + + public short getCodepage() + { + return field_1_codepage; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[INTERFACEHDR]\n"); + buffer.append(" .codepage = ") + .append(Integer.toHexString(getCodepage())).append("\n"); + buffer.append("[/INTERFACEHDR]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, getCodepage()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/IterationRecord.java b/src/java/org/apache/poi/hssf/record/IterationRecord.java new file mode 100644 index 000000000..ec0847a53 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/IterationRecord.java @@ -0,0 +1,177 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Iteration Record

+ * Description: Tells whether to iterate over forumla calculations or not + * (if a formula is dependant upon another formula's result) + * (odd feature for something that can only have 32 elements in + * a formula!)

+ * REFERENCE: PG 325 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class IterationRecord + extends Record +{ + public final static short sid = 0x11; + private short field_1_iteration; + + public IterationRecord() + { + } + + /** + * Constructs an Iteration record and sets its fields appropriately. + * + * @param short id must be 0x11 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public IterationRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs an Iteration record and sets its fields appropriately. + * + * @param short id must be 0x11 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public IterationRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT An ITERATION RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_iteration = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set whether or not to iterate for calculations + * @param iterate or not + */ + + public void setIteration(boolean iterate) + { + if (iterate) + { + field_1_iteration = 1; + } + else + { + field_1_iteration = 0; + } + } + + /** + * get whether or not to iterate for calculations + * + * @return whether iterative calculations are turned off or on + */ + + public boolean getIteration() + { + return (field_1_iteration == 1); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[ITERATION]\n"); + buffer.append(" .iteration = ").append(getIteration()) + .append("\n"); + buffer.append("[/ITERATION]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x2); + LittleEndian.putShort(data, 4 + offset, field_1_iteration); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/LabelRecord.java b/src/java/org/apache/poi/hssf/record/LabelRecord.java new file mode 100644 index 000000000..5173851f6 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/LabelRecord.java @@ -0,0 +1,313 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * LabelRecord.java + * + * Created on November 11, 2001, 12:51 PM + */ +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.StringUtil; + +/** + * Label Record - read only support for strings stored directly in the cell.. Don't + * use this (except to read), use LabelSST instead

+ * REFERENCE: PG 325 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + * @see org.apache.poi.hssf.record.LabelSSTRecord + */ + +public class LabelRecord + extends Record + implements CellValueRecordInterface +{ + public final static short sid = 0x204; + private short field_1_row; + private short field_2_column; + private short field_3_xf_index; + private short field_4_string_len; + private byte field_5_unicode_flag; + private String field_6_value; + + /** Creates new LabelRecord */ + + public LabelRecord() + { + } + + /** + * Constructs an Label record and sets its fields appropriately. + * + * @param short id must be 0x204 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public LabelRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs an Label record and sets its fields appropriately. + * + * @param short id must be 0x204 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record + */ + + public LabelRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + /** + * called by constructor, should throw runtime exception in the event of a + * record passed with a differing ID. + * + * @param id alleged id for this record + */ + + protected void validateSid(short id) + { + if (id != this.sid) + { + throw new RecordFormatException("Not a valid LabelRecord"); + } + } + + /** + * called by the constructor, should set class level fields. Should throw + * runtime exception for bad/icomplete data. + * + * @param data raw data + * @param size size of data + */ + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_row = LittleEndian.getShort(data, 0 + offset); + field_2_column = LittleEndian.getShort(data, 2 + offset); + field_3_xf_index = LittleEndian.getShort(data, 4 + offset); + field_4_string_len = LittleEndian.getShort(data, 6 + offset); + field_5_unicode_flag = data[ 8 + offset ]; + if (isUnCompressedUnicode()) + { + field_6_value = StringUtil.getFromUnicode(data, 8 + offset, + field_4_string_len); + } + else + { + field_6_value = new String(data, 9 + offset, getStringLength()); + } + } + +/* READ ONLY ACCESS... THIS IS FOR COMPATIBILITY ONLY...USE LABELSST! + public void setRow(short row) { + field_1_row = row; + } + + public void setColumn(short col) { + field_2_column = col; + } + + public void setXFIndex(short index) { + field_3_xf_index = index; + } + */ + public short getRow() + { + return field_1_row; + } + + public short getColumn() + { + return field_2_column; + } + + public short getXFIndex() + { + return field_3_xf_index; + } + + /** + * get the number of characters this string contains + * @return number of characters + */ + + public short getStringLength() + { + return field_4_string_len; + } + + /** + * is this uncompressed unicode (16bit)? Or just 8-bit compressed? + * @return isUnicode - True for 16bit- false for 8bit + */ + + public boolean isUnCompressedUnicode() + { + return (field_5_unicode_flag == 1); + } + + /** + * get the value + * + * @return the text string + * @see #getStringLength() + */ + + public String getValue() + { + return field_6_value; + } + + /** + * THROWS A RUNTIME EXCEPTION.. USE LABELSSTRecords. YOU HAVE NO REASON to use LABELRecord!! + */ + + public int serialize(int offset, byte [] data) + { + throw new RecordFormatException( + "Label Records are supported READ ONLY...convert to LabelSST"); + } + + public short getSid() + { + return this.sid; + } + + public boolean isBefore(CellValueRecordInterface i) + { + if (this.getRow() > i.getRow()) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() > i.getColumn())) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())) + { + return false; + } + return true; + } + + public boolean isAfter(CellValueRecordInterface i) + { + if (this.getRow() < i.getRow()) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() < i.getColumn())) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())) + { + return false; + } + return true; + } + + public boolean isEqual(CellValueRecordInterface i) + { + return ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())); + } + + public boolean isInValueSection() + { + return true; + } + + public boolean isValue() + { + return true; + } + + /** + * NO-OP! + */ + + public void setColumn(short col) + { + } + + /** + * NO-OP! + */ + + public void setRow(short row) + { + } + + /** + * no op! + */ + + public void setXFIndex(short xf) + { + } +} diff --git a/src/java/org/apache/poi/hssf/record/LabelSSTRecord.java b/src/java/org/apache/poi/hssf/record/LabelSSTRecord.java new file mode 100644 index 000000000..3cd105487 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/LabelSSTRecord.java @@ -0,0 +1,329 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Label SST Record

+ * Description: Refers to a string in the shared string table and is a column + * value.

+ * REFERENCE: PG 325 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class LabelSSTRecord + extends Record + implements CellValueRecordInterface, Comparable +{ + public final static short sid = 0xfd; + private short field_1_row; + private short field_2_column; + private short field_3_xf_index; + private int field_4_sst_index; + + public LabelSSTRecord() + { + } + + /** + * Constructs an LabelSST record and sets its fields appropriately. + * + * @param short id must be 0xfd or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public LabelSSTRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs an LabelSST record and sets its fields appropriately. + * + * @param short id must be 0xfd or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public LabelSSTRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A valid LabelSST RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_row = LittleEndian.getShort(data, 0 + offset); + field_2_column = LittleEndian.getShort(data, 2 + offset); + field_3_xf_index = LittleEndian.getShort(data, 4 + offset); + field_4_sst_index = LittleEndian.getInt(data, 6 + offset); + } + + public void setRow(short row) + { + field_1_row = row; + } + + public void setColumn(short col) + { + field_2_column = col; + } + + /** + * set the index to the extended format record + * + * @see org.apache.poi.hssf.record.ExtendedFormatRecord + * @param index - the index to the XF record + */ + + public void setXFIndex(short index) + { + field_3_xf_index = index; + } + + /** + * set the index to the string in the SSTRecord + * + * @param index - of string in the SST Table + * @see org.apache.poi.hssf.record.SSTRecord + */ + + public void setSSTIndex(int index) + { + field_4_sst_index = index; + } + + public short getRow() + { + return field_1_row; + } + + public short getColumn() + { + return field_2_column; + } + + /** + * get the index to the extended format record + * + * @see org.apache.poi.hssf.record.ExtendedFormatRecord + * @return the index to the XF record + */ + + public short getXFIndex() + { + return field_3_xf_index; + } + + /** + * get the index to the string in the SSTRecord + * + * @return index of string in the SST Table + * @see org.apache.poi.hssf.record.SSTRecord + */ + + public int getSSTIndex() + { + return field_4_sst_index; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[LABELSST]\n"); + buffer.append(" .row = ") + .append(Integer.toHexString(getRow())).append("\n"); + buffer.append(" .column = ") + .append(Integer.toHexString(getColumn())).append("\n"); + buffer.append(" .xfindex = ") + .append(Integer.toHexString(getXFIndex())).append("\n"); + buffer.append(" .sstindex = ") + .append(Integer.toHexString(getSSTIndex())).append("\n"); + buffer.append("[/LABELSST]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 10); + LittleEndian.putShort(data, 4 + offset, getRow()); + LittleEndian.putShort(data, 6 + offset, getColumn()); + LittleEndian.putShort(data, 8 + offset, getXFIndex()); + LittleEndian.putInt(data, 10 + offset, getSSTIndex()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 14; + } + + public short getSid() + { + return this.sid; + } + + public boolean isBefore(CellValueRecordInterface i) + { + if (this.getRow() > i.getRow()) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() > i.getColumn())) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())) + { + return false; + } + return true; + } + + public boolean isAfter(CellValueRecordInterface i) + { + if (this.getRow() < i.getRow()) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() < i.getColumn())) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())) + { + return false; + } + return true; + } + + public boolean isEqual(CellValueRecordInterface i) + { + return ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())); + } + + public boolean isInValueSection() + { + return true; + } + + public boolean isValue() + { + return true; + } + + public int compareTo(Object obj) + { + CellValueRecordInterface loc = ( CellValueRecordInterface ) obj; + + if ((this.getRow() == loc.getRow()) + && (this.getColumn() == loc.getColumn())) + { + return 0; + } + if (this.getRow() < loc.getRow()) + { + return -1; + } + if (this.getRow() > loc.getRow()) + { + return 1; + } + if (this.getColumn() < loc.getColumn()) + { + return -1; + } + if (this.getColumn() > loc.getColumn()) + { + return 1; + } + return -1; + } + + public boolean equals(Object obj) + { + if (!(obj instanceof CellValueRecordInterface)) + { + return false; + } + CellValueRecordInterface loc = ( CellValueRecordInterface ) obj; + + if ((this.getRow() == loc.getRow()) + && (this.getColumn() == loc.getColumn())) + { + return true; + } + return false; + } +} diff --git a/src/java/org/apache/poi/hssf/record/MMSRecord.java b/src/java/org/apache/poi/hssf/record/MMSRecord.java new file mode 100644 index 000000000..7219620d3 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/MMSRecord.java @@ -0,0 +1,193 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: MMS Record

+ * Description: defines how many add menu and del menu options are stored + * in the file. Should always be set to 0 for HSSF workbooks

+ * REFERENCE: PG 328 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class MMSRecord + extends Record +{ + public final static short sid = 0xC1; + private byte field_1_addMenuCount; // = 0; + private byte field_2_delMenuCount; // = 0; + + public MMSRecord() + { + } + + /** + * Constructs a MMS record and sets its fields appropriately. + * + * @param short id must be 0xc1 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public MMSRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a MMS record and sets its fields appropriately. + * + * @param short id must be 0xc1 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the data + */ + + public MMSRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A MMS RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_addMenuCount = data[ 0 + offset ]; + field_2_delMenuCount = data[ 1 + offset ]; + } + + /** + * set number of add menu options (set to 0) + * @param number of add menu options + */ + + public void setAddMenuCount(byte am) + { + field_1_addMenuCount = am; + } + + /** + * set number of del menu options (set to 0) + * @param number of add menu options + */ + + public void setDelMenuCount(byte dm) + { + field_2_delMenuCount = dm; + } + + /** + * get number of add menu options (should be 0) + * @return number of add menu options + */ + + public byte getAddMenuCount() + { + return field_1_addMenuCount; + } + + /** + * get number of add del options (should be 0) + * @return number of add menu options + */ + + public byte getDelMenuCount() + { + return field_2_delMenuCount; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[MMS]\n"); + buffer.append(" .addMenu = ") + .append(Integer.toHexString(getAddMenuCount())).append("\n"); + buffer.append(" .delMenu = ") + .append(Integer.toHexString(getDelMenuCount())).append("\n"); + buffer.append("[/MMS]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + data[ 4 + offset ] = getAddMenuCount(); + data[ 5 + offset ] = getDelMenuCount(); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/MergeCellsRecord.java b/src/java/org/apache/poi/hssf/record/MergeCellsRecord.java new file mode 100644 index 000000000..9bfd98ec9 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/MergeCellsRecord.java @@ -0,0 +1,319 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import java.util.ArrayList; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Merged Cells Record

+ * Description: Optional record defining a square area of cells to "merged" into + * one cell.

+ * REFERENCE: NONE (UNDOCUMENTED PRESENTLY)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class MergeCellsRecord + extends Record +{ + public final static short sid = 0xe5; + private short field_1_num_areas; + private ArrayList field_2_regions; + + public MergeCellsRecord() + { + } + + /** + * Constructs a MergedCellsRecord and sets its fields appropriately + * + * @param short id must be 0xe5 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public MergeCellsRecord(short sid, short size, byte [] data) + { + super(sid, size, data); + } + + /** + * Constructs a MergedCellsRecord and sets its fields appropriately + * + * @param short id must be 0xe5 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset the offset of the record's data + */ + + public MergeCellsRecord(short sid, short size, byte [] data, int offset) + { + super(sid, size, data, offset); + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_num_areas = LittleEndian.getShort(data, 0 + offset); + field_2_regions = new ArrayList(field_1_num_areas + 10); + int pos = 2; + + for (int k = 0; k < field_1_num_areas; k++) + { + MergedRegion region = + new MergedRegion(LittleEndian + .getShort(data, pos + offset), LittleEndian + .getShort(data, pos + 2 + offset), LittleEndian + .getShort(data, pos + 4 + offset), LittleEndian + .getShort(data, pos + 6 + offset)); + + pos += 8; + field_2_regions.add(region); + } + } + + /** + * get the number of merged areas. If this drops down to 0 you should just go + * ahead and delete the record. + * @return number of areas + */ + + public short getNumAreas() + { + return field_1_num_areas; + } + + /** + * set the number of merged areas. You do not need to call this if you use addArea, + * it will be incremented automatically or decremented when an area is removed. If + * you are setting this to 0 then you are a terrible person. Just remove the record. + * (just kidding about you being a terrible person..hehe) + * + * @param number of areas + */ + + public void setNumAreas(short numareas) + { + field_1_num_areas = numareas; + } + + /** + * Add an area to consider a merged cell. The index returned is only gauranteed to + * be correct provided you do not add ahead of or remove ahead of it (in which case + * you should increment or decrement appropriately....in other words its an arrayList) + * + * @param rowfrom - the upper left hand corner's row + * @param colfrom - the upper left hand corner's col + * @param rowto - the lower right hand corner's row + * @param colto - the lower right hand corner's col + * @return new index of said area (don't depend on it if you add/remove) + */ + + public int addArea(short rowfrom, short colfrom, short rowto, short colto) + { + if (field_2_regions == null) + { + field_2_regions = new ArrayList(10); + } + MergedRegion region = new MergedRegion(rowfrom, rowto, colfrom, + colto); + + field_2_regions.add(region); + field_1_num_areas++; + return field_2_regions.size() - 1; + } + + /** + * essentially unmerge the cells in the "area" stored at the passed in index + * @param area index + */ + + public void removeAreaAt(int area) + { + field_2_regions.remove(area); + field_1_num_areas--; + } + + /** + * return the MergedRegion at the given index. + * + * @return MergedRegion representing the area that is Merged (r1,c1 - r2,c2) + */ + + public MergedRegion getAreaAt(int index) + { + return ( MergedRegion ) field_2_regions.get(index); + } + + public int getRecordSize() + { + int retValue; + + retValue = 6 + (8 * field_2_regions.size()); + return retValue; + } + + public short getSid() + { + return sid; + } + + public int serialize(int offset, byte [] data) + { + int recordsize = getRecordSize(); + int pos = 6; + + LittleEndian.putShort(data, offset + 0, sid); + LittleEndian.putShort(data, offset + 2, ( short ) (recordsize - 4)); + LittleEndian.putShort(data, offset + 4, getNumAreas()); + for (int k = 0; k < getNumAreas(); k++) + { + MergedRegion region = getAreaAt(k); + + LittleEndian.putShort(data, offset + pos, region.row_from); + pos += 2; + LittleEndian.putShort(data, offset + pos, region.row_to); + pos += 2; + LittleEndian.putShort(data, offset + pos, region.col_from); + pos += 2; + LittleEndian.putShort(data, offset + pos, region.col_to); + pos += 2; + } + return recordsize; + } + + public String toString() + { + StringBuffer retval = new StringBuffer(); + + retval.append("[MERGEDCELLS]").append("\n"); + retval.append(" .sid =").append(sid).append("\n"); + retval.append(" .numregions =").append(field_1_num_areas) + .append("\n"); + for (int k = 0; k < field_1_num_areas; k++) + { + MergedRegion region = ( MergedRegion ) field_2_regions.get(k); + + retval.append(" .rowfrom =").append(region.row_from) + .append("\n"); + retval.append(" .colfrom =").append(region.col_from) + .append("\n"); + retval.append(" .rowto =").append(region.row_to) + .append("\n"); + retval.append(" .colto =").append(region.col_to) + .append("\n"); + } + retval.append("[MERGEDCELLS]").append("\n"); + return retval.toString(); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A MERGEDCELLS RECORD!! " + + id); + } + } + + /** + * this is a low level representation of a MergedRegion of cells. It is an + * inner class because we do not want it used without reference to this class. + * + */ + + public class MergedRegion + { + + /** + * create a merged region all in one stroke. + */ + + public MergedRegion(short row_from, short row_to, short col_from, + short col_to) + { + this.row_from = row_from; + this.row_to = row_to; + this.col_from = col_from; + this.col_to = col_to; + } + + /** + * upper lefthand corner row + */ + + public short row_from; + + /** + * lower right hand corner row + */ + + public short row_to; + + /** + * upper right hand corner col + */ + + public short col_from; + + /** + * lower right hand corner col + */ + + public short col_to; + } +} diff --git a/src/java/org/apache/poi/hssf/record/MulBlankRecord.java b/src/java/org/apache/poi/hssf/record/MulBlankRecord.java new file mode 100644 index 000000000..80562df00 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/MulBlankRecord.java @@ -0,0 +1,250 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * MulBlankRecord.java + * + * Created on December 10, 2001, 12:49 PM + */ +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Mulitple Blank cell record

+ * Description: Represents a set of columns in a row with no value but with styling. + * In this release we have read-only support for this record type. + * The RecordFactory converts this to a set of BlankRecord objects.

+ * REFERENCE: PG 329 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + * @see org.apache.poi.hssf.record.RecordFactory + * @see org.apache.poi.hssf.record.BlankRecord + */ + +public class MulBlankRecord + extends Record +{ + public final static short sid = 0xbe; + private short field_1_row; + private short field_2_first_col; + private short[] field_3_xfs; + private short field_4_last_col; + + /** Creates new MulBlankRecord */ + + public MulBlankRecord() + { + } + + /** + * Constructs a MulBlank record and sets its fields appropriately. + * + * @param short id must be 0xbe or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public MulBlankRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a MulBlank record and sets its fields appropriately. + * + * @param short id must be 0xbe or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public MulBlankRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + /** + * get the row number of the cells this represents + * + * @return row number + */ + + public short getRow() + { + return field_1_row; + } + + /** + * starting column (first cell this holds in the row) + * @return first column number + */ + + public short getFirstColumn() + { + return field_2_first_col; + } + + /** + * ending column (last cell this holds in the row) + * @return first column number + */ + + public short getLastColumn() + { + return field_4_last_col; + } + + /** + * get the number of columns this contains (last-first +1) + * @return number of columns (last - first +1) + */ + + public int getNumColumns() + { + return field_4_last_col - field_2_first_col + 1; + } + + /** + * returns the xf index for column (coffset = column - field_2_first_col) + * @param the column (coffset = column - field_2_first_col) + * @return the XF index for the column + */ + + public short getXFAt(int coffset) + { + return field_3_xfs[ coffset ]; + } + + /** + * called by the constructor, should set class level fields. Should throw + * runtime exception for bad/icomplete data. + * + * @param data raw data + * @param size size of data + */ + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_row = LittleEndian.getShort(data, 0 + offset); + field_2_first_col = LittleEndian.getShort(data, 2 + offset); + field_3_xfs = parseXFs(data, 4, offset, size); + field_4_last_col = LittleEndian.getShort(data, + (field_3_xfs.length * 2) + + 4 + offset); + } + + private short [] parseXFs(byte [] data, int offset, int recoffset, + short size) + { + short[] retval = new short[ ((size - offset) - 2) / 2 ]; + int idx = 0; + + for (; offset < size - 2; ) + { + short xf = 0; + + xf = LittleEndian.getShort(data, offset + recoffset); + offset += 2; + retval[ idx ] = xf; + idx++; + } + return retval; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[MULBLANK]\n"); + buffer.append("firstcol = ") + .append(Integer.toHexString(getFirstColumn())).append("\n"); + buffer.append(" lastcol = ") + .append(Integer.toHexString(getLastColumn())).append("\n"); + for (int k = 0; k < getNumColumns(); k++) + { + buffer.append("xf").append(k).append(" = ") + .append(Integer.toHexString(getXFAt(k))).append("\n"); + } + buffer.append("[/MULBLANK]\n"); + return buffer.toString(); + } + + /** + * called by constructor, should throw runtime exception in the event of a + * record passed with a differing ID. + * + * @param id alleged id for this record + */ + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("Not a MulBlankRecord!"); + } + } + + public short getSid() + { + return this.sid; + } + + public int serialize(int offset, byte [] data) + { + throw new RecordFormatException( + "Sorry, you can't serialize a MulBlank in this release"); + } +} diff --git a/src/java/org/apache/poi/hssf/record/MulRKRecord.java b/src/java/org/apache/poi/hssf/record/MulRKRecord.java new file mode 100644 index 000000000..715619586 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/MulRKRecord.java @@ -0,0 +1,299 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * MulRKRecord.java + * + * Created on November 9, 2001, 4:53 PM + */ +package org.apache.poi.hssf.record; + +import java.util.ArrayList; + +import org.apache.poi.util.LittleEndian; + +/** + * Used to store multiple RK numbers on a row. 1 MulRk = Multiple Cell values. + * HSSF just converts this into multiple NUMBER records. READ-ONLY SUPPORT!

+ * REFERENCE: PG 330 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class MulRKRecord + extends Record +{ + public final static short sid = 0xbd; + private short field_1_row; + private short field_2_first_col; + private ArrayList field_3_rks; + private short field_4_last_col; + + /** Creates new MulRKRecord */ + + public MulRKRecord() + { + } + + /** + * Constructs a MulRK record and sets its fields appropriately. + * + * @param short id must be 0xbd or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public MulRKRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a MulRK record and sets its fields appropriately. + * + * @param short id must be 0xbd or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of data + */ + + public MulRKRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + public short getRow() + { + return field_1_row; + } + + /** + * starting column (first cell this holds in the row) + * @return first column number + */ + + public short getFirstColumn() + { + return field_2_first_col; + } + + /** + * ending column (last cell this holds in the row) + * @return first column number + */ + + public short getLastColumn() + { + return field_4_last_col; + } + + /** + * get the number of columns this contains (last-first +1) + * @return number of columns (last - first +1) + */ + + public int getNumColumns() + { + return field_4_last_col - field_2_first_col + 1; + } + + /** + * returns the xf index for column (coffset = column - field_2_first_col) + * @return the XF index for the column + */ + + public short getXFAt(int coffset) + { + return (( RkRec ) field_3_rks.get(coffset)).xf; + } + + /** + * returns the rk number for column (coffset = column - field_2_first_col) + * @return the value (decoded into a double) + */ + + public double getRKNumberAt(int coffset) + { + return decodeNumber((( RkRec ) field_3_rks.get(coffset)).rk); + } + + /** + * Do the dirty work of decoding; made a private static method to + * facilitate testing the algorithm + */ + + private static double decodeNumber(int number) + { + long raw_number = number; + + // mask off the two low-order bits, 'cause they're not part of + // the number + raw_number &= -3; + double rvalue = 0; + + if ((number & 0x02) == 0x02) + { + + // ok, it's just a plain ol' int; we can handle this + // trivially by right-shifting and casting + rvalue = ( double ) (raw_number >> 2); + } + else + { + + // also trivial, but not as obvious ... left shift the + // bits high and use that clever static method in Double + // to convert the resulting bit image to a double + rvalue = Double.longBitsToDouble(raw_number << 32); + } + if ((number & 0x01) == 0x01) + { + + // low-order bit says divide by 100, and so we do. Why? + // 'cause that's what the algorithm says. Can't fight city + // hall, especially if it's the city of Redmond + rvalue /= 100; + } + return rvalue; + } + + /** + * called by the constructor, should set class level fields. Should throw + * runtime exception for bad/icomplete data. + * + * @param data raw data + * @param size size of data + */ + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_row = LittleEndian.getShort(data, 0 + offset); + field_2_first_col = LittleEndian.getShort(data, 2 + offset); + field_3_rks = parseRKs(data, 4, offset, size); + field_4_last_col = LittleEndian.getShort(data, + (field_3_rks.size() * 6) + + 4 + offset); + } + + private ArrayList parseRKs(byte [] data, int offset, int recoffset, + short size) + { + ArrayList retval = new ArrayList(); + + for (; offset < size - 2; ) + { + RkRec rec = new RkRec(); + + rec.xf = LittleEndian.getShort(data, offset + recoffset); + offset += 2; + rec.rk = LittleEndian.getInt(data, offset + recoffset); + offset += 4; + retval.add(rec); + } + return retval; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[MULRK]\n"); + buffer.append("firstcol = ") + .append(Integer.toHexString(getFirstColumn())).append("\n"); + buffer.append(" lastcol = ") + .append(Integer.toHexString(getLastColumn())).append("\n"); + for (int k = 0; k < getNumColumns(); k++) + { + buffer.append("xf").append(k).append(" = ") + .append(Integer.toHexString(getXFAt(k))).append("\n"); + buffer.append("rk").append(k).append(" = ") + .append(getRKNumberAt(k)).append("\n"); + } + buffer.append("[/MULRK]\n"); + return buffer.toString(); + } + + /** + * called by constructor, should throw runtime exception in the event of a + * record passed with a differing ID. + * + * @param id alleged id for this record + */ + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("Not a MulRKRecord!"); + } + } + + public short getSid() + { + return this.sid; + } + + public int serialize(int offset, byte [] data) + { + throw new RecordFormatException( + "Sorry, you can't serialize a MulRK in this release"); + } +} + +class RkRec +{ + public short xf; + public int rk; +} diff --git a/src/java/org/apache/poi/hssf/record/NumberRecord.java b/src/java/org/apache/poi/hssf/record/NumberRecord.java new file mode 100644 index 000000000..ddd1d2961 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/NumberRecord.java @@ -0,0 +1,354 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * NumberRecord.java + * + * Created on October 1, 2001, 8:01 PM + */ +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.hssf.record.Record; + +/** + * Contains a numeric cell value.

+ * REFERENCE: PG 334 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class NumberRecord + extends Record + implements CellValueRecordInterface, Comparable +{ + public static final short sid = 0x203; + private short field_1_row; + private short field_2_col; + private short field_3_xf; + private double field_4_value; + + /** Creates new NumberRecord */ + + public NumberRecord() + { + } + + /** + * Constructs a Number record and sets its fields appropriately. + * + * @param short id must be 0x203 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public NumberRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a Number record and sets its fields appropriately. + * + * @param short id must be 0x203 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the data + */ + + public NumberRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + /** + * called by the constructor, should set class level fields. Should throw + * runtime exception for bad/icomplete data. + * + * @param data raw data + * @param size size of data + */ + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_row = LittleEndian.getShort(data, 0 + offset); + field_2_col = LittleEndian.getShort(data, 2 + offset); + field_3_xf = LittleEndian.getShort(data, 4 + offset); + field_4_value = LittleEndian.getDouble(data, 6 + offset); + } + + public void setRow(short row) + { + field_1_row = row; + } + + public void setColumn(short col) + { + field_2_col = col; + } + + /** + * set the index to the ExtendedFormat + * @see org.apache.poi.hssf.record.ExtendedFormatRecord + * @param index to the XF record + */ + + public void setXFIndex(short xf) + { + field_3_xf = xf; + } + + /** + * set the value for the cell + * + * @param double representing the value + */ + + public void setValue(double value) + { + field_4_value = value; + } + + public short getRow() + { + return field_1_row; + } + + public short getColumn() + { + return field_2_col; + } + + /** + * get the index to the ExtendedFormat + * @see org.apache.poi.hssf.record.ExtendedFormatRecord + * @return index to the XF record + */ + + public short getXFIndex() + { + return field_3_xf; + } + + /** + * get the value for the cell + * + * @return double representing the value + */ + + public double getValue() + { + return field_4_value; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[NUMBER]\n"); + buffer.append(" .row = ") + .append(Integer.toHexString(getRow())).append("\n"); + buffer.append(" .col = ") + .append(Integer.toHexString(getColumn())).append("\n"); + buffer.append(" .xfindex = ") + .append(Integer.toHexString(getXFIndex())).append("\n"); + buffer.append(" .value = ").append(getValue()) + .append("\n"); + buffer.append("[/NUMBER]\n"); + return buffer.toString(); + } + + /** + * 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 + */ + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 14); + LittleEndian.putShort(data, 4 + offset, getRow()); + LittleEndian.putShort(data, 6 + offset, getColumn()); + LittleEndian.putShort(data, 8 + offset, getXFIndex()); + LittleEndian.putDouble(data, 10 + offset, getValue()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 18; + } + + /** + * called by constructor, should throw runtime exception in the event of a + * record passed with a differing ID. + * + * @param id alleged id for this record + */ + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A Number RECORD"); + } + } + + public short getSid() + { + return this.sid; + } + + public boolean isBefore(CellValueRecordInterface i) + { + if (this.getRow() > i.getRow()) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() > i.getColumn())) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())) + { + return false; + } + return true; + } + + public boolean isAfter(CellValueRecordInterface i) + { + if (this.getRow() < i.getRow()) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() < i.getColumn())) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())) + { + return false; + } + return true; + } + + public boolean isEqual(CellValueRecordInterface i) + { + return ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())); + } + + public boolean isInValueSection() + { + return true; + } + + public boolean isValue() + { + return true; + } + + public int compareTo(Object obj) + { + CellValueRecordInterface loc = ( CellValueRecordInterface ) obj; + + if ((this.getRow() == loc.getRow()) + && (this.getColumn() == loc.getColumn())) + { + return 0; + } + if (this.getRow() < loc.getRow()) + { + return -1; + } + if (this.getRow() > loc.getRow()) + { + return 1; + } + if (this.getColumn() < loc.getColumn()) + { + return -1; + } + if (this.getColumn() > loc.getColumn()) + { + return 1; + } + return -1; + } + + public boolean equals(Object obj) + { + if (!(obj instanceof CellValueRecordInterface)) + { + return false; + } + CellValueRecordInterface loc = ( CellValueRecordInterface ) obj; + + if ((this.getRow() == loc.getRow()) + && (this.getColumn() == loc.getColumn())) + { + return true; + } + return false; + } +} diff --git a/src/java/org/apache/poi/hssf/record/PasswordRecord.java b/src/java/org/apache/poi/hssf/record/PasswordRecord.java new file mode 100644 index 000000000..553f4402b --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/PasswordRecord.java @@ -0,0 +1,169 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Password Record

+ * Description: stores the encrypted password for a sheet or workbook (HSSF doesn't support encryption) + * REFERENCE: PG 371 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class PasswordRecord + extends Record +{ + public final static short sid = 0x13; + private short field_1_password; // not sure why this is only 2 bytes, but it is... go figure + + public PasswordRecord() + { + } + + /** + * Constructs a Password record and sets its fields appropriately. + * + * @param short id must be 0x13 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public PasswordRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a Password record and sets its fields appropriately. + * + * @param short id must be 0x13 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the data + */ + + public PasswordRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A PASSWORD RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_password = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set the password + * + * @param short representing the password + */ + + public void setPassword(short password) + { + field_1_password = password; + } + + /** + * get the password + * + * @return short representing the password + */ + + public short getPassword() + { + return field_1_password; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[PASSWORD]\n"); + buffer.append(" .password = ") + .append(Integer.toHexString(getPassword())).append("\n"); + buffer.append("[/PASSWORD]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, getPassword()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/PasswordRev4Record.java b/src/java/org/apache/poi/hssf/record/PasswordRev4Record.java new file mode 100644 index 000000000..8170c13d2 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/PasswordRev4Record.java @@ -0,0 +1,170 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Protection Revision 4 password Record

+ * Description: Stores the (2 byte??!!) encrypted password for a shared + * workbook

+ * REFERENCE: PG 374 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class PasswordRev4Record + extends Record +{ + public final static short sid = 0x1BC; + private short field_1_password; + + public PasswordRev4Record() + { + } + + /** + * Constructs a PasswordRev4 (PROT4REVPASS) record and sets its fields appropriately. + * + * @param short id must be 0x1bc or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public PasswordRev4Record(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a PasswordRev4 (PROT4REVPASS) record and sets its fields appropriately. + * + * @param short id must be 0x1bc or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the data + */ + + public PasswordRev4Record(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A PROT4REVPASSWORD RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_password = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set the password + * + * @param short representing the password + */ + + public void setPassword(short pw) + { + field_1_password = pw; + } + + /** + * get the password + * + * @return short representing the password + */ + + public short getPassword() + { + return field_1_password; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[PROT4REVPASSWORD]\n"); + buffer.append(" .password = ") + .append(Integer.toHexString(getPassword())).append("\n"); + buffer.append("[/PROT4REVPASSWORD]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, getPassword()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/PrecisionRecord.java b/src/java/org/apache/poi/hssf/record/PrecisionRecord.java new file mode 100644 index 000000000..7b876bf4e --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/PrecisionRecord.java @@ -0,0 +1,177 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Precision Record

+ * Description: defines whether to store with full precision or what's displayed by the gui + * (meaning have really screwed up and skewed figures or only think you do!)

+ * REFERENCE: PG 372 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class PrecisionRecord + extends Record +{ + public final static short sid = 0xE; + public short field_1_precision; + + public PrecisionRecord() + { + } + + /** + * Constructs a Precision record and sets its fields appropriately. + * + * @param short id must be 0xe or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public PrecisionRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a Precision record and sets its fields appropriately. + * + * @param short id must be 0xe or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record + */ + + public PrecisionRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A PRECISION RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_precision = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set whether to use full precision or just skew all you figures all to hell. + * + * @param fullprecision - or not + */ + + public void setFullPrecision(boolean fullprecision) + { + if (fullprecision == true) + { + field_1_precision = 1; + } + else + { + field_1_precision = 0; + } + } + + /** + * get whether to use full precision or just skew all you figures all to hell. + * + * @return fullprecision - or not + */ + + public boolean getFullPrecision() + { + return (field_1_precision == 1); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[PRECISION]\n"); + buffer.append(" .precision = ").append(getFullPrecision()) + .append("\n"); + buffer.append("[/PRECISION]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, field_1_precision); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/PrintGridlinesRecord.java b/src/java/org/apache/poi/hssf/record/PrintGridlinesRecord.java new file mode 100644 index 000000000..a8dd6596d --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/PrintGridlinesRecord.java @@ -0,0 +1,176 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Print Gridlines Record

+ * Description: whether to print the gridlines when you enjoy you spreadsheet on paper.

+ * REFERENCE: PG 373 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class PrintGridlinesRecord + extends Record +{ + public final static short sid = 0x2b; + private short field_1_print_gridlines; + + public PrintGridlinesRecord() + { + } + + /** + * Constructs a PrintGridlines record and sets its fields appropriately. + * + * @param short id must be 0x2b or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public PrintGridlinesRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a PrintGridlines record and sets its fields appropriately. + * + * @param short id must be 0x2b or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record data + */ + + public PrintGridlinesRecord(short id, short size, byte [] data, + int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A PrintGridlines RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_print_gridlines = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set whether or not to print the gridlines (and make your spreadsheet ugly) + * + * @param make spreadsheet ugly - Y/N + */ + + public void setPrintGridlines(boolean pg) + { + if (pg == true) + { + field_1_print_gridlines = 1; + } + else + { + field_1_print_gridlines = 0; + } + } + + /** + * get whether or not to print the gridlines (and make your spreadsheet ugly) + * + * @return make spreadsheet ugly - Y/N + */ + + public boolean getPrintGridlines() + { + return (field_1_print_gridlines == 1); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[PRINTGRIDLINES]\n"); + buffer.append(" .printgridlines = ").append(getPrintGridlines()) + .append("\n"); + buffer.append("[/PRINTGRIDLINES]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x2); + LittleEndian.putShort(data, 4 + offset, field_1_print_gridlines); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/PrintHeadersRecord.java b/src/java/org/apache/poi/hssf/record/PrintHeadersRecord.java new file mode 100644 index 000000000..333ba5ecc --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/PrintHeadersRecord.java @@ -0,0 +1,174 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Print Headers Record

+ * Description: Whether or not to print the row/column headers when you + * enjoy your spreadsheet in the physical form.

+ * REFERENCE: PG 373 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class PrintHeadersRecord + extends Record +{ + public final static short sid = 0x2a; + private short field_1_print_headers; + + public PrintHeadersRecord() + { + } + + /** + * Constructs a PrintHeaders record and sets its fields appropriately. + * + * @param short id must be 0x2a or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public PrintHeadersRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a PrintHeaders record and sets its fields appropriately. + * + * @param short id must be 0x2a or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the data + */ + + public PrintHeadersRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A PrintHeaders RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_print_headers = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set to print the headers - y/n + * @param printheaders or not + */ + + public void setPrintHeaders(boolean p) + { + if (p == true) + { + field_1_print_headers = 1; + } + else + { + field_1_print_headers = 0; + } + } + + /** + * get whether to print the headers - y/n + * @return printheaders or not + */ + + public boolean getPrintHeaders() + { + return (field_1_print_headers == 1); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[PRINTHEADERS]\n"); + buffer.append(" .printheaders = ").append(getPrintHeaders()) + .append("\n"); + buffer.append("[/PRINTHEADERS]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x2); + LittleEndian.putShort(data, 4 + offset, field_1_print_headers); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/PrintSetupRecord.java b/src/java/org/apache/poi/hssf/record/PrintSetupRecord.java new file mode 100644 index 000000000..9a09f82b1 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/PrintSetupRecord.java @@ -0,0 +1,426 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.BitField; + +/** + * Title: Print Setup Record

+ * Description: Stores print setup options -- bogus for HSSF (and marked as such)

+ * REFERENCE: PG 385 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class PrintSetupRecord + extends Record +{ + public final static short sid = 0xa1; + private short field_1_paper_size; + private short field_2_scale; + private short field_3_page_start; + private short field_4_fit_width; + private short field_5_fit_height; + private short field_6_options; + static final private BitField lefttoright = + new BitField(0x01); // print over then down + static final private BitField landscape = + new BitField(0x02); // landscape mode + static final private BitField validsettings = new BitField( + 0x04); // if papersize, scale, resolution, copies, landscape + + // weren't obtained from the print consider them + // mere bunk + static final private BitField nocolor = + new BitField(0x08); // print mono/b&w, colorless + static final private BitField draft = + new BitField(0x10); // print draft quality + static final private BitField notes = + new BitField(0x20); // print the notes + static final private BitField noOrientation = + new BitField(0x40); // the orientation is not set + static final private BitField usepage = + new BitField(0x80); // use a user set page no, instead of auto + private short field_7_hresolution; + private short field_8_vresolution; + private double field_9_headermargin; + private double field_10_footermargin; + private short field_11_copies; + + public PrintSetupRecord() + { + } + + /** + * Constructs a PrintSetup (SETUP) record and sets its fields appropriately. + * + * @param short id must be 0xa1 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public PrintSetupRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a PrintSetup (SETUP) record and sets its fields appropriately. + * + * @param short id must be 0xa1 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public PrintSetupRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException( + "NOT A valid PrintSetup record RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_paper_size = LittleEndian.getShort(data, 0 + offset); + field_2_scale = LittleEndian.getShort(data, 2 + offset); + field_3_page_start = LittleEndian.getShort(data, 4 + offset); + field_4_fit_width = LittleEndian.getShort(data, 6 + offset); + field_5_fit_height = LittleEndian.getShort(data, 8 + offset); + field_6_options = LittleEndian.getShort(data, 10 + offset); + field_7_hresolution = LittleEndian.getShort(data, 12 + offset); + field_8_vresolution = LittleEndian.getShort(data, 14 + offset); + field_9_headermargin = LittleEndian.getDouble(data, 16 + offset); + field_10_footermargin = LittleEndian.getDouble(data, 24 + offset); + field_11_copies = LittleEndian.getShort(data, 32 + offset); + } + + public void setPaperSize(short size) + { + field_1_paper_size = size; + } + + public void setScale(short scale) + { + field_2_scale = scale; + } + + public void setPageStart(short start) + { + field_3_page_start = start; + } + + public void setFitWidth(short width) + { + field_4_fit_width = width; + } + + public void setFitHeight(short height) + { + field_5_fit_height = height; + } + + public void setOptions(short options) + { + field_6_options = options; + } + + // option bitfields + public void setLeftToRight(boolean ltor) + { + lefttoright.setShortBoolean(field_6_options, ltor); + } + + public void setLandscape(boolean ls) + { + landscape.setShortBoolean(field_6_options, ls); + } + + public void setValidSettings(boolean valid) + { + validsettings.setShortBoolean(field_6_options, valid); + } + + public void setNoColor(boolean mono) + { + nocolor.setShortBoolean(field_6_options, mono); + } + + public void setDraft(boolean d) + { + draft.setShortBoolean(field_6_options, d); + } + + public void setNotes(boolean printnotes) + { + notes.setShortBoolean(field_6_options, printnotes); + } + + public void setNoOrientation(boolean orientation) + { + noOrientation.setShortBoolean(field_6_options, orientation); + } + + public void setUsePage(boolean page) + { + usepage.setShortBoolean(field_6_options, page); + } + + // end option bitfields + public void setHResolution(short resolution) + { + field_7_hresolution = resolution; + } + + public void setVResolution(short resolution) + { + field_8_vresolution = resolution; + } + + public void setHeaderMargin(double headermargin) + { + field_9_headermargin = headermargin; + } + + public void setFooterMargin(double footermargin) + { + field_10_footermargin = footermargin; + } + + public void setCopies(short copies) + { + field_11_copies = copies; + } + + public short getPaperSize() + { + return field_1_paper_size; + } + + public short getScale() + { + return field_2_scale; + } + + public short getPageStart() + { + return field_3_page_start; + } + + public short getFitWidth() + { + return field_4_fit_width; + } + + public short getFitHeight() + { + return field_5_fit_height; + } + + public short getOptions() + { + return field_6_options; + } + + // option bitfields + public boolean getLeftToRight() + { + return lefttoright.isSet(field_6_options); + } + + public boolean getLandscape() + { + return landscape.isSet(field_6_options); + } + + public boolean getValidSettings() + { + return validsettings.isSet(field_6_options); + } + + public boolean getNoColor() + { + return nocolor.isSet(field_6_options); + } + + public boolean getDraft() + { + return draft.isSet(field_6_options); + } + + public boolean getNotes() + { + return notes.isSet(field_6_options); + } + + public boolean getNoOrientation() + { + return noOrientation.isSet(field_6_options); + } + + public boolean getUsePage() + { + return usepage.isSet(field_6_options); + } + + // end option bitfields + public short getHResolution() + { + return field_7_hresolution; + } + + public short getVResolution() + { + return field_8_vresolution; + } + + public double getHeaderMargin() + { + return field_9_headermargin; + } + + public double getFooterMargin() + { + return field_10_footermargin; + } + + public short getCopies() + { + return field_11_copies; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[PRINTSETUP]\n"); + buffer.append(" .papersize = ").append(getPaperSize()) + .append("\n"); + buffer.append(" .scale = ").append(getScale()) + .append("\n"); + buffer.append(" .pagestart = ").append(getPageStart()) + .append("\n"); + buffer.append(" .fitwidth = ").append(getFitWidth()) + .append("\n"); + buffer.append(" .fitheight = ").append(getFitHeight()) + .append("\n"); + buffer.append(" .options = ").append(getOptions()) + .append("\n"); + buffer.append(" .ltor = ").append(getLeftToRight()) + .append("\n"); + buffer.append(" .landscape = ").append(getLandscape()) + .append("\n"); + buffer.append(" .valid = ").append(getValidSettings()) + .append("\n"); + buffer.append(" .mono = ").append(getNoColor()) + .append("\n"); + buffer.append(" .draft = ").append(getDraft()) + .append("\n"); + buffer.append(" .notes = ").append(getNotes()) + .append("\n"); + buffer.append(" .noOrientat = ").append(getNoOrientation()) + .append("\n"); + buffer.append(" .usepage = ").append(getUsePage()) + .append("\n"); + buffer.append(" .hresolution = ").append(getHResolution()) + .append("\n"); + buffer.append(" .vresolution = ").append(getVResolution()) + .append("\n"); + buffer.append(" .headermargin = ").append(getHeaderMargin()) + .append("\n"); + buffer.append(" .footermargin = ").append(getFooterMargin()) + .append("\n"); + buffer.append(" .copies = ").append(getCopies()) + .append("\n"); + buffer.append("[/PRINTSETUP]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 34); + LittleEndian.putShort(data, 4 + offset, getPaperSize()); + LittleEndian.putShort(data, 6 + offset, getScale()); + LittleEndian.putShort(data, 8 + offset, getPageStart()); + LittleEndian.putShort(data, 10 + offset, getFitWidth()); + LittleEndian.putShort(data, 12 + offset, getFitHeight()); + LittleEndian.putShort(data, 14 + offset, getOptions()); + LittleEndian.putShort(data, 16 + offset, getHResolution()); + LittleEndian.putShort(data, 18 + offset, getVResolution()); + LittleEndian.putDouble(data, 20 + offset, getHeaderMargin()); + LittleEndian.putDouble(data, 28 + offset, getFooterMargin()); + LittleEndian.putShort(data, 36 + offset, getCopies()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 38; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/ProtectRecord.java b/src/java/org/apache/poi/hssf/record/ProtectRecord.java new file mode 100644 index 000000000..d40f4bfcb --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/ProtectRecord.java @@ -0,0 +1,176 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Protect Record

+ * Description: defines whether a sheet or workbook is protected (HSSF DOES NOT SUPPORT ENCRYPTION)

+ * (kindly ask the US government to stop having arcane stupid encryption laws and we'll support it)

+ * (after all terrorists will all use US-legal encrypton right??)

+ * REFERENCE: PG 373 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class ProtectRecord + extends Record +{ + public final static short sid = 0x12; + private short field_1_protect; + + public ProtectRecord() + { + } + + /** + * Constructs a Protect record and sets its fields appropriately. + * + * @param short id must be 0x12 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public ProtectRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a Protect record and sets its fields appropriately. + * + * @param short id must be 0x12 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the data + */ + + public ProtectRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A PROTECT RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_protect = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set whether the sheet is protected or not + * @param whether to protect the sheet or not + */ + + public void setProtect(boolean protect) + { + if (protect) + { + field_1_protect = 1; + } + else + { + field_1_protect = 0; + } + } + + /** + * get whether the sheet is protected or not + * @return whether to protect the sheet or not + */ + + public short getProtect() + { + return field_1_protect; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[PROTECT]\n"); + buffer.append(" .rowheight = ") + .append(Integer.toHexString(getProtect())).append("\n"); + buffer.append("[/PROTECT]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, getProtect()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/ProtectionRev4Record.java b/src/java/org/apache/poi/hssf/record/ProtectionRev4Record.java new file mode 100644 index 000000000..6c203f3e4 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/ProtectionRev4Record.java @@ -0,0 +1,176 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Protection Revision 4 Record

+ * Description: describes whether this is a protected shared/tracked workbook

+ * ( HSSF does not support encryption because we don't feel like going to jail )

+ * REFERENCE: PG 373 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class ProtectionRev4Record + extends Record +{ + public final static short sid = 0x1af; + private short field_1_protect; + + public ProtectionRev4Record() + { + } + + /** + * Constructs a ProtectionRev4 record and sets its fields appropriately. + * + * @param short id must be 0x1af or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public ProtectionRev4Record(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a ProtectionRev4 record and sets its fields appropriately. + * + * @param short id must be 0x1af or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the data + */ + + public ProtectionRev4Record(short id, short size, byte [] data, + int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A PROTECTION REV 4 RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_protect = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set whether the this is protected shared/tracked workbook or not + * @param whether to protect the workbook or not + */ + + public void setProtect(boolean protect) + { + if (protect) + { + field_1_protect = 1; + } + else + { + field_1_protect = 0; + } + } + + /** + * get whether the this is protected shared/tracked workbook or not + * @return whether to protect the workbook or not + */ + + public short getProtect() + { + return field_1_protect; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[PROT4REV]\n"); + buffer.append(" .rowheight = ") + .append(Integer.toHexString(getProtect())).append("\n"); + buffer.append("[/PROT4REV]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, getProtect()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/RKRecord.java b/src/java/org/apache/poi/hssf/record/RKRecord.java new file mode 100644 index 000000000..544668d28 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/RKRecord.java @@ -0,0 +1,377 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: RK Record + * Description: An internal 32 bit number with the two most significant bits + * storing the type. This is part of a bizarre scheme to save disk + * space and memory (gee look at all the other whole records that + * are in the file just "cause"..,far better to waste processor + * cycles on this then leave on of those "valuable" records out).

+ * We support this in READ-ONLY mode. HSSF converts these to NUMBER records

+ * + * + * + * REFERENCE: PG 376 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + * @see org.apache.poi.hssf.record.NumberRecord + */ + +public class RKRecord + extends Record + implements CellValueRecordInterface +{ + public final static short sid = 0x27e; + public final static short RK_IEEE_NUMBER = 0; + public final static short RK_IEEE_NUMBER_TIMES_100 = 1; + public final static short RK_INTEGER = 2; + public final static short RK_INTEGER_TIMES_100 = 3; + private short field_1_row; + private short field_2_col; + private short field_3_xf_index; + private int field_4_rk_number; + private double rkNumber; + + public RKRecord() + { + } + + /** + * Constructs a RK record and sets its fields appropriately. + * + * @param short id must be 0x27e or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public RKRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a RK record and sets its fields appropriately. + * + * @param short id must be 0x27e or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the data + */ + + public RKRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A valid RK RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_row = LittleEndian.getShort(data, 0 + offset); + field_2_col = LittleEndian.getShort(data, 2 + offset); + field_3_xf_index = LittleEndian.getShort(data, 4 + offset); + field_4_rk_number = LittleEndian.getInt(data, 6 + offset); + } + + public short getRow() + { + return field_1_row; + } + + public short getColumn() + { + return field_2_col; + } + + public short getXFIndex() + { + return field_3_xf_index; + } + + public int getRKField() + { + return field_4_rk_number; + } + + /** + * Get the type of the number + * + * @return one of these values: + *

    + *
  1. RK_IEEE_NUMBER
  2. + *
  3. RK_IEEE_NUMBER_TIMES_100
  4. + *
  5. RK_INTEGER
  6. + *
  7. RK_INTEGER_TIMES_100
  8. + *
+ */ + + public short getRKType() + { + return ( short ) (field_4_rk_number & 3); + } + + /** + * Extract the value of the number + *

+ * The mechanism for determining the value is dependent on the two + * low order bits of the raw number. If bit 1 is set, the number + * is an integer and can be cast directly as a double, otherwise, + * it's apparently the exponent and mantissa of a double (and the + * remaining low-order bits of the double's mantissa are 0's). + *

+ * If bit 0 is set, the result of the conversion to a double is + * divided by 100; otherwise, the value is left alone. + *

+ * [insert picture of Screwy Squirrel in full Napoleonic regalia] + * + * @return the value as a proper double (hey, it could + * happen) + */ + + public double getRKNumber() + { + return decodeNumber(field_4_rk_number); + } + + /** + * Do the dirty work of decoding; made a private static method to + * facilitate testing the algorithm + */ + + private static double decodeNumber(int number) + { + long raw_number = number; + + // mask off the two low-order bits, 'cause they're not part of + // the number + raw_number &= -3; + double rvalue = 0; + + if ((number & 0x02) == 0x02) + { + + // ok, it's just a plain ol' int; we can handle this + // trivially by right-shifting and casting + rvalue = ( double ) (raw_number >> 2); + } + else + { + + // also trivial, but not as obvious ... left shift the + // bits high and use that clever static method in Double + // to convert the resulting bit image to a double + rvalue = Double.longBitsToDouble(raw_number << 32); + } + if ((number & 0x01) == 0x01) + { + + // low-order bit says divide by 100, and so we do. Why? + // 'cause that's what the algorithm says. Can't fight city + // hall, especially if it's the city of Redmond + rvalue /= 100; + } + return rvalue; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[RK]\n"); + buffer.append(" .row = ") + .append(Integer.toHexString(getRow())).append("\n"); + buffer.append(" .col = ") + .append(Integer.toHexString(getColumn())).append("\n"); + buffer.append(" .xfindex = ") + .append(Integer.toHexString(getXFIndex())).append("\n"); + buffer.append(" .rknumber = ") + .append(Integer.toHexString(getRKField())).append("\n"); + buffer.append(" .rktype = ") + .append(Integer.toHexString(getRKType())).append("\n"); + buffer.append(" .rknumber = ").append(getRKNumber()) + .append("\n"); + buffer.append("[/RK]\n"); + return buffer.toString(); + } + +//temporarily just constructs a new number record and returns its value + public int serialize(int offset, byte [] data) + { + NumberRecord rec = new NumberRecord(); + + rec.setColumn(getColumn()); + rec.setRow(getRow()); + rec.setValue(getRKNumber()); + rec.setXFIndex(getXFIndex()); + return rec.serialize(offset, data); + } + + /** + * Debugging main() + *

+ * Normally I'd do this in a junit test, but let's face it -- once + * this algorithm has been tested and it works, we are never ever + * going to change it. This is driven by the Faceless Enemy's + * minions, who dare not change the algorithm out from under us. + * + * @param ignored_args command line arguments, which we blithely + * ignore + */ + + public static void main(String ignored_args[]) + { + int[] values = + { + 0x3FF00000, 0x405EC001, 0x02F1853A, 0x02F1853B, 0xFCDD699A + }; + double[] rvalues = + { + 1, 1.23, 12345678, 123456.78, -13149594 + }; + + for (int j = 0; j < values.length; j++) + { + System.out.println("input = " + Integer.toHexString(values[ j ]) + + " -> " + rvalues[ j ] + ": " + + RKRecord.decodeNumber(values[ j ])); + } + } + + public short getSid() + { + return this.sid; + } + + public boolean isBefore(CellValueRecordInterface i) + { + if (this.getRow() > i.getRow()) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() > i.getColumn())) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())) + { + return false; + } + return true; + } + + public boolean isAfter(CellValueRecordInterface i) + { + if (this.getRow() < i.getRow()) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() < i.getColumn())) + { + return false; + } + if ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())) + { + return false; + } + return true; + } + + public boolean isEqual(CellValueRecordInterface i) + { + return ((this.getRow() == i.getRow()) + && (this.getColumn() == i.getColumn())); + } + + public boolean isInValueSection() + { + return true; + } + + public boolean isValue() + { + return true; + } + + public void setColumn(short col) + { + } + + public void setRow(short row) + { + } + + /** + * NO OP! + */ + + public void setXFIndex(short xf) + { + } +} diff --git a/src/java/org/apache/poi/hssf/record/Record.java b/src/java/org/apache/poi/hssf/record/Record.java new file mode 100644 index 000000000..3c6f62591 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/Record.java @@ -0,0 +1,244 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +/** + * Title: Record + * Description: All HSSF Records inherit from this class. It + * populates the fields common to all records (id, size and data). + * Subclasses should be sure to validate the id, + * Company: + * @author Andrew C. Oliver + * @author Marc Johnson (mjohnson at apache dot org) + * @version 2.0-pre + */ + +public abstract class Record +{ + + /** + * The static ID, subclasses should override this value with the id for the + * record type they handle. + */ + + public short sid = 0; + private short id = 0; + private short size = 0; + private byte[] data = null; + + /** + * instantiates a blank record strictly for ID matching + */ + + public Record() + { + } + + /** + * Constructor Record + * + * @param id record id + * @param size record size + * @param data raw data + */ + + public Record(short id, short size, byte [] data) + { + this.id = id; + this.size = size; + this.data = data; + validateSid(id); + fillFields(data, size); + } + + /** + * Constructor Record + * + * @param id record id + * @param size record size + * @param data raw data + */ + + public Record(short id, short size, byte [] data, int offset) + { + this.id = id; + this.size = size; + this.data = data; + validateSid(id); + fillFields(data, size, offset); + } + + /** + * called by constructor, should throw runtime exception in the event of a + * record passed with a differing ID. + * + * @param id alleged id for this record + */ + + protected abstract void validateSid(short id); + + /** + * called by the constructor, should set class level fields. Should throw + * runtime exception for bad/icomplete data. + * + * @param data raw data + */ + + protected void fillFields(byte [] data, short size) + { + fillFields(data, size, 0); + } + + /** + * called by the constructor, should set class level fields. Should throw + * runtime exception for bad/icomplete data. + * + * @param data raw data + * @param size size of data + * @param offset of the record's data (provided a big array of the file) + */ + + protected abstract void fillFields(byte [] data, short size, int offset); + + /** + * 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 + */ + + public byte [] serialize() + { + byte[] retval = new byte[ getRecordSize() ]; + + serialize(0, retval); + return retval; + } + + /** + * 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. + * + * @param offset to begin writing at + * @param byte array containing instance data + * @return number of bytes written + */ + + public abstract int serialize(int offset, byte [] data); + + /** + * gives the current serialized size of the record. + */ + + public int getRecordSize() + { + + // this is kind od a stupid way to do it but for now we just serialize + // the record and return the size of the byte array + return serialize().length; + } + + /** + * tells whether this type of record contains a value + */ + + public boolean isValue() + { + return false; + } + + /** + * DBCELL, ROW, VALUES all say yes + */ + + public boolean isInValueSection() + { + return false; + } + + /** + * get a string representation of the record (for biffview/debugging) + */ + + public String toString() + { + return super.toString(); + } + + /** + * Process a continuation record; default handling is to ignore + * it -- TODO add logging + * + * @param record the continuation record's data + */ + + // made public to satisfy biffviewer + + /* protected */ + public void processContinueRecord(byte [] record) + { + + // System.out.println("Got a continue record ... NOW what??"); + } + + /** + * return the non static version of the id for this record. + */ + + public abstract short getSid(); +} diff --git a/src/java/org/apache/poi/hssf/record/RecordFactory.java b/src/java/org/apache/poi/hssf/record/RecordFactory.java new file mode 100644 index 000000000..4b1400a87 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/RecordFactory.java @@ -0,0 +1,329 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import java.io.InputStream; +import java.io.IOException; + +import java.util.*; + +import java.lang.reflect.Constructor; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.HexDump; + +/** + * Title: Record Factory

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

+ * + * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Marc Johnson (mjohnson at apache dot org) + * @author Glen Stampoultzis (gstamp at iprimus dot com dot au) + * @version 1.0-pre + */ + +public class RecordFactory +{ + private static int NUM_RECORDS = 10000; + private static final Class[] records = new Class[] + { + BOFRecord.class, InterfaceHdrRecord.class, MMSRecord.class, + InterfaceEndRecord.class, WriteAccessRecord.class, + CodepageRecord.class, DSFRecord.class, TabIdRecord.class, + FnGroupCountRecord.class, WindowProtectRecord.class, + ProtectRecord.class, PasswordRecord.class, ProtectionRev4Record.class, + PasswordRev4Record.class, WindowOneRecord.class, BackupRecord.class, + HideObjRecord.class, DateWindow1904Record.class, + PrecisionRecord.class, RefreshAllRecord.class, BookBoolRecord.class, + FontRecord.class, FormatRecord.class, ExtendedFormatRecord.class, + StyleRecord.class, UseSelFSRecord.class, BoundSheetRecord.class, + CountryRecord.class, SSTRecord.class, ExtSSTRecord.class, + EOFRecord.class, IndexRecord.class, CalcModeRecord.class, + CalcCountRecord.class, RefModeRecord.class, IterationRecord.class, + DeltaRecord.class, SaveRecalcRecord.class, PrintHeadersRecord.class, + PrintGridlinesRecord.class, GridsetRecord.class, GutsRecord.class, + DefaultRowHeightRecord.class, WSBoolRecord.class, HeaderRecord.class, + FooterRecord.class, HCenterRecord.class, VCenterRecord.class, + PrintSetupRecord.class, DefaultColWidthRecord.class, + DimensionsRecord.class, RowRecord.class, LabelSSTRecord.class, + RKRecord.class, NumberRecord.class, DBCellRecord.class, + WindowTwoRecord.class, SelectionRecord.class, ContinueRecord.class, + LabelRecord.class, BlankRecord.class, ColumnInfoRecord.class, + MulRKRecord.class, MulBlankRecord.class, MergeCellsRecord.class, + FormulaRecord.class + }; + private static Map recordsMap = recordsToMap(records); + + /** + * changes the default capacity (10000) to handle larger files + */ + + public static void setCapacity(int capacity) + { + NUM_RECORDS = capacity; + } + + /** + * Create an array of records from an input stream + * + * @param in the InputStream from which the records will be + * obtained + * + * @return an array of Records created from the InputStream + * + * @exception RecordFormatException on error processing the + * InputStream + */ + + public static List createRecords(InputStream in) + throws RecordFormatException + { + ArrayList records = new ArrayList(NUM_RECORDS); + Record last_record = null; + int loc = 0; + + try + { + long offset = 0; + short rectype = 0; + + do + { + rectype = LittleEndian.readShort(in); + loc += 2; + if (rectype != 0) + { + short recsize = LittleEndian.readShort(in); + byte[] data = new byte[ ( int ) recsize ]; + + in.read(data); + loc += recsize; + offset += 4 + recsize; + Record[] recs = createRecord(rectype, recsize, + data); // handle MulRK records + + if (recs.length > 1) + { + for (int k = 0; k < recs.length; k++) + { + records.add( + recs[ k ]); // these will be number records + last_record = + recs[ k ]; // do to keep the algorythm homogenous...you can't + } // actually continue a number record anyhow. + } + else + { + Record record = recs[ 0 ]; + + if (record != null) + { + if (rectype == ContinueRecord.sid) + { + if (last_record == null) + { + throw new RecordFormatException( + "First record is a ContinueRecord??"); + } + last_record.processContinueRecord(data); + } + else + { + last_record = record; + records.add(record); + } + } + } + } + } + while (rectype != 0); + } + catch (IOException e) + { + throw new RecordFormatException("Error reading bytes"); + } + + // Record[] retval = new Record[ records.size() ]; + // retval = ( Record [] ) records.toArray(retval); + return records; + } + + public static Record [] createRecord(short rectype, short size, + byte [] data) + { + Record retval = null; + Record[] realretval = null; + + try + { + Constructor constructor = + ( Constructor ) recordsMap.get(new Short(rectype)); + + if (constructor != null) + { + retval = ( Record ) constructor.newInstance(new Object[] + { + new Short(rectype), new Short(size), data + }); + } + else + { + retval = new UnknownRecord(rectype, size, data); + } + } + catch (Exception introspectionException) + { + throw new RecordFormatException( + "Unable to construct record instance"); + } + if (retval instanceof RKRecord) + { + RKRecord rk = ( RKRecord ) retval; + NumberRecord num = new NumberRecord(); + + num.setColumn(rk.getColumn()); + num.setRow(rk.getRow()); + num.setXFIndex(rk.getXFIndex()); + num.setValue(rk.getRKNumber()); + retval = num; + } + else if (retval instanceof DBCellRecord) + { + retval = null; + } + else if (retval instanceof MulRKRecord) + { + MulRKRecord mrk = ( MulRKRecord ) retval; + + realretval = new Record[ mrk.getNumColumns() ]; + for (int k = 0; k < mrk.getNumColumns(); k++) + { + NumberRecord nr = new NumberRecord(); + + nr.setColumn(( short ) (k + mrk.getFirstColumn())); + nr.setRow(mrk.getRow()); + nr.setXFIndex(mrk.getXFAt(k)); + nr.setValue(mrk.getRKNumberAt(k)); + realretval[ k ] = nr; + } + } + else if (retval instanceof MulBlankRecord) + { + MulBlankRecord mb = ( MulBlankRecord ) retval; + + realretval = new Record[ mb.getNumColumns() ]; + for (int k = 0; k < mb.getNumColumns(); k++) + { + BlankRecord br = new BlankRecord(); + + br.setColumn(( short ) (k + mb.getFirstColumn())); + br.setRow(mb.getRow()); + br.setXFIndex(mb.getXFAt(k)); + realretval[ k ] = br; + } + } + if (realretval == null) + { + realretval = new Record[ 1 ]; + realretval[ 0 ] = retval; + } + return realretval; + } + + public static short [] getAllKnownRecordSIDs() + { + short[] results = new short[ recordsMap.size() ]; + int i = 0; + + for (Iterator iterator = recordsMap.keySet().iterator(); + iterator.hasNext(); ) + { + Short sid = ( Short ) iterator.next(); + + results[ i++ ] = sid.shortValue(); + } + return results; + } + + private static Map recordsToMap(Class [] records) + { + Map result = new HashMap(); + Constructor constructor; + + for (int i = 0; i < records.length; i++) + { + Class record = null; + short sid = 0; + + record = records[ i ]; + try + { + sid = record.getField("sid").getShort(null); + constructor = record.getConstructor(new Class[] + { + short.class, short.class, byte [].class + }); + } + catch (Exception illegalArgumentException) + { + throw new RecordFormatException( + "Unable to determine record types"); + } + result.put(new Short(sid), constructor); + } + return result; + } +} diff --git a/src/java/org/apache/poi/hssf/record/RecordFormatException.java b/src/java/org/apache/poi/hssf/record/RecordFormatException.java new file mode 100644 index 000000000..65665d284 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/RecordFormatException.java @@ -0,0 +1,70 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +/** + * Title: Record Format Exception + * Description: Used by records to indicate invalid format/data.

+ */ + +public class RecordFormatException + extends RuntimeException +{ + public RecordFormatException(String exception) + { + super(exception); + } +} diff --git a/src/java/org/apache/poi/hssf/record/RefModeRecord.java b/src/java/org/apache/poi/hssf/record/RefModeRecord.java new file mode 100644 index 000000000..df06d55c7 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/RefModeRecord.java @@ -0,0 +1,173 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: RefMode Record

+ * Description: Describes which reference mode to use

+ * REFERENCE: PG 376 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class RefModeRecord + extends Record +{ + public final static short sid = 0xf; + public final static short USE_A1_MODE = 1; + public final static short USE_R1C1_MODE = 0; + private short field_1_mode; + + public RefModeRecord() + { + } + + /** + * Constructs a RefMode record and sets its fields appropriately. + * + * @param short id must be 0xf or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public RefModeRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a RefMode record and sets its fields appropriately. + * + * @param short id must be 0xf or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public RefModeRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT An RefMode RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_mode = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set the reference mode to use (HSSF uses/assumes A1) + * @param the mode to use + * @see #USE_A1_MODE + * @see #USE_R1C1_MODE + * + */ + + public void setMode(short mode) + { + field_1_mode = mode; + } + + /** + * get the reference mode to use (HSSF uses/assumes A1) + * @return mode to use + * @see #USE_A1_MODE + * @see #USE_R1C1_MODE + */ + + public short getMode() + { + return field_1_mode; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[REFMODE]\n"); + buffer.append(" .mode = ") + .append(Integer.toHexString(getMode())).append("\n"); + buffer.append("[/REFMODE]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x2); + LittleEndian.putShort(data, 4 + offset, getMode()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/RefreshAllRecord.java b/src/java/org/apache/poi/hssf/record/RefreshAllRecord.java new file mode 100644 index 000000000..edf9403d0 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/RefreshAllRecord.java @@ -0,0 +1,175 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Refresh All Record

+ * Description: Flag whether to refresh all external data when loading a sheet. + * (which hssf doesn't support anyhow so who really cares?)

+ * REFERENCE: PG 376 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class RefreshAllRecord + extends Record +{ + public final static short sid = 0x1B7; + private short field_1_refreshall; + + public RefreshAllRecord() + { + } + + /** + * Constructs a RefreshAll record and sets its fields appropriately. + * + * @param short id must be 0x187 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public RefreshAllRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a RefreshAll record and sets its fields appropriately. + * + * @param short id must be 0x187 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record data + */ + + public RefreshAllRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A REFRESHALL RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_refreshall = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set whether to refresh all external data when loading a sheet + * @param refreshall or not + */ + + public void setRefreshAll(boolean refreshall) + { + if (refreshall) + { + field_1_refreshall = 1; + } + else + { + field_1_refreshall = 0; + } + } + + /** + * get whether to refresh all external data when loading a sheet + * @return refreshall or not + */ + + public boolean getRefreshAll() + { + return (field_1_refreshall == 1); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[REFRESHALL]\n"); + buffer.append(" .refreshall = ").append(getRefreshAll()) + .append("\n"); + buffer.append("[/REFRESHALL]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, field_1_refreshall); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/RowRecord.java b/src/java/org/apache/poi/hssf/record/RowRecord.java new file mode 100644 index 000000000..36232656a --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/RowRecord.java @@ -0,0 +1,510 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.BitField; +import org.apache.poi.util.LittleEndian; + +/** + * Title: Row Record

+ * Description: stores the row information for the sheet.

+ * REFERENCE: PG 379 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class RowRecord + extends Record + implements Comparable +{ + public final static short sid = 0x208; + private short field_1_row_number; + private short field_2_first_col; + private short field_3_last_col; // plus 1 + private short field_4_height; + private short field_5_optimize; // hint field for gui, can/should be set to zero + + // for generated sheets. + private short field_6_reserved; + private short field_7_option_flags; + private BitField outlineLevel = new BitField(0x07); + + // bit 3 reserved + private BitField colapsed = new BitField(0x10); + private BitField zeroHeight = new BitField(0x20); + private BitField badFontHeight = new BitField(0x40); + private BitField formatted = new BitField(0x80); + private short field_8_xf_index; // only if isFormatted + + public RowRecord() + { + } + + /** + * Constructs a Row record and sets its fields appropriately. + * + * @param short id must be 0x208 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public RowRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a Row record and sets its fields appropriately. + * + * @param short id must be 0x208 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record data + */ + + public RowRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A valid ROW RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_row_number = LittleEndian.getShort(data, 0 + offset); + field_2_first_col = LittleEndian.getShort(data, 2 + offset); + field_3_last_col = LittleEndian.getShort(data, 4 + offset); + field_4_height = LittleEndian.getShort(data, 6 + offset); + field_5_optimize = LittleEndian.getShort(data, 8 + offset); + field_6_reserved = LittleEndian.getShort(data, 10 + offset); + field_7_option_flags = LittleEndian.getShort(data, 12 + offset); + field_8_xf_index = LittleEndian.getShort(data, 14 + offset); + } + + /** + * set the logical row number for this row (0 based index) + * @param row - the row number + */ + + public void setRowNumber(short row) + { + field_1_row_number = row; + } + + /** + * set the logical col number for the first cell this row (0 based index) + * @param col - the col number + */ + + public void setFirstCol(short col) + { + field_2_first_col = col; + } + + /** + * set the logical col number for the last cell this row (0 based index) + * @param col - the col number + */ + + public void setLastCol(short col) + { + field_3_last_col = col; + } + + /** + * set the height of the row + * @param height of the row + */ + + public void setHeight(short height) + { + field_4_height = height; + } + + /** + * set whether to optimize or not (set to 0) + * @param optimize (set to 0) + */ + + public void setOptimize(short optimize) + { + field_5_optimize = optimize; + } + + /** + * sets the option bitmask. (use the individual bit setters that refer to this + * method) + * @param options - the bitmask + */ + + public void setOptionFlags(short options) + { + field_7_option_flags = options; + } + + // option bitfields + + /** + * set the outline level of this row + * @param ol - the outline level + * @see #setOptionFlags(short) + */ + + public void setOutlineLevel(short ol) + { + field_7_option_flags = + outlineLevel.setShortValue(field_7_option_flags, ol); + } + + /** + * set whether or not to colapse this row + * @param c - colapse or not + * @see #setOptionFlags(short) + */ + + public void setColapsed(boolean c) + { + field_7_option_flags = colapsed.setShortBoolean(field_7_option_flags, + c); + } + + /** + * set whether or not to display this row with 0 height + * @param - z height is zero or not. + * @see #setOptionFlags(short) + */ + + public void setZeroHeight(boolean z) + { + field_7_option_flags = + zeroHeight.setShortBoolean(field_7_option_flags, z); + } + + /** + * set whether the font and row height are not compatible + * @param - f -true if they aren't compatible (damn not logic) + * @see #setOptionFlags(short) + */ + + public void setBadFontHeight(boolean f) + { + field_7_option_flags = + badFontHeight.setShortBoolean(field_7_option_flags, f); + } + + /** + * set whether the row has been formatted (even if its got all blank cells) + * @param formatted or not + * @see #setOptionFlags(short) + */ + + public void setFormatted(boolean f) + { + field_7_option_flags = formatted.setShortBoolean(field_7_option_flags, + f); + } + + // end bitfields + + /** + * if the row is formatted then this is the index to the extended format record + * @see org.apache.poi.hssf.record.ExtendedFormatRecord + * @param index to the XF record + */ + + public void setXFIndex(short index) + { + field_8_xf_index = index; + } + + /** + * get the logical row number for this row (0 based index) + * @return row - the row number + */ + + public short getRowNumber() + { + return field_1_row_number; + } + + /** + * get the logical col number for the first cell this row (0 based index) + * @return col - the col number + */ + + public short getFirstCol() + { + return field_2_first_col; + } + + /** + * get the logical col number for the last cell this row (0 based index) + * @return col - the col number + */ + + public short getLastCol() + { + return field_3_last_col; + } + + /** + * get the height of the row + * @return height of the row + */ + + public short getHeight() + { + return field_4_height; + } + + /** + * get whether to optimize or not (set to 0) + * @return optimize (set to 0) + */ + + public short getOptimize() + { + return field_5_optimize; + } + + /** + * gets the option bitmask. (use the individual bit setters that refer to this + * method) + * @return options - the bitmask + */ + + public short getOptionFlags() + { + return field_7_option_flags; + } + + // option bitfields + + /** + * get the outline level of this row + * @return ol - the outline level + * @see #getOptionFlags() + */ + + public short getOutlineLevel() + { + return outlineLevel.getShortValue(field_7_option_flags); + } + + /** + * get whether or not to colapse this row + * @return c - colapse or not + * @see #getOptionFlags() + */ + + public boolean getColapsed() + { + return (colapsed.isSet(field_7_option_flags)); + } + + /** + * get whether or not to display this row with 0 height + * @return - z height is zero or not. + * @see #getOptionFlags() + */ + + public boolean getZeroHeight() + { + return zeroHeight.isSet(field_7_option_flags); + } + + /** + * get whether the font and row height are not compatible + * @return - f -true if they aren't compatible (damn not logic) + * @see #getOptionFlags() + */ + + public boolean getBadFontHeight() + { + return badFontHeight.isSet(field_7_option_flags); + } + + /** + * get whether the row has been formatted (even if its got all blank cells) + * @return formatted or not + * @see #getOptionFlags() + */ + + public boolean getFormatted() + { + return formatted.isSet(field_7_option_flags); + } + + // end bitfields + + /** + * if the row is formatted then this is the index to the extended format record + * @see org.apache.poi.hssf.record.ExtendedFormatRecord + * @return index to the XF record or bogus value (undefined) if isn't formatted + */ + + public short getXFIndex() + { + return field_8_xf_index; + } + + public boolean isInValueSection() + { + return true; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[ROW]\n"); + buffer.append(" .rownumber = ") + .append(Integer.toHexString(getRowNumber())).append("\n"); + buffer.append(" .firstcol = ") + .append(Integer.toHexString(getFirstCol())).append("\n"); + buffer.append(" .lastcol = ") + .append(Integer.toHexString(getLastCol())).append("\n"); + buffer.append(" .height = ") + .append(Integer.toHexString(getHeight())).append("\n"); + buffer.append(" .optimize = ") + .append(Integer.toHexString(getOptimize())).append("\n"); + buffer.append(" .reserved = ") + .append(Integer.toHexString(field_6_reserved)).append("\n"); + buffer.append(" .optionflags = ") + .append(Integer.toHexString(getOptionFlags())).append("\n"); + buffer.append(" .outlinelvl = ") + .append(Integer.toHexString(getOutlineLevel())).append("\n"); + buffer.append(" .colapsed = ").append(getColapsed()) + .append("\n"); + buffer.append(" .zeroheight = ").append(getZeroHeight()) + .append("\n"); + buffer.append(" .badfontheig= ").append(getBadFontHeight()) + .append("\n"); + buffer.append(" .formatted = ").append(getFormatted()) + .append("\n"); + buffer.append(" .xfindex = ") + .append(Integer.toHexString(getXFIndex())).append("\n"); + buffer.append("[/ROW]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + 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, 10 + offset, getHeight()); + LittleEndian.putShort(data, 12 + offset, getOptimize()); + LittleEndian.putShort(data, 14 + offset, field_6_reserved); + LittleEndian.putShort(data, 16 + offset, getOptionFlags()); + +// LittleEndian.putShort(data,18,getOutlineLevel()); + LittleEndian.putShort(data, 18 + offset, getXFIndex()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 20; + } + + public short getSid() + { + return this.sid; + } + + public int compareTo(Object obj) + { + RowRecord loc = ( RowRecord ) obj; + + if (this.getRowNumber() == loc.getRowNumber()) + { + return 0; + } + if (this.getRowNumber() < loc.getRowNumber()) + { + return -1; + } + if (this.getRowNumber() > loc.getRowNumber()) + { + return 1; + } + return -1; + } + + public boolean equals(Object obj) + { + if (!(obj instanceof RowRecord)) + { + return false; + } + RowRecord loc = ( RowRecord ) obj; + + if (this.getRowNumber() == loc.getRowNumber()) + { + return true; + } + return false; + } +} diff --git a/src/java/org/apache/poi/hssf/record/SSTRecord.java b/src/java/org/apache/poi/hssf/record/SSTRecord.java new file mode 100644 index 000000000..3f594175b --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/SSTRecord.java @@ -0,0 +1,1221 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.BinaryTree; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; + +import java.util.*; + +/** + * Title: Static String Table Record + *

+ * Description: This holds all the strings for LabelSSTRecords. + *

+ * REFERENCE: PG 389 Microsoft Excel 97 Developer's Kit (ISBN: + * 1-57231-498-2) + *

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Marc Johnson (mjohnson at apache dot org) + * @version 2.0-pre + * @see org.apache.poi.hssf.record.LabelSSTRecord + * @see org.apache.poi.hssf.record.ContinueRecord + */ + +public class SSTRecord + 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 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; + + // 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; + + // union of strings in the SST and EXTSST + private int field_1_num_strings; + + // according to docs ONLY SST + private int field_2_num_unique_strings; + private BinaryTree field_3_strings; + + // this is the number of characters we expect in the first + // sub-record in a subsequent continuation record + private int __expected_chars; + + // 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; + + // this is the total length of the current string being handled + private int _total_length_bytes; + + // 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; + + /** + * default constructor + */ + + public SSTRecord() + { + 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; + } + + /** + * Constructs an SST record and sets its fields appropriately. + * + * @param id must be 0xfc or an exception will be throw upon + * validation + * @param size the size of the data area of the record + * @param data of the record (should not contain sid/len) + */ + + public SSTRecord(final short id, final short size, final byte [] data) + { + super(id, size, data); + } + + /** + * Constructs an SST record and sets its fields appropriately. + * + * @param id must be 0xfc or an exception will be throw upon + * validation + * @param size the size of the data area of the record + * @param data of the record (should not contain sid/len) + * @param offset of the record + */ + + public SSTRecord(final short id, final short size, final byte [] data, + int offset) + { + super(id, size, data, offset); + } + + /** + * Add a string. Determines whether 8-bit encoding can be used, or + * whether 16-bit encoding must be used. + *

+ * THIS IS THE PREFERRED METHOD OF ADDING A STRING. IF YOU USE THE + * OTHER ,code>addString METHOD AND FORCE 8-BIT ENCODING ON + * A STRING THAT SHOULD USE 16-BIT ENCODING, YOU WILL CORRUPT THE + * STRING; IF YOU USE THAT METHOD AND FORCE 16-BIT ENCODING, YOU + * ARE WASTING SPACE WHEN THE WORKBOOK IS WRITTEN OUT. + * + * @param string string to be added + * + * @return the index of that string in the table + */ + + public int addString(final String string) + { + int rval; + + if (string == null) + { + rval = addString("", false); + } + else + { + + // scan for characters greater than 255 ... if any are + // present, we have to use 16-bit encoding. Otherwise, we + // can use 8-bit encoding + boolean useUTF16 = false; + int strlen = string.length(); + + for (int j = 0; j < strlen; j++) + { + if (string.charAt(j) > 255) + { + useUTF16 = true; + break; + } + } + rval = addString(string, useUTF16); + } + return rval; + } + + /** + * Add a string and assert the encoding (8-bit or 16-bit) to be + * used. + *

+ * USE THIS METHOD AT YOUR OWN RISK. IF YOU FORCE 8-BIT ENCODING, + * YOU MAY CORRUPT YOUR STRING. IF YOU FORCE 16-BIT ENCODING AND + * IT ISN'T NECESSARY, YOU WILL WASTE SPACE WHEN THIS RECORD IS + * WRITTEN OUT. + * + * @param string string to be added + * @param useUTF16 if true, forces 16-bit encoding. If false, + * forces 8-bit encoding + * + * @return the index of that string in the table + */ + + 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) + { + rval = integer.intValue(); + } + else + { + + // This is a new string -- we didn't see it among the + // 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); + } + return rval; + } + + /** + * @return number of strings + */ + + public int getNumStrings() + { + return field_1_num_strings; + } + + /** + * @return number of unique strings + */ + + public int getNumUniqueStrings() + { + return field_2_num_unique_strings; + } + + /** + * USE THIS METHOD AT YOUR OWN PERIL: THE addString + * METHODS MANIPULATE THE NUMBER OF STRINGS AS A SIDE EFFECT; YOUR + * ATTEMPTS AT MANIPULATING THE STRING COUNT IS LIKELY TO BE VERY + * WRONG AND WILL RESULT IN BAD BEHAVIOR WHEN THIS RECORD IS + * WRITTEN OUT AND ANOTHER PROCESS ATTEMPTS TO READ THE RECORD + * + * @param number of strings + * + * @param count + */ + + public void setNumStrings(final int count) + { + field_1_num_strings = count; + } + + /** + * USE THIS METHOD AT YOUR OWN PERIL: THE addString + * METHODS MANIPULATE THE NUMBER OF UNIQUE STRINGS AS A SIDE + * EFFECT; YOUR ATTEMPTS AT MANIPULATING THE UNIQUE STRING COUNT + * IS LIKELY TO BE VERY WRONG AND WILL RESULT IN BAD BEHAVIOR WHEN + * THIS RECORD IS WRITTEN OUT AND ANOTHER PROCESS ATTEMPTS TO READ + * THE RECORD + * + * @param number of strings + * + * @param count + */ + + public void getNumUniqueStrings(final int count) + { + field_2_num_unique_strings = count; + } + + /** + * Get a particular string by its index + * + * @param id index into the array of strings + * + * @return the desired string + */ + + public String getString(final int id) + { + return (( UnicodeString ) field_3_strings.get(new Integer(id))) + .getString(); + } + + public boolean getString16bit(final int id) + { + return ((( UnicodeString ) field_3_strings.get(new Integer(id))) + .getOptionFlags() == 1); + } + + /** + * Return a debugging string representation + * + * @return string representation + */ + + public String toString() + { + 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(" .string_" + k + " = ") + .append((( UnicodeString ) field_3_strings + .get(new Integer(k))).toString()).append("\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. + *

+ * 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); + + 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; + + 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; + } + + 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: + *

+ *

    + *
  1. The string counts at the beginning of the SST record are + * not in the Continue record + *
  2. 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 + *
+ * + * @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; + } + + /** + * @return hashcode + */ + + public int hashCode() + { + return field_2_num_unique_strings; + } + + /** + * + * @param o + * @return true if equal + */ + + public boolean equals(Object o) + { + if ((o == null) || (o.getClass() != this.getClass())) + { + return false; + } + 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)); + } + + /** + * validate SID + * + * @param id the alleged SID + * + * @exception RecordFormatException if validation fails + */ + + protected void validateSid(final short id) + throws RecordFormatException + { + if (id != sid) + { + throw new RecordFormatException("NOT An SST RECORD"); + } + } + + /** + * Fill the fields from the data + *

+ * The data consists of sets of string data. This string data is + * arranged as follows: + *

+ * + * short string_length; // length of string data + * byte string_flag; // flag specifying special string + * // handling + * short run_count; // optional count of formatting runs + * int extend_length; // optional extension length + * char[] string_data; // string data, can be byte[] or + * // short[] (length of array is + * // string_length) + * int[] formatting_runs; // optional formatting runs (length of + * // array is run_count) + * byte[] extension; // optional extension (length of array + * // is extend_length) + * + *

+ * The string_flag is bit mapped as follows: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Bit numberMeaning if 0Meaning if 1
0string_data is byte[]string_data is short[] + *
1Should always be 0string_flag is defective + *
2extension is not includedextension is included + *
3formatting run data is not includedformatting run data is included + *
4Should always be 0string_flag is defective + *
5Should always be 0string_flag is defective + *
6Should always be 0string_flag is defective + *
7Should always be 0string_flag is defective + *
+ *

+ * We can handle eating the overhead associated with bits 2 or 3 + * (or both) being set, but we have no idea what to do with the + * associated data. The UnicodeString class can handle the byte[] + * vs short[] nature of the actual string data + * + * @param data raw data + * @param size size of the raw data + */ + + 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); + } + + /** + * @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 + * UnicodeStrings + */ + + Iterator getStrings() + { + return field_3_strings.values().iterator(); + } + + /** + * @return count of the strings we hold. + */ + + int countStrings() + { + return field_3_strings.size(); + } + + /** + * @return the unfinished string + */ + + String getUnfinishedString() + { + return _unfinished_string; + } + + /** + * @return the total length of the current string + */ + + int getTotalLength() + { + return _total_length_bytes; + } + + /** + * @return offset into current string data + */ + + int getStringDataOffset() + { + return _string_data_offset; + } + + /** + * @return true if current string uses wide characters + */ + + 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) + { + return byte_count / (_wide_char ? LittleEndianConsts.SHORT_SIZE + : LittleEndianConsts.BYTE_SIZE); + } + + // 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/SaveRecalcRecord.java b/src/java/org/apache/poi/hssf/record/SaveRecalcRecord.java new file mode 100644 index 000000000..3597ad2a5 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/SaveRecalcRecord.java @@ -0,0 +1,167 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Save Recalc Record

+ * Description: defines whether to recalculate before saving (set to true)

+ * REFERENCE: PG 381 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class SaveRecalcRecord + extends Record +{ + public final static short sid = 0x5f; + private short field_1_recalc; + + public SaveRecalcRecord() + { + } + + /** + * Constructs an SaveRecalc record and sets its fields appropriately. + * + * @param short id must be 0x5f or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public SaveRecalcRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs an SaveRecalc record and sets its fields appropriately. + * + * @param short id must be 0x5f or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the the data + */ + + public SaveRecalcRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A Save Recalc RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_recalc = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set whether to recalculate formulas/etc before saving or not + * @param recalc - whether to recalculate or not + */ + + public void setRecalc(boolean recalc) + { + field_1_recalc = ( short ) ((recalc == true) ? 1 + : 0); + } + + /** + * get whether to recalculate formulas/etc before saving or not + * @return recalc - whether to recalculate or not + */ + + public boolean getRecalc() + { + return (field_1_recalc == 1); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[SAVERECALC]\n"); + buffer.append(" .recalc = ").append(getRecalc()) + .append("\n"); + buffer.append("[/SAVERECALC]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x2); + LittleEndian.putShort(data, 4 + offset, field_1_recalc); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/SelectionRecord.java b/src/java/org/apache/poi/hssf/record/SelectionRecord.java new file mode 100644 index 000000000..7d98f7f75 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/SelectionRecord.java @@ -0,0 +1,277 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import java.util.*; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Selection Record

+ * Description: shows the user's selection on the sheet + * for write set num refs to 0

+ * + * TODO : Implement reference subrecords + * REFERENCE: PG 291 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class SelectionRecord + extends Record +{ + public final static short sid = 0x1d; + private byte field_1_pane; + private short field_2_row_active_cell; + private short field_3_col_active_cell; + private short field_4_ref_active_cell; + private short field_5_num_refs; + private ArrayList field_6_refs; + + public SelectionRecord() + { + } + + /** + * Constructs a Selection record and sets its fields appropriately. + * + * @param short id must be 0x1d or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public SelectionRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a Selection record and sets its fields appropriately. + * + * @param short id must be 0x1d or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public SelectionRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A valid Selection RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_pane = data[ 0 + offset ]; + field_2_row_active_cell = LittleEndian.getShort(data, 1 + offset); + field_3_col_active_cell = LittleEndian.getShort(data, 3 + offset); + field_4_ref_active_cell = LittleEndian.getShort(data, 5 + offset); + field_5_num_refs = LittleEndian.getShort(data, 7 + offset); + } + + /** + * set which window pane this is for + * @param pane + */ + + public void setPane(byte pane) + { + field_1_pane = pane; + } + + /** + * set the active cell's row + * @param row number of active cell + */ + + public void setActiveCellRow(short row) + { + field_2_row_active_cell = row; + } + + /** + * set the active cell's col + * @param col number of active cell + */ + + public void setActiveCellCol(short col) + { + field_3_col_active_cell = col; + } + + /** + * set the active cell's reference number + * @param ref number of active cell + */ + + public void setActiveCellRef(short ref) + { + field_4_ref_active_cell = ref; + } + + /** + * set the number of cell refs (we don't support selection so set to 0 + * @param refs - number of references + */ + + public void setNumRefs(short refs) + { + field_5_num_refs = refs; + } + + /** + * get which window pane this is for + * @return pane + */ + + public byte getPane() + { + return field_1_pane; + } + + /** + * get the active cell's row + * @return row number of active cell + */ + + public short getActiveCellRow() + { + return field_2_row_active_cell; + } + + /** + * get the active cell's col + * @return col number of active cell + */ + + public short getActiveCellCol() + { + return field_3_col_active_cell; + } + + /** + * get the active cell's reference number + * @return ref number of active cell + */ + + public short getActiveCellRef() + { + return field_4_ref_active_cell; + } + + /** + * get the number of cell refs (we don't support selection so set to 0 + * @return refs - number of references + */ + + public short getNumRefs() + { + return field_5_num_refs; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[SELECTION]\n"); + buffer.append(" .pane = ") + .append(Integer.toHexString(getPane())).append("\n"); + buffer.append(" .activecellrow = ") + .append(Integer.toHexString(getActiveCellRow())).append("\n"); + buffer.append(" .activecellcol = ") + .append(Integer.toHexString(getActiveCellCol())).append("\n"); + buffer.append(" .activecellref = ") + .append(Integer.toHexString(getActiveCellRef())).append("\n"); + buffer.append(" .numrefs = ") + .append(Integer.toHexString(getNumRefs())).append("\n"); + buffer.append("[/SELECTION]\n"); + return buffer.toString(); + } + +//hacked to provide one cell reference to 0,0 - 0,0 + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 15); + data[ 4 + offset ] = getPane(); + LittleEndian.putShort(data, 5 + offset, getActiveCellRow()); + LittleEndian.putShort(data, 7 + offset, getActiveCellCol()); + LittleEndian.putShort(data, 9 + offset, getActiveCellRef()); + LittleEndian.putShort(data, 11 + offset, ( short ) 1); + LittleEndian.putShort(data, 13 + offset, ( short ) 0); + LittleEndian.putShort(data, 15 + offset, ( short ) 0); + data[ 17 + offset ] = 0; + data[ 18 + offset ] = 0; + return getRecordSize(); + } + + public int getRecordSize() + { + return 19; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/SeriesRecord.java b/src/java/org/apache/poi/hssf/record/SeriesRecord.java new file mode 100644 index 000000000..3861b2861 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/SeriesRecord.java @@ -0,0 +1,242 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * The series record defines the (graphing) series within a chart. + * This record is matched with a corresponding EndRecord. + * + * @author Glen Stampoultzis (gstamp at iprimus dot com dot au) + */ + +public class SeriesRecord + extends Record +{ + public static final short sid = 0x1003; + public static final short AXIS_TYPE_DATE = 0; + public static final short AXIS_TYPE_NUMERIC = 1; + public static final short AXIS_TYPE_SEQUENCE = 3; + public static final short AXIS_TYPE_TEXT = 4; + private short field_1_xAxisType; + private short field_2_yAxisType; + private short field_3_countOfXValues; + private short field_4_countOfYValues; + private short field_5_bubbleType; // type of data in "bubble size series" + private short field_6_countOfBubbleSeries; // count of bubble series values + + public SeriesRecord() + { + } + + /** + * Constructs a SeriesRecord record and sets its fields appropriately. + * + * @param short id must be 0x1003 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public SeriesRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a SeriesRecord record and sets its fields appropriately. + * + * @param short id must be 0x1003 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public SeriesRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A SERIES RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_xAxisType = LittleEndian.getShort(data, 0 + offset); + field_2_yAxisType = LittleEndian.getShort(data, 2 + offset); + field_3_countOfXValues = LittleEndian.getShort(data, 4 + offset); + field_4_countOfYValues = LittleEndian.getShort(data, 6 + offset); + field_5_bubbleType = LittleEndian.getShort(data, 8 + offset); + field_6_countOfBubbleSeries = LittleEndian.getShort(data, + 10 + offset); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[SERIES]\n"); + buffer.append(" .xAxisType = ") + .append(Integer.toHexString(getXAxisType())).append("\n"); + buffer.append(" .yAxisType = ") + .append(Integer.toHexString(getYAxisType())).append("\n"); + buffer.append(" .countOfXValues = ").append(getCountOfXValues()) + .append("\n"); + buffer.append(" .countOfYValues = ").append(getCountOfYValues()) + .append("\n"); + buffer.append("[/SERIES]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 12)); // 12 byte length + LittleEndian.putShort(data, 4 + offset, getXAxisType()); + LittleEndian.putShort(data, 6 + offset, getYAxisType()); + LittleEndian.putShort(data, 8 + offset, getCountOfXValues()); + LittleEndian.putShort(data, 10 + offset, getCountOfYValues()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 12; + } + + public short getSid() + { + return this.sid; + } + + /** + * @return one of AXIS_TYPE_XXX + */ + + public short getXAxisType() + { + return field_1_xAxisType; + } + + /** + * @param xAxisType one of AXIS_TYPE_XXX + */ + + public void setXAxisType(short xAxisType) + { + this.field_1_xAxisType = xAxisType; + } + + /** + * @return one of AXIS_TYPE_XXX + */ + + public short getYAxisType() + { + return field_2_yAxisType; + } + + /** + * @param xAxisType one of AXIS_TYPE_XXX + */ + + public void setYAxisType(short yAxisType) + { + this.field_2_yAxisType = yAxisType; + } + + /** + * @return number of x values in the series. + */ + + public short getCountOfXValues() + { + return field_3_countOfXValues; + } + + /** + * Sets the number of x values in the series. + */ + + public void setCountOfXValues(short countOfXValues) + { + this.field_3_countOfXValues = countOfXValues; + } + + /** + * @return number of y values in the series. + */ + + public short getCountOfYValues() + { + return field_4_countOfYValues; + } + + /** + * @param countOfYValues sets the number of y values for the series. + */ + + public void setCountOfYValues(short countOfYValues) + { + this.field_4_countOfYValues = countOfYValues; + } +} diff --git a/src/java/org/apache/poi/hssf/record/StyleRecord.java b/src/java/org/apache/poi/hssf/record/StyleRecord.java new file mode 100644 index 000000000..e4721d2ec --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/StyleRecord.java @@ -0,0 +1,399 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.StringUtil; + +/** + * Title: Style Record

+ * Description: Describes a builtin to the gui or user defined style

+ * REFERENCE: PG 390 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class StyleRecord + extends Record +{ + public final static short sid = 0x293; + public final static short STYLE_USER_DEFINED = 0; + public final static short STYLE_BUILT_IN = 1; + + // shared by both user defined and builtin styles + private short field_1_xf_index; // TODO: bitfield candidate + + // only for built in styles + private byte field_2_builtin_style; + private byte field_3_outline_style_level; + + // only for user defined styles + private byte field_2_name_length; + private String field_3_name; + + public StyleRecord() + { + } + + /** + * Constructs a Style record and sets its fields appropriately. + * + * @param short id must be 0x293 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public StyleRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a Style record and sets its fields appropriately. + * + * @param short id must be 0x293 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset + */ + + public StyleRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A STYLE RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_xf_index = LittleEndian.getShort(data, 0 + offset); + if (getType() == 1) + { + field_2_builtin_style = data[ 2 + offset ]; + field_3_outline_style_level = data[ 3 + offset ]; + } + else if (getType() == 0) + { + field_2_name_length = data[ 2 + offset ]; + field_3_name = new String(data, 3 + offset, + field_2_name_length); + } + + // todo sanity check exception to make sure we're one or the other + } + + /** + * set the entire index field (including the type) (see bit setters that reference this method) + * @param bitmask + */ + + public void setIndex(short index) + { + field_1_xf_index = index; + } + + // bitfields for field 1 + + /** + * set the type of the style (builtin or user-defined) + * @see #STYLE_USER_DEFINED + * @see #STYLE_BUILT_IN + * @param type of style (userdefined/builtin) + * @see #setIndex(short) + */ + + public void setType(short type) + { + field_1_xf_index = setField(field_1_xf_index, type, 0x8000, 15); + } + + /** + * set the actual index of the style extended format record + * @see #setIndex(short) + * @param index of the xf record + */ + + public void setXFIndex(short index) + { + field_1_xf_index = setField(field_1_xf_index, index, 0x1FFF, 0); + } + + // end bitfields + // only for user defined records + + /** + * if this is a user defined record set the length of the style name + * @param length of the style's name + * @see #setName(String) + */ + + public void setNameLength(byte length) + { + field_2_name_length = length; + } + + /** + * set the style's name + * @param name of the style + * @see #setNameLength(byte) + */ + + public void setName(String name) + { + field_3_name = name; + } + + // end user defined + // only for buildin records + + /** + * if this is a builtin style set teh number of the built in style + * @param builtin style number (0-7) + * + */ + + public void setBuiltin(byte builtin) + { + field_2_builtin_style = builtin; + } + + /** + * set the row or column level of the style (if builtin 1||2) + */ + + public void setOutlineStyleLevel(byte level) + { + field_3_outline_style_level = level; + } + + // end builtin records + // field 1 + + /** + * get the entire index field (including the type) (see bit getters that reference this method) + * @return bitmask + */ + + public short getIndex() + { + return field_1_xf_index; + } + + // bitfields for field 1 + + /** + * get the type of the style (builtin or user-defined) + * @see #STYLE_USER_DEFINED + * @see #STYLE_BUILT_IN + * @return type of style (userdefined/builtin) + * @see #getIndex() + */ + + public short getType() + { + return ( short ) ((field_1_xf_index & 0x8000) >> 15); + } + + /** + * get the actual index of the style extended format record + * @see #getIndex() + * @return index of the xf record + */ + + public short getXFIndex() + { + return ( short ) (field_1_xf_index & 0x1FFF); + } + + // end bitfields + // only for user defined records + + /** + * if this is a user defined record get the length of the style name + * @return length of the style's name + * @see #getName() + */ + + public byte getNameLength() + { + return field_2_name_length; + } + + /** + * get the style's name + * @return name of the style + * @see #getNameLength() + */ + + public String getName() + { + return field_3_name; + } + + // end user defined + // only for buildin records + + /** + * if this is a builtin style get the number of the built in style + * @return builtin style number (0-7) + * + */ + + public byte getBuiltin() + { + return field_2_builtin_style; + } + + /** + * get the row or column level of the style (if builtin 1||2) + */ + + public byte getOutlineStyleLevel() + { + return field_3_outline_style_level; + } + + // end builtin records + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[STYLE]\n"); + buffer.append(" .xf_index_raw = ") + .append(Integer.toHexString(getIndex())).append("\n"); + buffer.append(" .type = ") + .append(Integer.toHexString(getType())).append("\n"); + buffer.append(" .xf_index = ") + .append(Integer.toHexString(getXFIndex())).append("\n"); + if (getType() == STYLE_BUILT_IN) + { + buffer.append(" .builtin_style = ") + .append(Integer.toHexString(getBuiltin())).append("\n"); + buffer.append(" .outline_level = ") + .append(Integer.toHexString(getOutlineStyleLevel())) + .append("\n"); + } + else if (getType() == STYLE_USER_DEFINED) + { + buffer.append(" .name_length = ") + .append(Integer.toHexString(getNameLength())).append("\n"); + buffer.append(" .name = ").append(getName()) + .append("\n"); + } + buffer.append("[/STYLE]\n"); + return buffer.toString(); + } + + private short setField(int fieldValue, int new_value, int mask, + int shiftLeft) + { + return ( short ) ((fieldValue & ~mask) + | ((new_value << shiftLeft) & mask)); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + if (getType() == STYLE_BUILT_IN) + { + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x04)); // 4 bytes (8 total) + } + else + { + LittleEndian.putShort(data, 2 + offset, + (( short ) (0x03 + getNameLength()))); + } + LittleEndian.putShort(data, 4 + offset, getIndex()); + if (getType() == STYLE_BUILT_IN) + { + data[ 6 + offset ] = getBuiltin(); + data[ 7 + offset ] = getOutlineStyleLevel(); + } + else + { + data[ 6 + offset ] = getNameLength(); + StringUtil.putCompressedUnicode(getName(), data, 7 + offset); + } + return getRecordSize(); + } + + public int getRecordSize() + { + int retval; + + if (getType() == STYLE_BUILT_IN) + { + retval = 8; + } + else + { + retval = 7 + getNameLength(); + } + return retval; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/TabIdRecord.java b/src/java/org/apache/poi/hssf/record/TabIdRecord.java new file mode 100644 index 000000000..ea6f5ebc3 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/TabIdRecord.java @@ -0,0 +1,188 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Sheet Tab Index Array Record

+ * Description: Contains an array of sheet id's. Sheets always keep their ID + * regardless of what their name is.

+ * REFERENCE: PG 412 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class TabIdRecord + extends Record +{ + public final static short sid = 0x13d; + public short[] field_1_tabids; + + public TabIdRecord() + { + } + + /** + * Constructs a TabID record and sets its fields appropriately. + * + * @param short id must be 0x13d or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public TabIdRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a TabID record and sets its fields appropriately. + * + * @param short id must be 0x13d or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record + */ + + public TabIdRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A TABID RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_tabids = new short[ size / 2 ]; + for (int k = 0; k < field_1_tabids.length; k++) + { + field_1_tabids[ k ] = LittleEndian.getShort(data, + (k * 2) + offset); + } + } + + /** + * set the tab array. (0,1,2). + * @param array of tab id's {0,1,2} + */ + + public void setTabIdArray(short [] array) + { + field_1_tabids = array; + } + + /** + * get the tab array. (0,1,2). + * @return array of tab id's {0,1,2} + */ + + public short [] getTabIdArray() + { + return field_1_tabids; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[TABID]\n"); + buffer.append(" .elements = ").append(field_1_tabids.length) + .append("\n"); + for (int k = 0; k < field_1_tabids.length; k++) + { + buffer.append(" .element_" + k + " = ") + .append(field_1_tabids[ k ]).append("\n"); + } + buffer.append("[/TABID]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + short[] tabids = getTabIdArray(); + short length = ( short ) (tabids.length * 2); + int byteoffset = 4; + + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) length)); // nubmer tabids * + + // 2 (num bytes in a short) + for (int k = 0; k < (length / 2); k++) + { + LittleEndian.putShort(data, byteoffset + offset, tabids[ k ]); + byteoffset += 2; + } + return getRecordSize(); + } + + public int getRecordSize() + { + return 4 + (getTabIdArray().length * 2); + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/UnicodeString.java b/src/java/org/apache/poi/hssf/record/UnicodeString.java new file mode 100644 index 000000000..7338752ee --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/UnicodeString.java @@ -0,0 +1,366 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.StringUtil; + +/** + * Title: Unicode String

+ * Description: Unicode String record. We implement these as a record, although + * they are really just standard fields that are in several records. + * It is considered more desirable then repeating it in all of them.

+ * REFERENCE: PG 264 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver + * @author Marc Johnson (mjohnson at apache dot org) + * @version 2.0-pre + */ + +public class UnicodeString + extends Record + implements Comparable +{ + public final static short sid = 0xFFF; + private short field_1_charCount; // = 0; + private byte field_2_optionflags; // = 0; + private String field_3_string; // = null; + + public int hashCode() + { + return field_1_charCount; + } + + public boolean equals(Object o) + { + if ((o == null) || (o.getClass() != this.getClass())) + { + return false; + } + UnicodeString other = ( UnicodeString ) o; + + return ((field_1_charCount == other.field_1_charCount) + && (field_2_optionflags == other.field_2_optionflags) + && 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 + * @param size - size of the data + * @param data - the bytes of the string/fields + */ + + public UnicodeString(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * construct a unicode string from a string fragment + data + */ + + public UnicodeString(short id, short size, byte [] data, String prefix) + { + this(id, size, data); + field_3_string = prefix + field_3_string; + setCharCount(); + } + + /** + * NO OP + */ + + protected void validateSid(short id) + { + + // included only for interface compliance + } + + protected void fillFields(byte [] data, short size) + { + field_1_charCount = LittleEndian.getShort(data, 0); + field_2_optionflags = data[ 2 ]; + if ((field_2_optionflags & 1) == 0) + { + field_3_string = new String(data, 3, getCharCount()); + } + else + { + char[] array = new char[ getCharCount() ]; + + for (int j = 0; j < array.length; j++) + { + array[ j ] = ( char ) LittleEndian.getShort(data, + 3 + (j * 2)); + } + field_3_string = new String(array); + } + } + + /** + * get the number of characters in the string + * + * + * @return number of characters + * + */ + + public short getCharCount() + { + return field_1_charCount; + } + + /** + * set the number of characters in the string + * @param cc - number of characters + */ + + public void setCharCount(short cc) + { + field_1_charCount = cc; + } + + /** + * sets the number of characters to whaterver number of characters is in the string + * currently. effectively setCharCount(getString.length()). + * @see #setString(String) + * @see #getString() + */ + + public void setCharCount() + { + field_1_charCount = ( short ) field_3_string.length(); + } + + /** + * get the option flags which among other things return if this is a 16-bit or + * 8 bit string + * + * @return optionflags bitmask + * + */ + + public byte getOptionFlags() + { + return field_2_optionflags; + } + + /** + * set the option flags which among other things return if this is a 16-bit or + * 8 bit string + * + * @param optionflags bitmask + * + */ + + public void setOptionFlags(byte of) + { + field_2_optionflags = of; + } + + /** + * get the actual string this contains as a java String object + * + * + * @return String + * + */ + + public String getString() + { + return field_3_string; + } + + /** + * set the actual string this contains + * @param String - the text + */ + + public void setString(String string) + { + field_3_string = string; + if (getCharCount() < field_3_string.length()) + { + setCharCount(); + } + } + + /** + * unlike the real records we return the same as "getString()" rather than debug info + * @see #getDebugInfo() + * @return String value of the record + */ + + public String toString() + { + return getString(); + } + + /** + * return a character representation of the fields of this record + * + * + * @return String of output for biffviewer etc. + * + */ + + public String getDebugInfo() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[UNICODESTRING]\n"); + buffer.append(" .charcount = ") + .append(Integer.toHexString(getCharCount())).append("\n"); + buffer.append(" .optionflags = ") + .append(Integer.toHexString(getOptionFlags())).append("\n"); + buffer.append(" .string = ").append(getString()) + .append("\n"); + buffer.append("[/UNICODESTRING]\n"); + return buffer.toString(); + } + + 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) + { + StringUtil.putCompressedUnicode(getString(), data, 0x3 + offset); + } + else + { + StringUtil.putUncompressedUnicode(getString(), data, + 0x3 + offset); + } + return getRecordSize(); + } + + public int getRecordSize() + { + int charsize = 1; + + if (getOptionFlags() == 1) + { + charsize = 2; + } + return 3 + (getString().length() * charsize); + } + + public short getSid() + { + return this.sid; + } + + /** + * called by the constructor, should set class level fields. Should throw + * runtime exception for bad/icomplete data. + * + * @param data raw data + * @param size size of data + * @param offset of the records data (provided a big array of the file) + */ + + protected void fillFields(byte [] data, short size, int offset) + { + } + + public int compareTo(Object obj) + { + UnicodeString str = ( UnicodeString ) obj; + + return this.getString().compareTo(str.getString()); + } + + int maxBrokenLength(final int proposedBrokenLength) + { + int rval = proposedBrokenLength; + + if ((field_2_optionflags & 1) == 1) + { + int proposedStringLength = proposedBrokenLength - 3; + + if ((proposedStringLength % 2) == 1) + { + proposedStringLength--; + } + rval = proposedStringLength + 3; + } + return rval; + } + +// public boolean equals(Object obj) { +// if (!(obj instanceof UnicodeString)) return false; +// +// UnicodeString str = (UnicodeString)obj; +// +// +// return this.getString().equals(str.getString()); +// } +} diff --git a/src/java/org/apache/poi/hssf/record/UnknownRecord.java b/src/java/org/apache/poi/hssf/record/UnknownRecord.java new file mode 100644 index 000000000..10aab8910 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/UnknownRecord.java @@ -0,0 +1,177 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Unknown Record (for debugging)

+ * Description: Unknown record just tells you the sid so you can figure out + * what records you are missing. Also helps us read/modify sheets we + * don't know all the records to. (HSSF leaves these alone!)

+ * Company: SuperLink Software, Inc.

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class UnknownRecord + extends Record +{ + private short sid = 0; + private short size = 0; + private byte[] thedata = null; + int offset = 0; + + public UnknownRecord() + { + } + + /** + * construct an unknown record. No fields are interperated and the record will + * be serialized in its original form more or less + * @param id of the record -not validated, just stored for serialization + * @param size of the data + * @param the data + */ + + public UnknownRecord(short id, short size, byte [] data) + { + sid = id; + size = size; + thedata = data; + } + + /** + * spit the record out AS IS. no interperatation or identification + */ + + public int serialize(int offset, byte [] data) + { + if (thedata == null) + { + thedata = new byte[ 0 ]; + } + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) (thedata.length)); + if (thedata.length > 0) + { + System.arraycopy(thedata, 0, data, 4 + offset, thedata.length); + } + return getRecordSize(); + } + + public int getRecordSize() + { + int retval = 4; + + if (thedata != null) + { + retval += thedata.length; + } + return retval; + } + + protected void fillFields(byte [] data, short sid) + { + sid = sid; + thedata = data; + } + + /** + * NO OP! + */ + + protected void validateSid(short id) + { + + // if we had a valid sid we wouldn't be using the "Unknown Record" record now would we? + } + + /** + * print a sort of string representation ([UNKNOWN RECORD] id = x [/UNKNOWN RECORD]) + */ + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[UNKNOWN RECORD]\n"); + buffer.append(" .id = ").append(Integer.toHexString(sid)) + .append("\n"); + buffer.append("[/UNKNWON RECORD]\n"); + return buffer.toString(); + } + + public short getSid() + { + return this.sid; + } + + /** + * called by the constructor, should set class level fields. Should throw + * runtime exception for bad/icomplete data. + * + * @param data raw data + * @param size size of data + * @param offset of the records data (provided a big array of the file) + */ + + protected void fillFields(byte [] data, short size, int offset) + { + throw new RecordFormatException( + "Unknown record cannot be constructed via offset -- we need a copy of the data"); + } +} diff --git a/src/java/org/apache/poi/hssf/record/UseSelFSRecord.java b/src/java/org/apache/poi/hssf/record/UseSelFSRecord.java new file mode 100644 index 000000000..83a95ef83 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/UseSelFSRecord.java @@ -0,0 +1,176 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Use Natural Language Formulas Flag

+ * Description: Tells the GUI if this was written by something that can use + * "natural language" formulas. HSSF can't.

+ * REFERENCE: PG 420 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class UseSelFSRecord + extends Record +{ + public final static short sid = 0x160; + public final static short TRUE = 1; + public final static short FALSE = 0; + private short field_1_flag; + + public UseSelFSRecord() + { + } + + /** + * Constructs a UseSelFS record and sets its fields appropriately. + * + * @param short id must be 0x160 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public UseSelFSRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a UseSelFS record and sets its fields appropriately. + * + * @param short id must be 0x160 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of record + */ + + public UseSelFSRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A UseSelFS RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_flag = LittleEndian.getShort(data, 0 + offset); + } + + /** + * turn the flag on or off + * + * @param whether to use natural language formulas or not + * @see #TRUE + * @see #FALSE + */ + + public void setFlag(short flag) + { + field_1_flag = flag; + } + + /** + * returns whether we use natural language formulas or not + * + * @return whether to use natural language formulas or not + * @see #TRUE + * @see #FALSE + */ + + public short getFlag() + { + return field_1_flag; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[USESELFS]\n"); + buffer.append(" .flag = ") + .append(Integer.toHexString(getFlag())).append("\n"); + buffer.append("[/USESELFS]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, getFlag()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/VCenterRecord.java b/src/java/org/apache/poi/hssf/record/VCenterRecord.java new file mode 100644 index 000000000..9c78250dc --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/VCenterRecord.java @@ -0,0 +1,173 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: VCenter record

+ * Description: tells whether to center the sheet between vertical margins

+ * REFERENCE: PG 420 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class VCenterRecord + extends Record +{ + public final static short sid = 0x84; + private short field_1_vcenter; + + public VCenterRecord() + { + } + + /** + * Constructs a VCENTER record and sets its fields appropriately. + * + * @param short id must be 0x84 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public VCenterRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a VCENTER record and sets its fields appropriately. + * + * @param short id must be 0x84 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public VCenterRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A VCenter RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_vcenter = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set whether to center vertically or not + * @param vcenter or not + */ + + public void setVCenter(boolean hc) + { + if (hc == true) + { + field_1_vcenter = 1; + } + else + { + field_1_vcenter = 0; + } + } + + /** + * get whether to center vertically or not + * @return vcenter or not + */ + + public boolean getVCenter() + { + return (field_1_vcenter == 1); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[VCENTER]\n"); + buffer.append(" .vcenter = ").append(getVCenter()) + .append("\n"); + buffer.append("[/VCENTER]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x2); + LittleEndian.putShort(data, 4 + offset, ( short ) field_1_vcenter); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/WSBoolRecord.java b/src/java/org/apache/poi/hssf/record/WSBoolRecord.java new file mode 100644 index 000000000..e04566553 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/WSBoolRecord.java @@ -0,0 +1,418 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.BitField; +import org.apache.poi.util.LittleEndian; + +/** + * Title: WSBool Record.

+ * Description: stores workbook settings (aka its a big "everything we didn't + * put somewhere else")

+ * REFERENCE: PG 425 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Glen Stampoultzis (gstamp@iprimus.com.au) + * @version 2.0-pre + */ + +public class WSBoolRecord + extends Record +{ + public final static short sid = 0x81; + private byte field_1_wsbool; // crappy names are because this is really one big short field (2byte) + private byte field_2_wsbool; // but the docs inconsistantly use it as 2 seperate bytes + + // I decided to be consistant in this way. + static final private BitField autobreaks = + new BitField(0x01); // are automatic page breaks visible + + // bits 1 to 3 unused + static final private BitField dialog = + new BitField(0x10); // is sheet dialog sheet + static final private BitField applystyles = + new BitField(0x20); // whether to apply automatic styles to outlines + static final private BitField rowsumsbelow = new BitField( + 0x40); // whether summary rows will appear below detail in outlines + static final private BitField rowsumsright = new BitField( + 0x80); // whether summary rows will appear right of the detail in outlines + static final private BitField fittopage = + new BitField(0x01); // whether to fit stuff to the page + + // bit 2 reserved + static final private BitField displayguts = new BitField( + 0x06); // whether to display outline symbols (in the gutters) + + // bits 4-5 reserved + static final private BitField alternateexpression = // whether to use alternate expression eval + new BitField(0x40); + static final private BitField alternateformula = // whether to use alternate formula entry + new BitField(0x80); + + public WSBoolRecord() + { + } + + /** + * Constructs a WSBool record and sets its fields appropriately. + * + * @param short id must be 0x81 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public WSBoolRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a WSBool record and sets its fields appropriately. + * + * @param short id must be 0x81 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public WSBoolRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A WSBoolRECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_wsbool = + data[ 1 + offset ]; // backwards because theoretically this is one short field + field_2_wsbool = + data[ 0 + offset ]; // but it was easier to implement it this way to avoid confusion + } // because the dev kit shows the masks for it as 2 byte fields + + // why? Why ask why? But don't drink bud dry as its a really + // crappy beer, try the czech "Budvar" beer (which is the real + // budweiser though its ironically good...its sold in the USs + // as czechvar --- odd that they had the name first but can't + // use it)... + + /** + * set first byte (see bit setters) + */ + + public void setWSBool1(byte bool1) + { + field_1_wsbool = bool1; + } + + // bool1 bitfields + + /** + * show automatic page breaks or not + * @param whether to show auto page breaks + */ + + public void setAutobreaks(boolean ab) + { + field_1_wsbool = autobreaks.setByteBoolean(field_1_wsbool, ab); + } + + /** + * set whether sheet is a dialog sheet or not + * @param isDialog or not + */ + + public void setDialog(boolean isDialog) + { + field_1_wsbool = dialog.setByteBoolean(field_1_wsbool, isDialog); + } + + /** + * set if row summaries appear below detail in the outline + * @param below or not + */ + + public void setRowSumsBelow(boolean below) + { + field_1_wsbool = rowsumsbelow.setByteBoolean(field_1_wsbool, below); + } + + /** + * set if col summaries appear right of the detail in the outline + * @param right or not + */ + + public void setRowSumsRight(boolean right) + { + field_1_wsbool = rowsumsright.setByteBoolean(field_1_wsbool, right); + } + + // end bitfields + + /** + * set the second byte (see bit setters) + */ + + public void setWSBool2(byte bool2) + { + field_2_wsbool = field_2_wsbool = bool2; + } + + // bool2 bitfields + + /** + * fit to page option is on + * @param fit or not + */ + + public void setFitToPage(boolean fit2page) + { + field_2_wsbool = fittopage.setByteBoolean(field_2_wsbool, fit2page); + } + + /** + * set whether to display the guts or not + * + * @param guts or no guts (or glory) + */ + + public void setDisplayGuts(boolean guts) + { + field_2_wsbool = displayguts.setByteBoolean(field_2_wsbool, guts); + } + + /** + * whether alternate expression evaluation is on + * @param alternative expression evaluation or not + */ + + public void setAlternateExpression(boolean altexp) + { + field_2_wsbool = alternateexpression.setByteBoolean(field_2_wsbool, + altexp); + } + + /** + * whether alternative formula entry is on + * @param alternative formulas or not + */ + + public void setAlternateFormula(boolean formula) + { + field_2_wsbool = alternateformula.setByteBoolean(field_2_wsbool, + formula); + } + + // end bitfields + + /** + * get first byte (see bit getters) + */ + + public byte getWSBool1() + { + return field_1_wsbool; + } + + // bool1 bitfields + + /** + * show automatic page breaks or not + * @return whether to show auto page breaks + */ + + public boolean getAutobreaks() + { + return autobreaks.isSet(field_1_wsbool); + } + + /** + * get whether sheet is a dialog sheet or not + * @return isDialog or not + */ + + public boolean getDialog() + { + return dialog.isSet(field_1_wsbool); + } + + /** + * get if row summaries appear below detail in the outline + * @return below or not + */ + + public boolean getRowSumsBelow() + { + return rowsumsbelow.isSet(field_1_wsbool); + } + + /** + * get if col summaries appear right of the detail in the outline + * @return right or not + */ + + public boolean getRowSumsRight() + { + return rowsumsright.isSet(field_1_wsbool); + } + + // end bitfields + + /** + * get the second byte (see bit getters) + */ + + public byte getWSBool2() + { + return field_2_wsbool; + } + + // bool2 bitfields + + /** + * fit to page option is on + * @return fit or not + */ + + public boolean getFitToPage() + { + return fittopage.isSet(field_2_wsbool); + } + + /** + * get whether to display the guts or not + * + * @return guts or no guts (or glory) + */ + + public boolean getDisplayGuts() + { + return displayguts.isSet(field_2_wsbool); + } + + /** + * whether alternate expression evaluation is on + * @return alternative expression evaluation or not + */ + + public boolean getAlternateExpression() + { + return alternateexpression.isSet(field_2_wsbool); + } + + /** + * whether alternative formula entry is on + * @return alternative formulas or not + */ + + public boolean getAlternateFormula() + { + return alternateformula.isSet(field_2_wsbool); + } + + // end bitfields + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[WSBOOL]\n"); + buffer.append(" .wsbool1 = ") + .append(Integer.toHexString(getWSBool1())).append("\n"); + buffer.append(" .autobreaks = ").append(getAutobreaks()) + .append("\n"); + buffer.append(" .dialog = ").append(getDialog()) + .append("\n"); + buffer.append(" .rowsumsbelw= ").append(getRowSumsBelow()) + .append("\n"); + buffer.append(" .rowsumsrigt= ").append(getRowSumsRight()) + .append("\n"); + buffer.append(" .wsbool2 = ") + .append(Integer.toHexString(getWSBool2())).append("\n"); + buffer.append(" .fittopage = ").append(getFitToPage()) + .append("\n"); + buffer.append(" .displayguts= ").append(getDisplayGuts()) + .append("\n"); + buffer.append(" .alternateex= ") + .append(getAlternateExpression()).append("\n"); + buffer.append(" .alternatefo= ").append(getAlternateFormula()) + .append("\n"); + buffer.append("[/WSBOOL]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 0x2); + data[ 5 + offset ] = getWSBool1(); + data[ 4 + offset ] = getWSBool2(); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/WindowOneRecord.java b/src/java/org/apache/poi/hssf/record/WindowOneRecord.java new file mode 100644 index 000000000..694189a09 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/WindowOneRecord.java @@ -0,0 +1,504 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.BitField; +import org.apache.poi.util.LittleEndian; + +/** + * Title: Window1 Record

+ * Description: Stores the attributes of the workbook window. This is basically + * so the gui knows how big to make the window holding the spreadsheet + * document.

+ * REFERENCE: PG 421 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class WindowOneRecord + extends Record +{ + public final static short sid = 0x3d; + + // our variable names stolen from old TV sets. + private short field_1_h_hold; // horizontal position + private short field_2_v_hold; // vertical position + private short field_3_width; + private short field_4_height; + private short field_5_options; + static final private BitField hidden = + new BitField(0x01); // is this window is hidden + static final private BitField iconic = + new BitField(0x02); // is this window is an icon + static final private BitField reserved = new BitField(0x04); // reserved + static final private BitField hscroll = + new BitField(0x08); // display horizontal scrollbar + static final private BitField vscroll = + new BitField(0x10); // display vertical scrollbar + static final private BitField tabs = + new BitField(0x20); // display tabs at the bottom + + // all the rest are "reserved" + private short field_6_selected_tab; + private short field_7_displayed_tab; + private short field_8_num_selected_tabs; + private short field_9_tab_width_ratio; + + public WindowOneRecord() + { + } + + /** + * Constructs a WindowOne record and sets its fields appropriately. + * + * @param short id must be 0x3d or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public WindowOneRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a WindowOne record and sets its fields appropriately. + * + * @param short id must be 0x3d or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public WindowOneRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A WINDOW1 RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_h_hold = LittleEndian.getShort(data, 0 + offset); + field_2_v_hold = LittleEndian.getShort(data, 2 + offset); + field_3_width = LittleEndian.getShort(data, 4 + offset); + field_4_height = LittleEndian.getShort(data, 6 + offset); + field_5_options = LittleEndian.getShort(data, 8 + offset); + field_6_selected_tab = LittleEndian.getShort(data, 10 + offset); + field_7_displayed_tab = LittleEndian.getShort(data, 12 + offset); + field_8_num_selected_tabs = LittleEndian.getShort(data, 14 + offset); + field_9_tab_width_ratio = LittleEndian.getShort(data, 16 + offset); + } + + /** + * set the horizontal position of the window (in 1/20ths of a point) + * @param h - horizontal location + */ + + public void setHorizontalHold(short h) + { + field_1_h_hold = h; + } + + /** + * set the vertical position of the window (in 1/20ths of a point) + * @param v - vertical location + */ + + public void setVerticalHold(short v) + { + field_2_v_hold = v; + } + + /** + * set the width of the window + * @param width + */ + + public void setWidth(short w) + { + field_3_width = w; + } + + /** + * set teh height of the window + * @param height + */ + + public void setHeight(short h) + { + field_4_height = h; + } + + /** + * set the options bitmask (see bit setters) + * + * @param o - the bitmask + */ + + public void setOptions(short o) + { + field_5_options = o; + } + + // bitfields for options + + /** + * set whether the window is hidden or not + * @param ishidden or not + */ + + public void setHidden(boolean ishidden) + { + hidden.setShortBoolean(field_5_options, ishidden); + } + + /** + * set whether the window has been iconized or not + * @param iconize or not + */ + + public void setIconic(boolean isiconic) + { + iconic.setShortBoolean(field_5_options, isiconic); + } + + /** + * set whether to display the horizontal scrollbar or not + * @param display or not + */ + + public void setDisplayHorizonalScrollbar(boolean scroll) + { + hscroll.setShortBoolean(field_5_options, scroll); + } + + /** + * set whether to display the vertical scrollbar or not + * @param display or not + */ + + public void setDisplayVerticalScrollbar(boolean scroll) + { + vscroll.setShortBoolean(field_5_options, scroll); + } + + /** + * set whether to display the tabs or not + * @param display or not + */ + + public void setDisplayTabs(boolean disptabs) + { + tabs.setShortBoolean(field_5_options, disptabs); + } + + // end bitfields + + /** + * set the selected tab number + * @param Tab number + */ + + public void setSelectedTab(short s) + { + field_6_selected_tab = s; + } + + /** + * set the displayed tab number + * @param Tab number + */ + + public void setDisplayedTab(short t) + { + field_7_displayed_tab = t; + } + + /** + * set the number of selected tabs + * @param number of tabs + */ + + public void setNumSelectedTabs(short n) + { + field_8_num_selected_tabs = n; + } + + /** + * ratio of the width of the tabs to the horizontal scrollbar + * @param ratio + */ + + public void setTabWidthRatio(short r) + { + field_9_tab_width_ratio = r; + } + + /** + * get the horizontal position of the window (in 1/20ths of a point) + * @return h - horizontal location + */ + + public short getHorizontalHold() + { + return field_1_h_hold; + } + + /** + * get the vertical position of the window (in 1/20ths of a point) + * @return v - vertical location + */ + + public short getVerticalHold() + { + return field_2_v_hold; + } + + /** + * get the width of the window + * @return width + */ + + public short getWidth() + { + return field_3_width; + } + + /** + * get the height of the window + * @return height + */ + + public short getHeight() + { + return field_4_height; + } + + /** + * get the options bitmask (see bit setters) + * + * @return o - the bitmask + */ + + public short getOptions() + { + return field_5_options; + } + + // bitfields for options + + /** + * get whether the window is hidden or not + * @return ishidden or not + */ + + public boolean getHidden() + { + return hidden.isSet(field_5_options); + } + + /** + * get whether the window has been iconized or not + * @return iconize or not + */ + + public boolean getIconic() + { + return iconic.isSet(field_5_options); + } + + /** + * get whether to display the horizontal scrollbar or not + * @return display or not + */ + + public boolean getDisplayHorizontalScrollbar() + { + return hscroll.isSet(field_5_options); + } + + /** + * get whether to display the vertical scrollbar or not + * @return display or not + */ + + public boolean getDisplayVerticalScrollbar() + { + return vscroll.isSet(field_5_options); + } + + /** + * get whether to display the tabs or not + * @return display or not + */ + + public boolean getDisplayTabs() + { + return tabs.isSet(field_5_options); + } + + // end options bitfields + + /** + * get the selected tab number + * @return Tab number + */ + + public short getSelectedTab() + { + return field_6_selected_tab; + } + + /** + * get the displayed tab number + * @return Tab number + */ + + public short getDisplayedTab() + { + return field_7_displayed_tab; + } + + /** + * get the number of selected tabs + * @return number of tabs + */ + + public short getNumSelectedTabs() + { + return field_8_num_selected_tabs; + } + + /** + * ratio of the width of the tabs to the horizontal scrollbar + * @return ratio + */ + + public short getTabWidthRatio() + { + return field_9_tab_width_ratio; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[WINDOW1]\n"); + buffer.append(" .h_hold = ") + .append(Integer.toHexString(getHorizontalHold())).append("\n"); + buffer.append(" .v_hold = ") + .append(Integer.toHexString(getVerticalHold())).append("\n"); + buffer.append(" .width = ") + .append(Integer.toHexString(getWidth())).append("\n"); + buffer.append(" .height = ") + .append(Integer.toHexString(getHeight())).append("\n"); + buffer.append(" .options = ") + .append(Integer.toHexString(getOptions())).append("\n"); + buffer.append(" .hidden = ").append(getHidden()) + .append("\n"); + buffer.append(" .iconic = ").append(getIconic()) + .append("\n"); + buffer.append(" .hscroll = ") + .append(getDisplayHorizontalScrollbar()).append("\n"); + buffer.append(" .vscroll = ") + .append(getDisplayVerticalScrollbar()).append("\n"); + buffer.append(" .tabs = ").append(getDisplayTabs()) + .append("\n"); + buffer.append(" .selectedtab = ") + .append(Integer.toHexString(getSelectedTab())).append("\n"); + buffer.append(" .displayedtab = ") + .append(Integer.toHexString(getDisplayedTab())).append("\n"); + buffer.append(" .numselectedtabs = ") + .append(Integer.toHexString(getNumSelectedTabs())).append("\n"); + buffer.append(" .tabwidthratio = ") + .append(Integer.toHexString(getTabWidthRatio())).append("\n"); + buffer.append("[/WINDOW1]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x12)); // 18 bytes (22 total) + LittleEndian.putShort(data, 4 + offset, getHorizontalHold()); + LittleEndian.putShort(data, 6 + offset, getVerticalHold()); + LittleEndian.putShort(data, 8 + offset, getWidth()); + LittleEndian.putShort(data, 10 + offset, getHeight()); + LittleEndian.putShort(data, 12 + offset, getOptions()); + LittleEndian.putShort(data, 14 + offset, getSelectedTab()); + LittleEndian.putShort(data, 16 + offset, getDisplayedTab()); + LittleEndian.putShort(data, 18 + offset, getNumSelectedTabs()); + LittleEndian.putShort(data, 20 + offset, getTabWidthRatio()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 22; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/WindowProtectRecord.java b/src/java/org/apache/poi/hssf/record/WindowProtectRecord.java new file mode 100644 index 000000000..63d868a66 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/WindowProtectRecord.java @@ -0,0 +1,175 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +/** + * Title: Window Protect Record

+ * Description: flags whether workbook windows are protected

+ * REFERENCE: PG 424 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class WindowProtectRecord + extends Record +{ + public final static short sid = 0x19; + private short field_1_protect; + + public WindowProtectRecord() + { + } + + /** + * Constructs a WindowProtect record and sets its fields appropriately. + * + * @param short id must be 0x19 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public WindowProtectRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a WindowProtect record and sets its fields appropriately. + * + * @param short id must be 0x19 or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public WindowProtectRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A WINDOWPROTECT RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_protect = LittleEndian.getShort(data, 0 + offset); + } + + /** + * set whether this window should be protected or not + * @param protect or not + */ + + public void setProtect(boolean protect) + { + if (protect == true) + { + field_1_protect = 1; + } + else + { + field_1_protect = 0; + } + } + + /** + * is this window protected or not + * + * @return protected or not + */ + + public boolean getProtect() + { + return (field_1_protect == 1); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[WINDOWPROTECT]\n"); + buffer.append(" .protect = ").append(getProtect()) + .append("\n"); + buffer.append("[/WINDOWPROTECT]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + (( short ) 0x02)); // 2 bytes (6 total) + LittleEndian.putShort(data, 4 + offset, field_1_protect); + return getRecordSize(); + } + + public int getRecordSize() + { + return 6; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/WindowTwoRecord.java b/src/java/org/apache/poi/hssf/record/WindowTwoRecord.java new file mode 100644 index 000000000..b2ac56c4d --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/WindowTwoRecord.java @@ -0,0 +1,618 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.BitField; +import org.apache.poi.util.LittleEndian; + +/** + * Title: Window Two Record

+ * Description: sheet window settings

+ * REFERENCE: PG 422 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class WindowTwoRecord + extends Record +{ + public final static short sid = 0x23e; + private short field_1_options; + + // bitfields + private BitField displayFormulas = new BitField(0x01); + private BitField displayGridlines = new BitField(0x02); + private BitField displayRowColHeadings = new BitField(0x04); + private BitField freezePanes = new BitField(0x08); + private BitField displayZeros = new BitField(0x10); + private BitField defaultHeader = + new BitField(0x20); // if false use color in field 4 + + // if true use default foreground + // for headers + private BitField arabic = + new BitField(0x40); // for our desert dwelling friends + private BitField displayGuts = new BitField(0x80); + private BitField freezePanesNoSplit = new BitField(0x100); + private BitField selected = new BitField(0x200); + private BitField paged = new BitField(0x400); + private BitField savedInPageBreakPreview = new BitField(0x800); + + // 4-7 reserved + // end bitfields + private short field_2_top_row; + private short field_3_left_col; + private int field_4_header_color; + private short field_5_page_break_zoom; + private short field_6_normal_zoom; + private int field_7_reserved; + + public WindowTwoRecord() + { + } + + /** + * Constructs a WindowTwo record and sets its fields appropriately. + * + * @param short id must be 0x23e or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public WindowTwoRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a WindowTwo record and sets its fields appropriately. + * + * @param short id must be 0x23e or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public WindowTwoRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A valid WindowTwo RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_options = LittleEndian.getShort(data, 0 + offset); + field_2_top_row = LittleEndian.getShort(data, 2 + offset); + field_3_left_col = LittleEndian.getShort(data, 4 + offset); + field_4_header_color = LittleEndian.getInt(data, 6 + offset); + if (size > 10) + { + field_5_page_break_zoom = LittleEndian.getShort(data, + 10 + offset); + field_6_normal_zoom = LittleEndian.getShort(data, + 12 + offset); + } + if (size > 14) + { // there is a special case of this record that has only 14 bytes...undocumented! + field_7_reserved = LittleEndian.getInt(data, 14 + offset); + } + } + + /** + * set the options bitmask or just use the bit setters. + * @param options + */ + + public void setOptions(short options) + { + field_1_options = options; + } + + // option bitfields + + /** + * set whether the window should display formulas + * @param formulas or not + */ + + public void setDisplayFormulas(boolean formulas) + { + displayFormulas.setBoolean(field_1_options, formulas); + } + + /** + * set whether the window should display gridlines + * @param gridlines or not + */ + + public void setDisplayGridlines(boolean gridlines) + { + displayGridlines.setBoolean(field_1_options, gridlines); + } + + /** + * set whether the window should display row and column headings + * @param headings or not + */ + + public void setDisplayRowColHeadings(boolean headings) + { + displayRowColHeadings.setBoolean(field_1_options, headings); + } + + /** + * set whether the window should freeze panes + * @param freeze panes or not + */ + + public void setFreezePanes(boolean freezepanes) + { + freezePanes.setBoolean(field_1_options, freezepanes); + } + + /** + * set whether the window should display zero values + * @param zeros or not + */ + + public void setDisplayZeros(boolean zeros) + { + displayZeros.setBoolean(field_1_options, zeros); + } + + /** + * set whether the window should display a default header + * @param header or not + */ + + public void setDefaultHeader(boolean header) + { + defaultHeader.setBoolean(field_1_options, header); + } + + /** + * is this arabic? + * @param arabic or not + */ + + public void setArabic(boolean isarabic) + { + arabic.setBoolean(field_1_options, isarabic); + } + + /** + * set whether the outline symbols are displaed + * @param symbols or not + */ + + public void setDisplayGuts(boolean guts) + { + displayGuts.setBoolean(field_1_options, guts); + } + + /** + * freeze unsplit panes or not + * @param freeze or not + */ + + public void setFreezePanesNoSplit(boolean freeze) + { + freezePanesNoSplit.setBoolean(field_1_options, freeze); + } + + /** + * sheet tab is selected + * @param selected or not + */ + + public void setSelected(boolean sel) + { + selected.setBoolean(field_1_options, sel); + } + + /** + * is the sheet currently displayed in the window + * @param displayed or not + */ + + public void setPaged(boolean p) + { + paged.setBoolean(field_1_options, p); + } + + /** + * was the sheet saved in page break view + * @param pagebreaksaved or not + */ + + public void setSavedInPageBreakPreview(boolean p) + { + savedInPageBreakPreview.setBoolean(field_1_options, p); + } + + // end of bitfields. + + /** + * set the top row visible in the window + * @param toprow + */ + + public void setTopRow(short topRow) + { + field_2_top_row = topRow; + } + + /** + * set the leftmost column displayed in the window + * @param leftmost + */ + + public void setLeftCol(short leftCol) + { + field_3_left_col = leftCol; + } + + /** + * set the palette index for the header color + * @param color + */ + + public void setHeaderColor(int color) + { + field_4_header_color = color; + } + + /** + * zoom magification in page break view + * @param zoom + */ + + public void setPageBreakZoom(short zoom) + { + field_5_page_break_zoom = zoom; + } + + /** + * set the zoom magnification in normal view + * @param zoom + */ + + public void setNormalZoom(short zoom) + { + field_6_normal_zoom = zoom; + } + + /** + * set the reserved (don't do this) value + */ + + public void setReserved(int reserved) + { + field_7_reserved = reserved; + } + + /** + * get the options bitmask or just use the bit setters. + * @return options + */ + + public short getOptions() + { + return field_1_options; + } + + // option bitfields + + /** + * get whether the window should display formulas + * @return formulas or not + */ + + public boolean getDisplayFormulas() + { + return displayFormulas.isSet(field_1_options); + } + + /** + * get whether the window should display gridlines + * @return gridlines or not + */ + + public boolean getDisplayGridlines() + { + return displayGridlines.isSet(field_1_options); + } + + /** + * get whether the window should display row and column headings + * @return headings or not + */ + + public boolean getDisplayRowColHeadings() + { + return displayRowColHeadings.isSet(field_1_options); + } + + /** + * get whether the window should freeze panes + * @return freeze panes or not + */ + + public boolean getFreezePanes() + { + return freezePanes.isSet(field_1_options); + } + + /** + * get whether the window should display zero values + * @return zeros or not + */ + + public boolean getDisplayZeros() + { + return displayZeros.isSet(field_1_options); + } + + /** + * get whether the window should display a default header + * @return header or not + */ + + public boolean getDefaultHeader() + { + return defaultHeader.isSet(field_1_options); + } + + /** + * is this arabic? + * @return arabic or not + */ + + public boolean getArabic() + { + return arabic.isSet(field_1_options); + } + + /** + * get whether the outline symbols are displaed + * @return symbols or not + */ + + public boolean getDisplayGuts() + { + return displayGuts.isSet(field_1_options); + } + + /** + * freeze unsplit panes or not + * @return freeze or not + */ + + public boolean getFreezePanesNoSplit() + { + return freezePanesNoSplit.isSet(field_1_options); + } + + /** + * sheet tab is selected + * @return selected or not + */ + + public boolean getSelected() + { + return selected.isSet(field_1_options); + } + + /** + * is the sheet currently displayed in the window + * @return displayed or not + */ + + public boolean getPaged() + { + return paged.isSet(field_1_options); + } + + /** + * was the sheet saved in page break view + * @return pagebreaksaved or not + */ + + public boolean getSavedInPageBreakPreview() + { + return savedInPageBreakPreview.isSet(field_1_options); + } + + // end of bitfields. + + /** + * get the top row visible in the window + * @return toprow + */ + + public short getTopRow() + { + return field_2_top_row; + } + + /** + * get the leftmost column displayed in the window + * @return leftmost + */ + + public short getLeftCol() + { + return field_3_left_col; + } + + /** + * get the palette index for the header color + * @return color + */ + + public int getHeaderColor() + { + return field_4_header_color; + } + + /** + * zoom magification in page break view + * @return zoom + */ + + public short getPageBreakZoom() + { + return field_5_page_break_zoom; + } + + /** + * get the zoom magnification in normal view + * @return zoom + */ + + public short getNormalZoom() + { + return field_6_normal_zoom; + } + + /** + * get the reserved bits - why would you do this? + * @return reserved stuff -probably garbage + */ + + public int getReserved() + { + return field_7_reserved; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[WINDOW2]\n"); + buffer.append(" .options = ") + .append(Integer.toHexString(getOptions())).append("\n"); + buffer.append(" .dispformulas= ").append(getDisplayFormulas()) + .append("\n"); + buffer.append(" .dispgridlins= ").append(getDisplayGridlines()) + .append("\n"); + buffer.append(" .disprcheadin= ") + .append(getDisplayRowColHeadings()).append("\n"); + buffer.append(" .freezepanes = ").append(getFreezePanes()) + .append("\n"); + buffer.append(" .displayzeros= ").append(getDisplayZeros()) + .append("\n"); + buffer.append(" .defaultheadr= ").append(getDefaultHeader()) + .append("\n"); + buffer.append(" .arabic = ").append(getArabic()) + .append("\n"); + buffer.append(" .displayguts = ").append(getDisplayGuts()) + .append("\n"); + buffer.append(" .frzpnsnosplt= ") + .append(getFreezePanesNoSplit()).append("\n"); + buffer.append(" .selected = ").append(getSelected()) + .append("\n"); + buffer.append(" .paged = ").append(getPaged()) + .append("\n"); + buffer.append(" .svdinpgbrkpv= ") + .append(getSavedInPageBreakPreview()).append("\n"); + buffer.append(" .toprow = ") + .append(Integer.toHexString(getTopRow())).append("\n"); + buffer.append(" .leftcol = ") + .append(Integer.toHexString(getLeftCol())).append("\n"); + buffer.append(" .headercolor = ") + .append(Integer.toHexString(getHeaderColor())).append("\n"); + buffer.append(" .pagebreakzoom = ") + .append(Integer.toHexString(getPageBreakZoom())).append("\n"); + buffer.append(" .normalzoom = ") + .append(Integer.toHexString(getNormalZoom())).append("\n"); + buffer.append(" .reserved = ") + .append(Integer.toHexString(getReserved())).append("\n"); + buffer.append("[/WINDOW2]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, ( short ) 18); + LittleEndian.putShort(data, 4 + offset, getOptions()); + LittleEndian.putShort(data, 6 + offset, getTopRow()); + LittleEndian.putShort(data, 8 + offset, getLeftCol()); + LittleEndian.putInt(data, 10 + offset, getHeaderColor()); + LittleEndian.putShort(data, 14 + offset, getPageBreakZoom()); + LittleEndian.putShort(data, 16 + offset, getNormalZoom()); + LittleEndian.putInt(data, 18 + offset, getReserved()); + return getRecordSize(); + } + + public int getRecordSize() + { + return 22; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/WriteAccessRecord.java b/src/java/org/apache/poi/hssf/record/WriteAccessRecord.java new file mode 100644 index 000000000..8c3967eef --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/WriteAccessRecord.java @@ -0,0 +1,191 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.StringUtil; + +/** + * Title: Write Access Record

+ * Description: Stores the username of that who owns the spreadsheet generator + * (on unix the user's login, on Windoze its the name you typed when + * you installed the thing)

+ * REFERENCE: PG 424 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 2.0-pre + */ + +public class WriteAccessRecord + extends Record +{ + public final static short sid = 0x5c; + private String field_1_username; + + public WriteAccessRecord() + { + } + + /** + * Constructs a WriteAccess record and sets its fields appropriately. + * + * @param short id must be 0x5c or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + */ + + public WriteAccessRecord(short id, short size, byte [] data) + { + super(id, size, data); + } + + /** + * Constructs a WriteAccess record and sets its fields appropriately. + * + * @param short id must be 0x5c or an exception will be throw upon validation + * @param short size the size of the data area of the record + * @param byte[] data of the record (should not contain sid/len) + * @param offset of the record data + */ + + public WriteAccessRecord(short id, short size, byte [] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT A WRITEACCESS RECORD"); + } + } + + protected void fillFields(byte [] data, short size, int offset) + { + field_1_username = new String(data, 3 + offset, data.length - 4); + } + + /** + * set the username for the user that created the report. HSSF uses the logged in user. + * @param username of the user who is logged in (probably "tomcat" or "apache") + */ + + public void setUsername(String username) + { + field_1_username = username; + } + + /** + * get the username for the user that created the report. HSSF uses the logged in user. On + * natively created M$ Excel sheet this would be the name you typed in when you installed it + * in most cases. + * @return username of the user who is logged in (probably "tomcat" or "apache") + */ + + public String getUsername() + { + return field_1_username; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[WRITEACCESS]\n"); + buffer.append(" .name = ") + .append(field_1_username.toString()).append("\n"); + buffer.append("[/WRITEACCESS]\n"); + return buffer.toString(); + } + + public int serialize(int offset, byte [] data) + { + String username = getUsername(); + StringBuffer temp = new StringBuffer(0x70 - (0x3)); + + temp.append(username); + while (temp.length() < 0x70 - 0x3) + { + temp.append( + " "); // (70 = fixed lenght -3 = the overhead bits of unicode string) + } + username = temp.toString(); + UnicodeString str = new UnicodeString(); + + str.setString(username); + str.setOptionFlags(( byte ) 0x0); + str.setCharCount(( short ) 0x4); + byte[] stringbytes = str.serialize(); + + LittleEndian.putShort(data, 0 + offset, sid); + LittleEndian.putShort(data, 2 + offset, + ( short ) (stringbytes + .length)); // 112 bytes (115 total) + System.arraycopy(stringbytes, 0, data, 4 + offset, + stringbytes.length); + return getRecordSize(); + } + + public int getRecordSize() + { + return 116; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java new file mode 100644 index 000000000..a245eab41 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java @@ -0,0 +1,219 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record.aggregates; + +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.RowRecord; +import org.apache.poi.hssf.record.UnknownRecord; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +/** + * + * @author andy + */ + +public class RowRecordsAggregate + extends Record +{ + int firstrow = -1; + int lastrow = -1; + HashMap records = null; + int size = 0; + + /** Creates a new instance of ValueRecordsAggregate */ + + public RowRecordsAggregate() + { + records = new HashMap(); + } + + public void insertRow(RowRecord row) + { + size += row.getRecordSize(); + + // Integer integer = new Integer(row.getRowNumber()); + records.put(row, row); + if ((row.getRowNumber() < firstrow) || (firstrow == -1)) + { + firstrow = row.getRowNumber(); + } + if ((row.getRowNumber() > lastrow) || (lastrow == -1)) + { + lastrow = row.getRowNumber(); + } + } + + public void removeRow(RowRecord row) + { + size -= row.getRecordSize(); + + // Integer integer = new Integer(row.getRowNumber()); + records.remove(row); + } + + public RowRecord getRow(int rownum) + { + + // Integer integer = new Integer(rownum); + RowRecord row = new RowRecord(); + + row.setRowNumber(( short ) rownum); + return ( RowRecord ) records.get(row); + } + + public int getPhysicalNumberOfRows() + { + return records.size(); + } + + public int getFirstRowNum() + { + return firstrow; + } + + public int getLastRowNum() + { + return lastrow; + } + + public int construct(int offset, List records) + { + int k = 0; + + for (k = offset; k < records.size(); k++) + { + Record rec = ( Record ) records.get(k); + + if (!rec.isInValueSection() && !(rec instanceof UnknownRecord)) + { + break; + } + if (rec.getSid() == RowRecord.sid) + { + insertRow(( RowRecord ) rec); + } + } + return k; + } + + /** + * 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. + * + * @param offset to begin writing at + * @param byte array containing instance data + * @return number of bytes written + */ + + public int serialize(int offset, byte [] data) + { + Iterator itr = records.values().iterator(); + int pos = offset; + + while (itr.hasNext()) + { + pos += (( Record ) itr.next()).serialize(pos, data); + } + return pos - offset; + } + + /** + * called by the constructor, should set class level fields. Should throw + * runtime exception for bad/icomplete data. + * + * @param data raw data + * @param size size of data + * @param offset of the record's data (provided a big array of the file) + */ + + protected void fillFields(byte [] data, short size, int offset) + { + } + + /** + * called by constructor, should throw runtime exception in the event of a + * record passed with a differing ID. + * + * @param id alleged id for this record + */ + + protected void validateSid(short id) + { + } + + /** + * return the non static version of the id for this record. + */ + + public short getSid() + { + return -1000; + } + + public int getRecordSize() + { + return size; + } + + public Iterator getIterator() + { + return records.values().iterator(); + } +} diff --git a/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java new file mode 100644 index 000000000..9545cc372 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java @@ -0,0 +1,276 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record.aggregates; + +import org.apache.poi.hssf.record.CellValueRecordInterface; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.UnknownRecord; + +import java.util.Iterator; +import java.util.List; +import java.util.TreeMap; + +/** + * + * Aggregate value records together. Things are easier to handle that way. + * + * @author andy + * @author Glen Stampoultzis (gstamp at iprimus dot com dot au) + */ + +public class ValueRecordsAggregate + extends Record +{ + public final static short sid = -1000; + int firstcell = -1; + int lastcell = -1; + TreeMap records = null; + int size = 0; + + /** Creates a new instance of ValueRecordsAggregate */ + + public ValueRecordsAggregate() + { + records = new TreeMap(); + } + + public void insertCell(CellValueRecordInterface cell) + { + if (records.get(cell) == null) + { + size += (( Record ) cell).getRecordSize(); + } + else + { + size += (( Record ) cell).getRecordSize() + - (( Record ) records.get(cell)).getRecordSize(); + } + + // XYLocator xy = new XYLocator(cell.getRow(), cell.getColumn()); + records.put(cell, cell); + if ((cell.getColumn() < firstcell) || (firstcell == -1)) + { + firstcell = cell.getColumn(); + } + if ((cell.getColumn() > lastcell) || (lastcell == -1)) + { + lastcell = cell.getColumn(); + } + } + + public void removeCell(CellValueRecordInterface cell) + { + size -= (( Record ) cell).getRecordSize(); + + // XYLocator xy = new XYLocator(cell.getRow(), cell.getColumn()); + records.remove(cell); + } + + public int getPhysicalNumberOfCells() + { + return records.size(); + } + + public int getFirstCellNum() + { + return firstcell; + } + + public int getLastCellNum() + { + return lastcell; + } + + public int construct(int offset, List records) + { + int k = 0; + + for (k = offset; k < records.size(); k++) + { + Record rec = ( Record ) records.get(k); + + if (!rec.isInValueSection() && !(rec instanceof UnknownRecord)) + { + break; + } + if (rec.isValue()) + { + insertCell(( CellValueRecordInterface ) rec); + } + } + return k; + } + + /** + * 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. + * + * @param offset to begin writing at + * @param byte array containing instance data + * @return number of bytes written + */ + + public int serialize(int offset, byte [] data) + { + Iterator itr = records.values().iterator(); + int pos = offset; + + while (itr.hasNext()) + { + pos += (( Record ) itr.next()).serialize(pos, data); + } + return pos - offset; + } + + /** + * called by the constructor, should set class level fields. Should throw + * runtime exception for bad/icomplete data. + * + * @param data raw data + * @param size size of data + * @param offset of the record's data (provided a big array of the file) + */ + + protected void fillFields(byte [] data, short size, int offset) + { + } + + /** + * called by constructor, should throw runtime exception in the event of a + * record passed with a differing ID. + * + * @param id alleged id for this record + */ + + protected void validateSid(short id) + { + } + + /** + * return the non static version of the id for this record. + */ + + public short getSid() + { + return sid; + } + + public int getRecordSize() + { + return size; + } + + public Iterator getIterator() + { + return records.values().iterator(); + } +} + +/* + * class XYLocator implements Comparable { + * private int row = 0; + * private int col = 0; + * public XYLocator(int row, int col) { + * this.row = row; + * this.col = col; + * } + * + * public int getRow() { + * return row; + * } + * + * public int getCol() { + * return col; + * } + * + * public int compareTo(Object obj) { + * XYLocator loc = (XYLocator)obj; + * + * if (this.getRow() == loc.getRow() && + * this.getCol() == loc.getCol() ) + * return 0; + * + * if (this.getRow() < loc.getRow()) + * return -1; + * + * if (this.getRow() > loc.getRow()) + * return 1; + * + * if (this.getCol() < loc.getCol()) + * return -1; + * + * if (this.getCol() > loc.getCol()) + * return 1; + * + * return -1; + * + * } + * + * public boolean equals(Object obj) { + * if (!(obj instanceof XYLocator)) return false; + * + * XYLocator loc = (XYLocator)obj; + * if (this.getRow() == loc.getRow() + * && + * this.getCol() == loc.getCol() + * ) return true; + * return false; + * } + * + * + * } + */ diff --git a/src/java/org/apache/poi/hssf/record/formula/AddPtg.java b/src/java/org/apache/poi/hssf/record/formula/AddPtg.java new file mode 100644 index 000000000..4ce150262 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/AddPtg.java @@ -0,0 +1,121 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * AddPtg.java + * + * Created on October 29, 2001, 7:48 PM + */ +package org.apache.poi.hssf.record.formula; + +/** + * + * @author andy + */ + +public class AddPtg + extends Ptg + implements OperationPtg +{ + public final static int SIZE = 1; + public final static byte sid = 0x03; + + /** Creates new AddPtg */ + + public AddPtg() + { + } + + public AddPtg(byte [] data, int offset) + { + + // doesn't need anything + } + + public void writeBytes(byte [] array, int offset) + { + array[ offset + 0 ] = sid; + } + + public int getSize() + { + return SIZE; + } + + public int getType() + { + return TYPE_BINARY; + } + + public int getNumberOfOperands() + { + return 2; + } + + public String toFormulaString() + { + return "+"; + } + + public String toFormulaString(Ptg [] operands) + { + StringBuffer buffer = new StringBuffer(); + + buffer.append(operands[ 0 ].toFormulaString()); + buffer.append("+"); + buffer.append(operands[ 1 ].toFormulaString()); + return buffer.toString(); + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/AreaPtg.java b/src/java/org/apache/poi/hssf/record/formula/AreaPtg.java new file mode 100644 index 000000000..be7efab2a --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/AreaPtg.java @@ -0,0 +1,244 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * AreaPtg.java + * + * Created on November 17, 2001, 9:30 PM + */ +package org.apache.poi.hssf.record.formula; + +import org.apache.poi.util.LittleEndian; + +/** + * + * @author andy + */ + +public class AreaPtg + extends Ptg +{ + public final static short sid = 0x25; + private final static int SIZE = 9; + private short field_1_first_row; + private short field_2_last_row; + private short field_3_first_column; + private short field_4_last_column; + + /** Creates new AreaPtg */ + + public AreaPtg() + { + } + + public AreaPtg(byte [] data, int offset) + { + offset++; + field_1_first_row = LittleEndian.getShort(data, 0 + offset); + field_2_last_row = LittleEndian.getShort(data, 2 + offset); + field_3_first_column = LittleEndian.getShort(data, 4 + offset); + field_4_last_column = LittleEndian.getShort(data, 6 + offset); + System.out.println(toString()); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("AreaPtg\n"); + buffer.append("firstRow = " + getFirstRow()).append("\n"); + buffer.append("lastRow = " + getLastRow()).append("\n"); + buffer.append("firstCol = " + getFirstColumn()).append("\n"); + buffer.append("lastCol = " + getLastColumn()).append("\n"); + buffer.append("firstColRowRel= " + + isFirstColRowRelative()).append("\n"); + buffer.append("lastColRowRel = " + + isLastColRowRelative()).append("\n"); + buffer.append("firstColRel = " + isFirstColRelative()).append("\n"); + buffer.append("lastColRel = " + isLastColRelative()).append("\n"); + return buffer.toString(); + } + + public void writeBytes(byte [] array, int offset) + { + } + + public int getSize() + { + return SIZE; + } + + public short getFirstRow() + { + return field_1_first_row; + } + + public void setFirstRow(short row) + { + field_1_first_row = row; + } + + public short getLastRow() + { + return field_2_last_row; + } + + public void setLastRow(short row) + { + field_2_last_row = row; + } + + public short getFirstColumn() + { + return ( short ) (field_3_first_column & 0x3FFF); + } + + public short getFirstColumnRaw() + { + return field_3_first_column; + } + + public boolean isFirstColRowRelative() + { + return (((getFirstColumnRaw()) & 0x8000) == 0x8000); + } + + public boolean isFirstColRelative() + { + return (((getFirstColumnRaw()) & 0x4000) == 0x4000); + } + + public void setFirstColumn(short column) + { + field_3_first_column = column; // fixme + } + + public void setFirstColumnRaw(short column) + { + field_3_first_column = column; + } + + public short getLastColumn() + { + return ( short ) (field_4_last_column & 0x3FFF); // fixme + } + + public short getLastColumnRaw() + { + return field_4_last_column; + } + + public boolean isLastColRowRelative() + { + return (((getLastColumnRaw()) & 0x8000) == 1); + } + + public boolean isLastColRelative() + { + return (((getFirstColumnRaw()) & 0x4000) == 1); + } + + public void setLastColumn(short column) + { + field_4_last_column = column; // fixme + } + + public void setLastColumnRaw(short column) + { + field_4_last_column = column; + } + + public String toFormulaString() + { + String firstrow = "" + (getFirstRow() + 1); + String lastrow = null; + + if (isLastColRowRelative()) + { + lastrow = "" + (getFirstRow() + getLastRow()); + } + else + { + lastrow = "" + (getLastRow() + 1); + } + + // String firstcol = ""+ + // String lastcol + return colNumToLetter(getFirstColumn()) + firstrow + ":" + + colNumToLetter(getLastColumn()) + lastrow; + } + + public String colNumToLetter(int col) + { + byte[] b = + { + 0x41 + }; + + b[ 0 ] += ( byte ) col; + String retval = null; + + try + { + retval = new String(b, "UTF-8"); + } + catch (java.io.UnsupportedEncodingException e) + { + throw new RuntimeException( + "NON JDK 1.3 COMPLIANT JVM -- YOUR JVM MUST SUPPORT UTF-8 encoding as per docs!"); + } + return retval; + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java b/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java new file mode 100644 index 000000000..0a9fb5c48 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java @@ -0,0 +1,208 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * AttrPtg.java + * + * Created on November 21, 2001, 1:20 PM + */ +package org.apache.poi.hssf.record.formula; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.BitField; + +/** + * "Special Attributes" + * This seems to be a Misc Stuff and Junk record. One function it serves is + * in SUM functions (i.e. SUM(A1:A3) causes an area PTG then an ATTR with the SUM option set) + * @author andy + */ + +public class AttrPtg + extends Ptg + implements OperationPtg +{ + public final static short sid = 0x19; + private final static int SIZE = 4; + private byte field_1_options; + private short field_2_data; + private BitField semiVolatile = new BitField(0x01); + private BitField optiIf = new BitField(0x02); + private BitField optiChoose = new BitField(0x04); + private BitField optGoto = new BitField(0x08); + private BitField sum = new BitField(0x10); + private BitField baxcel = new BitField(0x20); + private BitField space = new BitField(0x40); + + /** Creates new AttrPtg */ + + public AttrPtg() + { + } + + public AttrPtg(byte [] data, int offset) + { + offset++; // adjust past id + field_1_options = data[ offset + 0 ]; + field_2_data = LittleEndian.getShort(data, offset + 1); + System.out.println("OPTIONS = " + Integer.toHexString(getOptions())); + System.out.println("OPTIONS & 0x10 = " + (getOptions() & 0x10)); + System.out.println(toString()); + } + + public void setOptions(byte options) + { + field_1_options = options; + } + + public byte getOptions() + { + return field_1_options; + } + + public boolean isSemiVolatile() + { + return semiVolatile.isSet(getOptions()); + } + + public boolean isOptimizedIf() + { + return optiIf.isSet(getOptions()); + } + + public boolean isOptimizedChoose() + { + return optiChoose.isSet(getOptions()); + } + + // lets hope no one uses this anymore + public boolean isGoto() + { + return optGoto.isSet(getOptions()); + } + + public boolean isSum() + { + return sum.isSet(getOptions()); + } + + // lets hope no one uses this anymore + public boolean isBaxcel() + { + return baxcel.isSet(getOptions()); + } + + // biff3&4 only shouldn't happen anymore + public boolean isSpace() + { + return space.isSet(getOptions()); + } + + public void setData(short data) + { + field_2_data = data; + } + + public short getData() + { + return field_2_data; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("AttrPtg\n"); + buffer.append("options=").append(field_1_options).append("\n"); + buffer.append("data =").append(field_2_data).append("\n"); + buffer.append("semi =").append(isSemiVolatile()).append("\n"); + buffer.append("optimif=").append(isOptimizedIf()).append("\n"); + buffer.append("optchos=").append(isOptimizedChoose()).append("\n"); + buffer.append("isGoto =").append(isGoto()).append("\n"); + buffer.append("isSum =").append(isSum()).append("\n"); + buffer.append("isBaxce=").append(isBaxcel()).append("\n"); + buffer.append("isSpace=").append(isSpace()).append("\n"); + return buffer.toString(); + } + + public void writeBytes(byte [] array, int offset) + { + } + + public int getSize() + { + return SIZE; + } + + public String toFormulaString() + { + return "SUM()"; + } + + public String toFormulaString(Ptg [] operands) + { + return "SUM(" + operands[ 0 ].toFormulaString() + ")"; + } + + public int getNumberOfOperands() + { + return 1; + } + + public int getType() + { + return -1; + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/DividePtg.java b/src/java/org/apache/poi/hssf/record/formula/DividePtg.java new file mode 100644 index 000000000..241047f3b --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/DividePtg.java @@ -0,0 +1,121 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * DividePtg.java + * + * Created on November 4, 2001, 9:04 PM + */ +package org.apache.poi.hssf.record.formula; + +/** + * + * @author andy + */ + +public class DividePtg + extends Ptg + implements OperationPtg +{ + public final static int SIZE = 1; + public final static byte sid = 0x06; + + /** Creates new AddPtg */ + + public DividePtg() + { + } + + public DividePtg(byte [] data, int offset) + { + + // doesn't need anything + } + + public void writeBytes(byte [] array, int offset) + { + array[ offset + 0 ] = sid; + } + + public int getSize() + { + return SIZE; + } + + public int getType() + { + return TYPE_BINARY; + } + + public int getNumberOfOperands() + { + return 2; + } + + public String toFormulaString() + { + return "/"; + } + + public String toFormulaString(Ptg [] operands) + { + StringBuffer buffer = new StringBuffer(); + + buffer.append(operands[ 0 ].toFormulaString()); + buffer.append("/"); + buffer.append(operands[ 1 ].toFormulaString()); + return buffer.toString(); + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java b/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java new file mode 100644 index 000000000..19320f7ae --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java @@ -0,0 +1,99 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * ExpPtg.java + * + * Created on November 25, 2001, 4:00 PM + */ +package org.apache.poi.hssf.record.formula; + +/** + * + * @author andy + */ + +public class ExpPtg + extends Ptg +{ + private final static int SIZE = 5; + public final static short sid = 0x1; + + /** Creates new ExpPtg */ + + public ExpPtg() + { + } + + /** Creates new ExpPtg */ + + public ExpPtg(byte [] array, int offset) + { + } + + public void writeBytes(byte [] array, int offset) + { + } + + public int getSize() + { + return SIZE; + } + + public String toFormulaString() + { + return "NO IDEA SHARED FORMULA EXP PTG"; + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/FormulaUtil.java b/src/java/org/apache/poi/hssf/record/formula/FormulaUtil.java new file mode 100644 index 000000000..4e2e3fbe5 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/FormulaUtil.java @@ -0,0 +1,318 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * FormulaUtil.java + * + * Created on November 4, 2001, 5:50 AM + */ +package org.apache.poi.hssf.record.formula; + +/** + * + * @author andy + */ + +public class FormulaUtil +{ + + /** Creates new FormulaUtil */ + + public FormulaUtil() + { + } + + public static Ptg [] parseFormula(String formula) + { + Ptg[] ptg = null; + StringBuffer f = new StringBuffer(formula); + + if (isIntAddition(formula)) + { + int loc = getLoc(formula, '+'); + + System.out.println(formula.substring(0, loc).trim() + "," + + formula.substring(loc + 1, + formula.length()).trim()); + ptg = formulaAddTwoInts(Short + .parseShort(formula.substring(0, loc).trim()), Short + .parseShort(formula.substring(loc + 1, formula.length()) + .trim())); + } + else if (isIntSubtraction(formula)) + { + int loc = getLoc(formula, '-'); + + ptg = formulaSubtractTwoInts(Short + .parseShort(formula.substring(0, loc).trim()), Short + .parseShort(formula.substring(loc + 1, formula.length()) + .trim())); + } + else if (isIntMultiplication(formula)) + { + int loc = getLoc(formula, '*'); + + ptg = formulaMultiplyTwoInts(Short + .parseShort(formula.substring(0, loc).trim()), Short + .parseShort(formula.substring(loc + 1, formula.length()) + .trim())); + } + else if (isIntDivision(formula)) + { + int loc = getLoc(formula, '/'); + + ptg = formulaDivideTwoInts(Short + .parseShort(formula.substring(0, loc).trim()), Short + .parseShort(formula.substring(loc + 1, formula.length()) + .trim())); + } + else if (isIntPower(formula)) + { + int loc = getLoc(formula, '^'); + + ptg = formulaPowerTwoInts(Short + .parseShort(formula.substring(0, loc).trim()), Short + .parseShort(formula.substring(loc + 1, formula.length()) + .trim())); + } + return ptg; + } + + public static Ptg [] formulaAddTwoInts(short first, short second) + { + Ptg[] ptg = new Ptg[ 3 ]; + + ptg[ 0 ] = createInteger(first); + ptg[ 1 ] = createInteger(second); + ptg[ 2 ] = createAdd(); + return ptg; + } + + public static Ptg [] formulaSubtractTwoInts(short first, short second) + { + Ptg[] ptg = new Ptg[ 3 ]; + + ptg[ 0 ] = createInteger(first); + ptg[ 1 ] = createInteger(second); + ptg[ 2 ] = createSubtract(); + return ptg; + } + + public static Ptg [] formulaMultiplyTwoInts(short first, short second) + { + Ptg[] ptg = new Ptg[ 3 ]; + + ptg[ 0 ] = createInteger(first); + ptg[ 1 ] = createInteger(second); + ptg[ 2 ] = createMultiply(); + return ptg; + } + + public static Ptg [] formulaPowerTwoInts(short first, short second) + { + Ptg[] ptg = new Ptg[ 3 ]; + + ptg[ 0 ] = createInteger(second); + ptg[ 1 ] = createInteger(first); + ptg[ 2 ] = createPower(); + return ptg; + } + + public static Ptg [] formulaDivideTwoInts(short first, short second) + { + Ptg[] ptg = new Ptg[ 3 ]; + + ptg[ 0 ] = createInteger(first); + ptg[ 1 ] = createInteger(second); + ptg[ 2 ] = createDivide(); + return ptg; + } + + public static Ptg createInteger(short value) + { + IntPtg ptg = new IntPtg(); + + ptg.setValue(value); + return ptg; + } + + public static Ptg createAdd() + { + AddPtg ptg = new AddPtg(); + + return ptg; + } + + public static Ptg createSubtract() + { + SubtractPtg ptg = new SubtractPtg(); + + return ptg; + } + + public static Ptg createMultiply() + { + MultiplyPtg ptg = new MultiplyPtg(); + + return ptg; + } + + public static Ptg createDivide() + { + DividePtg ptg = new DividePtg(); + + return ptg; + } + + public static Ptg createPower() + { + PowerPtg ptg = new PowerPtg(); + + return ptg; + } + + private static boolean isIntAddition(String formula) + { + StringBuffer buffer = new StringBuffer(formula); + + if (instr(formula, "+")) + { + return true; + } + return false; + } + + private static boolean isIntSubtraction(String formula) + { + StringBuffer buffer = new StringBuffer(formula); + + if (instr(formula, "-")) + { + return true; + } + return false; + } + + private static boolean isIntMultiplication(String formula) + { + StringBuffer buffer = new StringBuffer(formula); + + if (instr(formula, "*")) + { + return true; + } + return false; + } + + private static boolean isIntDivision(String formula) + { + StringBuffer buffer = new StringBuffer(formula); + + if (instr(formula, "/")) + { + return true; + } + return false; + } + + private static boolean isIntPower(String formula) + { + StringBuffer buffer = new StringBuffer(formula); + + if (instr(formula, "^")) + { + return true; + } + return false; + } + + private static boolean instr(String matchin, String matchon) + { + int lenmatchin = matchin.length(); + int lenmatchon = matchon.length(); + int pos = 0; + + if (lenmatchon > lenmatchin) + { + return false; + } + while (pos + lenmatchon < lenmatchin) + { + String sub = matchin.substring(pos, pos + lenmatchon); + + if (sub.equals(matchon)) + { + return true; + } + pos++; + } + return false; + } + + private static int getLoc(String matchin, char matchon) + { + int retval = -1; + + for (int pos = 0; pos < matchin.length(); pos++) + { + if (matchin.charAt(pos) == matchon) + { + retval = pos; + break; + } + } + return retval; + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/IntPtg.java b/src/java/org/apache/poi/hssf/record/formula/IntPtg.java new file mode 100644 index 000000000..94e855774 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/IntPtg.java @@ -0,0 +1,114 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * IntPtg.java + * + * Created on October 29, 2001, 7:37 PM + */ +package org.apache.poi.hssf.record.formula; + +import org.apache.poi.util.LittleEndian; + +/** + * Integer (short intger) + * Stores a (java) short value in a formula + * @author andy + */ + +public class IntPtg + extends Ptg +{ + public final static int SIZE = 3; + public final static byte sid = 0x1e; + private short field_1_value; + + /** Creates new IntPtg */ + + public IntPtg() + { + } + + public IntPtg(byte [] data, int offset) + { + setValue(LittleEndian.getShort(data, offset + 1)); + } + + public void setValue(short value) + { + field_1_value = value; + } + + public short getValue() + { + return field_1_value; + } + + public void writeBytes(byte [] array, int offset) + { + array[ offset + 0 ] = sid; + LittleEndian.putShort(array, offset + 1, getValue()); + } + + public int getSize() + { + return SIZE; + } + + public String toFormulaString() + { + return "" + getValue(); + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/MemErrPtg.java b/src/java/org/apache/poi/hssf/record/formula/MemErrPtg.java new file mode 100644 index 000000000..88fd45fdf --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/MemErrPtg.java @@ -0,0 +1,123 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * MemErrPtg.java + * + * Created on November 21, 2001, 8:46 AM + */ +package org.apache.poi.hssf.record.formula; + +import org.apache.poi.util.LittleEndian; + +/** + * + * @author andy + */ + +public class MemErrPtg + extends Ptg +{ + public final static short sid = 0x27; + private final static int SIZE = 7; + private int field_1_reserved; + private short field_2_subex_len; + + /** Creates new MemErrPtg */ + + public MemErrPtg() + { + } + + public MemErrPtg(byte [] data, int offset) + { + field_1_reserved = LittleEndian.getInt(data, 0); + field_2_subex_len = LittleEndian.getShort(data, 4); + } + + public void setReserved(int res) + { + field_1_reserved = res; + } + + public int getReserved() + { + return field_1_reserved; + } + + public void setSubexpressionLength(short subexlen) + { + field_2_subex_len = subexlen; + } + + public short getSubexpressionLength() + { + return field_2_subex_len; + } + + public void writeBytes(byte [] array, int offset) + { + } + + public int getSize() + { + return SIZE; + } + + public String toFormulaString() + { + return "ERR#"; + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java b/src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java new file mode 100644 index 000000000..8dc1395f2 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java @@ -0,0 +1,121 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * MultiplyPtg.java + * + * Created on November 4, 2001, 8:26 PM + */ +package org.apache.poi.hssf.record.formula; + +/** + * + * @author andy + */ + +public class MultiplyPtg + extends Ptg + implements OperationPtg +{ + public final static int SIZE = 1; + public final static byte sid = 0x05; + + /** Creates new AddPtg */ + + public MultiplyPtg() + { + } + + public MultiplyPtg(byte [] data, int offset) + { + + // doesn't need anything + } + + public void writeBytes(byte [] array, int offset) + { + array[ offset + 0 ] = sid; + } + + public int getSize() + { + return SIZE; + } + + public int getType() + { + return TYPE_BINARY; + } + + public int getNumberOfOperands() + { + return 2; + } + + public String toFormulaString() + { + return "*"; + } + + public String toFormulaString(Ptg [] operands) + { + StringBuffer buffer = new StringBuffer(); + + buffer.append(operands[ 0 ].toFormulaString()); + buffer.append("*"); + buffer.append(operands[ 1 ].toFormulaString()); + return buffer.toString(); + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/NamePtg.java b/src/java/org/apache/poi/hssf/record/formula/NamePtg.java new file mode 100644 index 000000000..fd6a1c922 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/NamePtg.java @@ -0,0 +1,108 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * NamePtg.java + * + * Created on November 25, 2001, 3:30 PM + */ +package org.apache.poi.hssf.record.formula; + +import org.apache.poi.util.LittleEndian; + +/** + * + * @author andy + */ + +public class NamePtg + extends Ptg +{ + public final static short sid = 0x23; + private final static int SIZE = 7; + private short field_1_ixti; // unknown function + private short field_2_label_index; + private short field_3_zero; // reserved must be 0 + + /** Creates new NamePtg */ + + public NamePtg() + { + } + + /** Creates new NamePtg */ + + public NamePtg(byte [] data, int offset) + { + offset++; + field_1_ixti = LittleEndian.getShort(data, offset); + field_2_label_index = LittleEndian.getShort(data, offset + 2); + field_3_zero = LittleEndian.getShort(data, offset + 4); + } + + public void writeBytes(byte [] array, int offset) + { + } + + public int getSize() + { + return SIZE; + } + + public String toFormulaString() + { + return "NO IDEA - NAME"; + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java b/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java new file mode 100644 index 000000000..c598cfcfd --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java @@ -0,0 +1,79 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * OperationPtg.java + * + * Created on October 29, 2001, 7:53 PM + */ +package org.apache.poi.hssf.record.formula; + +/** + * defines a Ptg that is an operation instead of an operand + * @author andy + */ + +public interface OperationPtg +{ + public final static int TYPE_UNARY = 0; + public final static int TYPE_BINARY = 1; + public final static int TYPE_FUNCTION = 2; + + public int getType(); + + public int getNumberOfOperands(); + + public String toFormulaString(Ptg [] operands); +} diff --git a/src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java b/src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java new file mode 100644 index 000000000..104fd6586 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java @@ -0,0 +1,103 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * ParenthesisPtg.java + * + * Created on November 21, 2001, 6:42 PM + */ +package org.apache.poi.hssf.record.formula; + +/** + * Denotes that the previous operation (if just after an operation) or operand + * (if just after an operand) should appear in parenthesis. For display purposes only. + * + * @author andy + */ + +public class ParenthesisPtg + extends Ptg +{ + private final static int SIZE = 1; + public final static byte sid = 0x15; + + /** Creates new ParenthesisPtg */ + + public ParenthesisPtg() + { + } + + /** Creates new ParenthesisPtg */ + + public ParenthesisPtg(byte [] data, int offset) + { + + // doesn't read anything + } + + public void writeBytes(byte [] array, int offset) + { + } + + public int getSize() + { + return SIZE; + } + + public String toFormulaString() + { + return "()"; // bug...should be an operation? have a new "Cosmetic and unnecessary" interface? + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/PowerPtg.java b/src/java/org/apache/poi/hssf/record/formula/PowerPtg.java new file mode 100644 index 000000000..e5e61be9e --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/PowerPtg.java @@ -0,0 +1,121 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * PowerPtg.java + * + * Created on November 17, 2001, 12:51 PM + */ +package org.apache.poi.hssf.record.formula; + +/** + * + * @author andy + */ + +public class PowerPtg + extends Ptg + implements OperationPtg +{ + public final static int SIZE = 1; + public final static byte sid = 0x07; + + /** Creates new AddPtg */ + + public PowerPtg() + { + } + + public PowerPtg(byte [] data, int offset) + { + + // doesn't need anything + } + + public void writeBytes(byte [] array, int offset) + { + array[ offset + 0 ] = sid; + } + + public int getSize() + { + return SIZE; + } + + public int getType() + { + return TYPE_BINARY; + } + + public int getNumberOfOperands() + { + return 2; + } + + public String toFormulaString() + { + return "^"; + } + + public String toFormulaString(Ptg [] operands) + { + StringBuffer buffer = new StringBuffer(); + + buffer.append(operands[ 1 ].toFormulaString()); + buffer.append("^"); + buffer.append(operands[ 0 ].toFormulaString()); + return buffer.toString(); + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/Ptg.java b/src/java/org/apache/poi/hssf/record/formula/Ptg.java new file mode 100644 index 000000000..3deb3e441 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/Ptg.java @@ -0,0 +1,167 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * Ptg.java + * + * Created on October 28, 2001, 6:30 PM + */ +package org.apache.poi.hssf.record.formula; + +/** + * + * @author andy + */ + +public abstract class Ptg +{ + + /** Creates new Ptg */ + + public Ptg() + { + } + + public static Ptg createPtg(byte [] data, int offset) + { + byte id = data[ offset + 0 ]; + Ptg retval = null; + + System.out.println("PTG = " + Integer.toHexString(id) + " (" + id + + ")"); + switch (id) + { + + case AddPtg.sid : + retval = new AddPtg(data, offset); + break; + + case SubtractPtg.sid : + retval = new SubtractPtg(data, offset); + break; + + case IntPtg.sid : + retval = new IntPtg(data, offset); + break; + + case DividePtg.sid : + retval = new DividePtg(data, offset); + break; + + case MultiplyPtg.sid : + retval = new MultiplyPtg(data, offset); + break; + + case PowerPtg.sid : + retval = new PowerPtg(data, offset); + break; + + case AreaPtg.sid : + retval = new AreaPtg(data, offset); + break; + + case MemErrPtg.sid : + retval = new MemErrPtg(data, offset); + break; + + case AttrPtg.sid : + retval = new AttrPtg(data, offset); + break; + + case ValueReferencePtg.sid : + retval = new ValueReferencePtg(data, offset); + break; + + case ParenthesisPtg.sid : + retval = new ParenthesisPtg(data, offset); + break; + + case ValueVariableFunctionPtg.sid : + retval = new ValueVariableFunctionPtg(data, offset); + break; + + case NamePtg.sid : + retval = new NamePtg(data, offset); + break; + + case ExpPtg.sid : + retval = new ExpPtg(data, offset); + break; + + default : + + // retval = new UnknownPtg(); + throw new RuntimeException("Unknown PTG = " + + Integer.toHexString(( int ) id) + + " (" + ( int ) id + ")"); + } + return retval; + } + + public abstract int getSize(); + + public final byte [] getBytes() + { + int size = getSize(); + byte[] bytes = new byte[ size ]; + + writeBytes(bytes, 0); + return bytes; + } + + public abstract void writeBytes(byte [] array, int offset); + + public abstract String toFormulaString(); +} diff --git a/src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java b/src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java new file mode 100644 index 000000000..e9c70c834 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java @@ -0,0 +1,121 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * SubtractPtg.java + * + * Created on November 4, 2001, 6:48 PM + */ +package org.apache.poi.hssf.record.formula; + +/** + * + * @author andy + */ + +public class SubtractPtg + extends Ptg + implements OperationPtg +{ + public final static int SIZE = 1; + public final static byte sid = 0x04; + + /** Creates new AddPtg */ + + public SubtractPtg() + { + } + + public SubtractPtg(byte [] data, int offset) + { + + // doesn't need anything + } + + public void writeBytes(byte [] array, int offset) + { + array[ offset + 0 ] = sid; + } + + public int getSize() + { + return SIZE; + } + + public int getType() + { + return TYPE_BINARY; + } + + public int getNumberOfOperands() + { + return 2; + } + + public String toFormulaString() + { + return "-"; + } + + public String toFormulaString(Ptg [] operands) + { + StringBuffer buffer = new StringBuffer(); + + buffer.append(operands[ 0 ].toFormulaString()); + buffer.append("-"); + buffer.append(operands[ 1 ].toFormulaString()); + return buffer.toString(); + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/UnknownPtg.java b/src/java/org/apache/poi/hssf/record/formula/UnknownPtg.java new file mode 100644 index 000000000..b6d49a9e1 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/UnknownPtg.java @@ -0,0 +1,98 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * UnknownPtg.java + * + * Created on November 18, 2001, 1:22 PM + */ +package org.apache.poi.hssf.record.formula; + +/** + * + * @author andy + */ + +public class UnknownPtg + extends Ptg +{ + private short size; + + /** Creates new UnknownPtg */ + + public UnknownPtg() + { + } + + public UnknownPtg(byte [] data, int offset) + { + + // doesn't need anything + } + + public void writeBytes(byte [] array, int offset) + { + } + + public int getSize() + { + return size; + } + + public String toFormulaString() + { + return "UNKNOWN"; + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/ValueReferencePtg.java b/src/java/org/apache/poi/hssf/record/formula/ValueReferencePtg.java new file mode 100644 index 000000000..7270df95a --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/ValueReferencePtg.java @@ -0,0 +1,161 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * ValueReferencePtg.java + * + * Created on November 21, 2001, 5:27 PM + */ +package org.apache.poi.hssf.record.formula; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.BitField; + +/** + * + * @author andy + */ + +public class ValueReferencePtg + extends Ptg +{ + private final static int SIZE = 5; + public final static byte sid = 0x44; + private short field_1_row; + private short field_2_col; + private BitField rowRelative = new BitField(0x8000); + private BitField colRelative = new BitField(0x4000); + + /** Creates new ValueReferencePtg */ + + public ValueReferencePtg() + { + } + + /** Creates new ValueReferencePtg */ + + public ValueReferencePtg(byte [] data, int offset) + { + offset++; // adjust for ptg + field_1_row = LittleEndian.getShort(data, offset + 0); + field_2_col = LittleEndian.getShort(data, offset + 2); + System.out.println(toString()); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer("[ValueReferencePtg]\n"); + + buffer.append("row = ").append(getRow()).append("\n"); + buffer.append("col = ").append(getColumnRaw()).append("\n"); + buffer.append("rowrelative = ").append(isRowRelative()).append("\n"); + buffer.append("colrelative = ").append(isColRelative()).append("\n"); + return buffer.toString(); + } + + public void writeBytes(byte [] array, int offset) + { + } + + public void setRow(short row) + { + field_1_row = row; + } + + public short getRow() + { + return field_1_row; + } + + public boolean isRowRelative() + { + return rowRelative.isSet(field_2_col); + } + + public boolean isColRelative() + { + return rowRelative.isSet(field_2_col); + } + + public void setColumnRaw(short col) + { + field_2_col = col; + } + + public short getColumnRaw() + { + return field_2_col; + } + + public void setColumn(short col) + { + field_2_col = col; // fix this + } + + public short getColumn() + { + return field_2_col; // fix this + } + + public int getSize() + { + return SIZE; + } + + public String toFormulaString() + { + return "NO IDEA YET VALUE REF"; + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java b/src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java new file mode 100644 index 000000000..84dcb51bd --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java @@ -0,0 +1,130 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * ValueVariableFunctionPtg.java + * + * Created on November 21, 2001, 7:02 PM + */ +package org.apache.poi.hssf.record.formula; + +import org.apache.poi.util.BitField; +import org.apache.poi.util.LittleEndian; + +/** + * An excel function with variable number of value arguments. + * @author andy + */ + +public class ValueVariableFunctionPtg + extends Ptg + implements OperationPtg +{ + public final static short sid = 0x42; + private final static short SIZE = 4; + private byte field_1_byte_1; + BitField numArgs = new BitField(0x7f); + BitField prompt = new BitField(0x80); + private short field_2_bytes; + BitField functionIndex = new BitField(0x7FFF); + BitField command = new BitField(0x8000); + + /** Creates new ValueVariableFunctionPtg */ + + public ValueVariableFunctionPtg() + { + } + + public ValueVariableFunctionPtg(byte [] data, int offset) + { + offset++; + field_1_byte_1 = data[ offset + 0 ]; + field_2_bytes = LittleEndian.getShort(data, offset + 1); + } + + public void writeBytes(byte [] array, int offset) + { + } + + public int getSize() + { + return SIZE; + } + + public short getNumArgs() + { + return numArgs.getShortValue(field_1_byte_1); + } + + public int getNumberOfOperands() + { + return getNumArgs(); + } + + public int getType() + { + return -1; + } + + public String toFormulaString() + { + return "NO IDEA YET VALUE VARIABLE"; + } + + public String toFormulaString(Ptg [] operands) + { + return toFormulaString(); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java new file mode 100644 index 000000000..a8027af26 --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -0,0 +1,861 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * Cell.java + * + * Created on September 30, 2001, 3:46 PM + */ +package org.apache.poi.hssf.usermodel; + +import org.apache.poi.hssf.model.Workbook; +import org.apache.poi.hssf.model.Sheet; +import org.apache.poi.hssf.record.CellValueRecordInterface; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.FormulaRecord; +import org.apache.poi.hssf.record.LabelSSTRecord; +import org.apache.poi.hssf.record.NumberRecord; +import org.apache.poi.hssf.record.BlankRecord; +import org.apache.poi.hssf.record.BoolErrRecord; +import org.apache.poi.hssf.record.ExtendedFormatRecord; + +/** + * High level representation of a cell in a row of a spreadsheet. + * Cells can be numeric, formula-based or string-based (text). The cell type + * specifies this. String cells cannot conatin numbers and numeric cells cannot + * contain strings (at least according to our model). Client apps should do the + * conversions themselves. Formula cells are treated like string cells, simply + * containing a formula string. They'll be rendered differently. + * + * Cells should have their number (0 based) before being added to a row. Only + * cells that have values should be added. + * + * NOTE: the alpha won't be implementing formulas + * + * @author Andrew C. Oliver (acoliver at apache dot org) + * @version 1.0-pre + */ + +public class HSSFCell +{ + + /** + * Numeric Cell type (0) + * @see #setCellType(int) + * @see #getCellType() + */ + + public final static int CELL_TYPE_NUMERIC = 0; + + /** + * String Cell type (1) + * @see #setCellType(int) + * @see #getCellType() + */ + + public final static int CELL_TYPE_STRING = 1; + + /** + * Formula Cell type (2) + * @see #setCellType(int) + * @see #getCellType() + */ + + public final static int CELL_TYPE_FORMULA = 2; + + /** + * Blank Cell type (3) + * @see #setCellType(int) + * @see #getCellType() + */ + + public final static int CELL_TYPE_BLANK = 3; + + /** + * Boolean Cell type (4) + * @see #setCellType(int) + * @see #getCellType() + */ + + public final static int CELL_TYPE_BOOLEAN = 4; + + /** + * Error Cell type (5) + * @see #setCellType(int) + * @see #getCellType() + */ + + public final static int CELL_TYPE_ERROR = 5; + public final static short ENCODING_COMPRESSED_UNICODE = 0; + public final static short ENCODING_UTF_16 = 1; + private short cellNum; + private int cellType; + private HSSFCellStyle cellStyle; + private double cellValue; + private String stringValue; + private boolean booleanValue; + private byte errorValue; + private short encoding; + private Workbook book; + private Sheet sheet; + private short row; + private CellValueRecordInterface record; + + /** + * Creates new Cell - Should only be called by HSSFRow. This creates a cell + * from scratch. + *

+ * When the cell is initially created it is set to CELL_TYPE_BLANK. Cell types + * can be changed/overwritten by calling setCellValue with the appropriate + * type as a parameter although conversions from one type to another may be + * prohibited. + * + * @param book - Workbook record of the workbook containing this cell + * @param sheet - Sheet record of the sheet containing this cell + * @param row - the row of this cell + * @param col - the column for this cell + * + * @see org.apache.poi.hssf.usermodel.HSSFRow#createCell(short) + */ + + protected HSSFCell(Workbook book, Sheet sheet, short row, short col) + { + cellNum = col; + this.row = row; + cellStyle = null; + cellValue = 0; + stringValue = null; + booleanValue = false; + errorValue = ( byte ) 0; + this.book = book; + this.sheet = sheet; + + // Relying on the fact that by default the cellType is set to 0 which + // is different to CELL_TYPE_BLANK hence the following method call correctly + // creates a new blank cell. + setCellType(CELL_TYPE_BLANK, false); + ExtendedFormatRecord xf = book.getExFormatAt(0xf); + + setCellStyle(new HSSFCellStyle(( short ) 0xf, xf)); + } + + /** + * Creates new Cell - Should only be called by HSSFRow. This creates a cell + * from scratch. + * + * @param book - Workbook record of the workbook containing this cell + * @param sheet - Sheet record of the sheet containing this cell + * @param row - the row of this cell + * @param col - the column for this cell + * @param type - CELL_TYPE_NUMERIC, CELL_TYPE_STRING, CELL_TYPE_FORMULA, CELL_TYPE_BLANK, + * CELL_TYPE_BOOLEAN, CELL_TYPE_ERROR + * Type of cell + * @see org.apache.poi.hssf.usermodel.HSSFRow#createCell(short,int) + * @deprecated As of 22-Jan-2002 use @see org.apache.poi.hssf.usermodel.HSSFRow#createCell(short) + * and use setCellValue to specify the type lazily. + */ + + protected HSSFCell(Workbook book, Sheet sheet, short row, short col, + int type) + { + cellNum = col; + this.row = row; + cellType = type; + cellStyle = null; + cellValue = 0; + stringValue = null; + booleanValue = false; + errorValue = ( byte ) 0; + this.book = book; + this.sheet = sheet; + switch (type) + { + + case CELL_TYPE_NUMERIC : + record = new NumberRecord(); + (( NumberRecord ) record).setColumn(col); + (( NumberRecord ) record).setRow(row); + (( NumberRecord ) record).setValue(( short ) 0); + (( NumberRecord ) record).setXFIndex(( short ) 0); + break; + + case CELL_TYPE_STRING : + record = new LabelSSTRecord(); + (( LabelSSTRecord ) record).setColumn(col); + (( LabelSSTRecord ) record).setRow(row); + (( LabelSSTRecord ) record).setXFIndex(( short ) 0); + break; + + case CELL_TYPE_BLANK : + record = new BlankRecord(); + (( BlankRecord ) record).setColumn(col); + (( BlankRecord ) record).setRow(row); + (( BlankRecord ) record).setXFIndex(( short ) 0); + break; + + case CELL_TYPE_FORMULA : + record = new FormulaRecord(); + (( FormulaRecord ) record).setColumn(col); + (( FormulaRecord ) record).setRow(row); + (( FormulaRecord ) record).setXFIndex(( short ) 0); + case CELL_TYPE_BOOLEAN : + record = new BoolErrRecord(); + (( BoolErrRecord ) record).setColumn(col); + (( BoolErrRecord ) record).setRow(row); + (( BoolErrRecord ) record).setXFIndex(( short ) 0); + (( BoolErrRecord ) record).setValue(false); + break; + + case CELL_TYPE_ERROR : + record = new BoolErrRecord(); + (( BoolErrRecord ) record).setColumn(col); + (( BoolErrRecord ) record).setRow(row); + (( BoolErrRecord ) record).setXFIndex(( short ) 0); + (( BoolErrRecord ) record).setValue(( byte ) 0); + break; + } + ExtendedFormatRecord xf = book.getExFormatAt(0xf); + + setCellStyle(new HSSFCellStyle(( short ) 0xf, xf)); + } + + /** + * Creates an HSSFCell from a CellValueRecordInterface. HSSFSheet uses this when + * reading in cells from an existing sheet. + * + * @param book - Workbook record of the workbook containing this cell + * @param sheet - Sheet record of the sheet containing this cell + * @param cval - the Cell Value Record we wish to represent + */ + + protected HSSFCell(Workbook book, Sheet sheet, short row, + CellValueRecordInterface cval) + { + cellNum = cval.getColumn(); + record = cval; + this.row = row; + cellType = determineType(cval); + cellStyle = null; + stringValue = null; + this.book = book; + this.sheet = sheet; + switch (cellType) + { + + case CELL_TYPE_NUMERIC : + cellValue = (( NumberRecord ) cval).getValue(); + break; + + case CELL_TYPE_STRING : + stringValue = + book + .getSSTString((( LabelSSTRecord ) cval).getSSTIndex()); + break; + + case CELL_TYPE_BLANK : + break; + + case CELL_TYPE_FORMULA : + cellValue = (( FormulaRecord ) cval).getValue(); + break; + + case CELL_TYPE_BOOLEAN : + booleanValue = (( BoolErrRecord ) cval).getBooleanValue(); + break; + + case CELL_TYPE_ERROR : + errorValue = (( BoolErrRecord ) cval).getErrorValue(); + break; + } + ExtendedFormatRecord xf = book.getExFormatAt(cval.getXFIndex()); + + setCellStyle(new HSSFCellStyle(( short ) cval.getXFIndex(), xf)); + } + + /** + * private constructor to prevent blank construction + */ + + private HSSFCell() + { + } + ; + + /** + * used internally -- given a cell value record, figure out its type + */ + + private int determineType(CellValueRecordInterface cval) + { + Record record = ( Record ) cval; + int sid = record.getSid(); + int retval = 0; + + switch (sid) + { + + case NumberRecord.sid : + retval = HSSFCell.CELL_TYPE_NUMERIC; + break; + + case BlankRecord.sid : + retval = HSSFCell.CELL_TYPE_BLANK; + break; + + case LabelSSTRecord.sid : + retval = HSSFCell.CELL_TYPE_STRING; + break; + + case FormulaRecord.sid : + retval = HSSFCell.CELL_TYPE_FORMULA; + break; + + case BoolErrRecord.sid : + BoolErrRecord boolErrRecord = ( BoolErrRecord ) record; + + retval = (boolErrRecord.isBoolean()) + ? HSSFCell.CELL_TYPE_BOOLEAN + : HSSFCell.CELL_TYPE_ERROR; + break; + } + return retval; + } + + /** + * set the cell's number within the row (0 based) + * @param short the cell number + */ + + public void setCellNum(short num) + { + cellNum = num; + record.setColumn(num); + } + + /** + * get the cell's number within the row + * @return short reperesenting the column number (logical!) + */ + + public short getCellNum() + { + return cellNum; + } + + /** + * set the cells type (numeric, formula or string) -- DONT USE FORMULAS IN THIS RELEASE + * WE'LL THROW YOU A RUNTIME EXCEPTION IF YOU DO + * @see #CELL_TYPE_NUMERIC + * @see #CELL_TYPE_STRING + * @see #CELL_TYPE_FORMULA + * @see #CELL_TYPE_BLANK + * @see #CELL_TYPE_BOOLEAN + * @see #CELL_TYPE_ERROR + */ + + public void setCellType(int cellType) + { + setCellType(cellType, true); + } + + /** + * sets the cell type. The setValue flag indicates whether to bother about + * trying to preserve the current value in the new record if one is created. + *

+ * The @see #setCellValue method will call this method with false in setValue + * since it will overwrite the cell value later + * + */ + + private void setCellType(int cellType, boolean setValue) + { + + // if (cellType == CELL_TYPE_FORMULA) + // { + // throw new RuntimeException( + // "Formulas have not been implemented in this release"); + // } + if (cellType > CELL_TYPE_ERROR) + { + throw new RuntimeException("I have no idea what type that is!"); + } + switch (cellType) + { + + case CELL_TYPE_FORMULA : + FormulaRecord frec = null; + + if (cellType != this.cellType) + { + frec = new FormulaRecord(); + } + else + { + frec = ( FormulaRecord ) record; + } + frec.setColumn(getCellNum()); + if (setValue) + { + frec.setValue(getNumericCellValue()); + } + frec.setXFIndex(( short ) cellStyle.getIndex()); + frec.setRow(row); + record = frec; + break; + + case CELL_TYPE_NUMERIC : + NumberRecord nrec = null; + + if (cellType != this.cellType) + { + nrec = new NumberRecord(); + } + else + { + nrec = ( NumberRecord ) record; + } + nrec.setColumn(getCellNum()); + if (setValue) + { + nrec.setValue(getNumericCellValue()); + } + nrec.setXFIndex(( short ) cellStyle.getIndex()); + nrec.setRow(row); + record = nrec; + break; + + case CELL_TYPE_STRING : + LabelSSTRecord lrec = null; + + if (cellType != this.cellType) + { + lrec = new LabelSSTRecord(); + } + else + { + lrec = ( LabelSSTRecord ) record; + } + lrec.setColumn(getCellNum()); + lrec.setRow(row); + lrec.setXFIndex(( short ) cellStyle.getIndex()); + if (setValue) + { + if ((getStringCellValue() != null) + && (!getStringCellValue().equals(""))) + { + int sst = 0; + + if (encoding == ENCODING_COMPRESSED_UNICODE) + { + sst = book.addSSTString(getStringCellValue()); + } + if (encoding == ENCODING_UTF_16) + { + sst = book.addSSTString(getStringCellValue(), + true); + } + lrec.setSSTIndex(sst); + } + } + record = lrec; + break; + + case CELL_TYPE_BLANK : + BlankRecord brec = null; + + if (cellType != this.cellType) + { + brec = new BlankRecord(); + } + else + { + brec = ( BlankRecord ) record; + } + brec.setColumn(getCellNum()); + + // During construction the cellStyle may be null for a Blank cell. + if (cellStyle != null) + { + brec.setXFIndex(( short ) cellStyle.getIndex()); + } + else + { + brec.setXFIndex(( short ) 0); + } + brec.setRow(row); + record = brec; + break; + + case CELL_TYPE_BOOLEAN : + BoolErrRecord boolRec = null; + + if (cellType != this.cellType) + { + boolRec = new BoolErrRecord(); + } + else + { + boolRec = ( BoolErrRecord ) record; + } + boolRec.setColumn(getCellNum()); + if (setValue) + { + boolRec.setValue(getBooleanCellValue()); + } + boolRec.setXFIndex(( short ) cellStyle.getIndex()); + boolRec.setRow(row); + record = boolRec; + break; + + case CELL_TYPE_ERROR : + BoolErrRecord errRec = null; + + if (cellType != this.cellType) + { + errRec = new BoolErrRecord(); + } + else + { + errRec = ( BoolErrRecord ) record; + } + errRec.setColumn(getCellNum()); + if (setValue) + { + errRec.setValue(getErrorCellValue()); + } + errRec.setXFIndex(( short ) cellStyle.getIndex()); + errRec.setRow(row); + record = errRec; + break; + } + if (cellType != this.cellType) + { + int loc = sheet.getLoc(); + + sheet.replaceValueRecord(record); + sheet.setLoc(loc); + } + this.cellType = cellType; + } + + /** + * get the cells type (numeric, formula or string) + * @see #CELL_TYPE_STRING + * @see #CELL_TYPE_NUMERIC + * @see #CELL_TYPE_FORMULA + * @see #CELL_TYPE_BOOLEAN + * @see #CELL_TYPE_ERROR + */ + + public int getCellType() + { + return cellType; + } + + /** + * set a numeric value for the cell + * + * @param double the numeric value to set this cell to. For formulas we'll set the + * precalculated value, for numerics we'll set its value. For other types we + * will change the cell to a numeric cell and set its value. + */ + + public void setCellValue(double value) + { + if ((cellType != CELL_TYPE_NUMERIC) + && (cellType != CELL_TYPE_FORMULA)) + { + setCellType(CELL_TYPE_NUMERIC, false); + } + (( NumberRecord ) record).setValue(value); + cellValue = value; + } + + /** + * set a string value for the cell. + * + * @param String value to set the cell to. For formulas we'll set the formula + * string, for String cells we'll set its value. For other types we will + * change the cell to a string cell and set its value. + * If value is null then we will change the cell to a Blank cell. + */ + + public void setCellValue(String value) + { + if (value == null) + { + setCellType(CELL_TYPE_BLANK, false); + } + else + { + if ((cellType != CELL_TYPE_STRING) + && (cellType != CELL_TYPE_FORMULA)) + { + setCellType(CELL_TYPE_STRING, false); + } + int index = 0; + + if (encoding == ENCODING_COMPRESSED_UNICODE) + { + index = book.addSSTString(value); + } + if (encoding == ENCODING_UTF_16) + { + index = book.addSSTString(value, true); + } + (( LabelSSTRecord ) record).setSSTIndex(index); + stringValue = value; + } + } + + /** + * get the value of the cell as a number. For strings we throw an exception. + * For blank cells we return a 0. + */ + + public double getNumericCellValue() + { + if (cellType == CELL_TYPE_BLANK) + { + return 0; + } + if (cellType == CELL_TYPE_STRING) + { + throw new NumberFormatException( + "You cannot get a numeric value from a String based cell"); + } + if (cellType == CELL_TYPE_BOOLEAN) + { + throw new NumberFormatException( + "You cannot get a numeric value from a boolean cell"); + } + if (cellType == CELL_TYPE_ERROR) + { + throw new NumberFormatException( + "You cannot get a numeric value from an error cell"); + } + return cellValue; + } + + /** + * get the value of the cell as a string - for numeric cells we throw an exception. + * For blank cells we return an empty string. + */ + + public String getStringCellValue() + { + if (cellType == CELL_TYPE_BLANK) + { + return ""; + } + if (cellType == CELL_TYPE_NUMERIC) + { + throw new NumberFormatException( + "You cannot get a string value from a numeric cell"); + } + if (cellType == CELL_TYPE_BOOLEAN) + { + throw new NumberFormatException( + "You cannot get a string value from a boolean cell"); + } + if (cellType == CELL_TYPE_ERROR) + { + throw new NumberFormatException( + "You cannot get a string value from an error cell"); + } + return stringValue; + } + + /** + * set a boolean value for the cell + * + * @param value the boolean value to set this cell to. For formulas we'll set the + * precalculated value, for booleans we'll set its value. For other types we + * will change the cell to a boolean cell and set its value. + */ + + public void setCellValue(boolean value) + { + if ((cellType != CELL_TYPE_BOOLEAN) + && (cellType != CELL_TYPE_FORMULA)) + { + setCellType(CELL_TYPE_BOOLEAN, false); + } + (( BoolErrRecord ) record).setValue(value); + booleanValue = value; + } + + /** + * set a error value for the cell + * + * @param value the error value to set this cell to. For formulas we'll set the + * precalculated value ??? IS THIS RIGHT??? , for errors we'll set + * its value. For other types we will change the cell to an error + * cell and set its value. + */ + + public void setCellErrorValue(byte value) + { + if ((cellType != CELL_TYPE_ERROR) && (cellType != CELL_TYPE_FORMULA)) + { + setCellType(CELL_TYPE_ERROR, false); + } + (( BoolErrRecord ) record).setValue(value); + errorValue = value; + } + + /** + * get the value of the cell as a boolean. For strings, numbers, and errors, we throw an exception. + * For blank cells we return a false. + */ + + public boolean getBooleanCellValue() + { + if (cellType == CELL_TYPE_BOOLEAN) + { + return booleanValue; + } + if (cellType == CELL_TYPE_BLANK) + { + return false; + } + throw new NumberFormatException( + "You cannot get a boolean value from a non-boolean cell"); + } + + /** + * get the value of the cell as an error code. For strings, numbers, and booleans, we throw an exception. + * For blank cells we return a 0. + */ + + public byte getErrorCellValue() + { + if (cellType == CELL_TYPE_ERROR) + { + return errorValue; + } + if (cellType == CELL_TYPE_BLANK) + { + return ( byte ) 0; + } + throw new NumberFormatException( + "You cannot get an error value from a non-error cell"); + } + + /** + * set the style for the cell. The style should be an HSSFCellStyle created/retreived from + * the HSSFWorkbook. + * + * @param HSSFCellStyle reference contained in the workbook + * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#createCellStyle() + * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getCellStyleAt(short) + */ + + public void setCellStyle(HSSFCellStyle style) + { + cellStyle = style; + record.setXFIndex(style.getIndex()); + } + + /** + * get the style for the cell. This is a reference to a cell style contained in the workbook + * object. + * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getCellStyleAt(short) + */ + + public HSSFCellStyle getCellStyle() + { + return cellStyle; + } + + /** + * used for internationalization, currently 0 for compressed unicode or 1 for 16-bit + * + * @see #ENCODING_COMPRESSED_UNICODE + * @see #ENCODING_UTF_16 + * + * @return 1 or 0 for compressed or uncompressed (used only with String type) + */ + + public short getEncoding() + { + return encoding; + } + + /** + * set the encoding to either 8 or 16 bit. (US/UK use 8-bit, rest of the western world use 16bit) + * + * @see #ENCODING_COMPRESSED_UNICODE + * @see #ENCODING_UTF_16 + * + * @param encoding either ENCODING_COMPRESSED_UNICODE (0) or ENCODING_UTF_16 (1) + */ + + public void setEncoding(short encoding) + { + this.encoding = encoding; + } + + /** + * Should only be used by HSSFSheet and friends. Returns the low level CellValueRecordInterface record + * + * @return CellValueRecordInterface representing the cell via the low level api. + */ + + protected CellValueRecordInterface getCellValueRecord() + { + return record; + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java new file mode 100644 index 000000000..373d11bad --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java @@ -0,0 +1,815 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * HSSFCellStyle.java + * + * Created on September 30, 2001, 3:47 PM + */ +package org.apache.poi.hssf.usermodel; + +import org.apache.poi.hssf.record.ExtendedFormatRecord; + +/** + * High level representation of the style of a cell in a sheet of a workbook. + * + * @version 1.0-pre + * + * @author Andrew C. Oliver (acoliver at apache dot org) + * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#createCellStyle() + * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getCellStyleAt(short) + * @see org.apache.poi.hssf.usermodel.HSSFCell#setCellStyle(HSSFCellStyle) + */ + +public class HSSFCellStyle + implements HSSFColorConstants +{ + private ExtendedFormatRecord format = null; + private short index = 0; + private short fontindex = 0; + + /** + * general (normal) horizontal alignment + */ + + public final static short ALIGN_GENERAL = 0x0; + + /** + * left-justified horizontal alignment + */ + + public final static short ALIGN_LEFT = 0x1; + + /** + * center horizontal alignment + */ + + public final static short ALIGN_CENTER = 0x2; + + /** + * right-justified horizontal alignment + */ + + public final static short ALIGN_RIGHT = 0x3; + + /** + * fill? horizontal alignment + */ + + public final static short ALIGN_FILL = 0x4; + + /** + * justified horizontal alignment + */ + + public final static short ALIGN_JUSTIFY = 0x5; + + /** + * center-selection? horizontal alignment + */ + + public final static short ALIGN_CENTER_SELECTION = 0x6; + + /** + * top-aligned vertical alignment + */ + + public final static short VERTICAL_TOP = 0x0; + + /** + * center-aligned vertical alignment + */ + + public final static short VERTICAL_CENTER = 0x1; + + /** + * bottom-aligned vertical alignment + */ + + public final static short VERTICAL_BOTTOM = 0x2; + + /** + * vertically justified vertical alignment + */ + + public final static short VERTICAL_JUSTIFY = 0x3; + + /** + * No border + */ + + public final static short BORDER_NONE = 0x0; + + /** + * Thin border + */ + + public final static short BORDER_THIN = 0x1; + + /** + * Medium border + */ + + public final static short BORDER_MEDIUM = 0x2; + + /** + * dash border + */ + + public final static short BORDER_DASHED = 0x3; + + /** + * dot border + */ + + public final static short BORDER_DOTTED = 0x4; + + /** + * Thick border + */ + + public final static short BORDER_THICK = 0x5; + + /** + * double-line border + */ + + public final static short BORDER_DOUBLE = 0x6; + + /** + * hair-line border + */ + + public final static short BORDER_HAIR = 0x7; + + /** + * Medium dashed border + */ + + public final static short BORDER_MEDIUM_DASHED = 0x8; + + /** + * dash-dot border + */ + + public final static short BORDER_DASH_DOT = 0x9; + + /** + * medium dash-dot border + */ + + public final static short BORDER_MEDIUM_DASH_DOT = 0xA; + + /** + * dash-dot-dot border + */ + + public final static short BORDER_DASH_DOT_DOT = 0xB; + + /** + * medium dash-dot-dot border + */ + + public final static short BORDER_MEDIUM_DASH_DOT_DOT = 0xC; + + /** + * slanted dash-dot border + */ + + public final static short BORDER_SLANTED_DASH_DOT = 0xD; + + /** Creates new HSSFCellStyle why would you want to do this?? */ + + protected HSSFCellStyle(short index, ExtendedFormatRecord rec) + { + this.index = index; + format = rec; + } + + /** + * get the index within the HSSFWorkbook (sequence within the collection of ExtnededFormat objects) + * @return unique index number of the underlying record this style represents (probably you don't care + * unless you're comparing which one is which) + */ + + public short getIndex() + { + return index; + } + + /** + * set the data format (only builtin formats are supported) + * @see org.apache.poi.hssf.usermodel.HSSFDataFormat + */ + + public void setDataFormat(short fmt) + { + format.setFormatIndex(fmt); + } + + /** + * get the index of the built in format + * @see org.apache.poi.hssf.usermodel.HSSFDataFormat + */ + + public short getDataFormat() + { + return format.getFormatIndex(); + } + + /** + * set the font for this style + * @param a font object created or retreived from the HSSFWorkbook object + * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#createFont() + * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getFontAt(short) + */ + + public void setFont(HSSFFont font) + { + format.setIndentNotParentFont(true); + fontindex = font.getIndex(); + format.setFontIndex(fontindex); + } + + public short getFontIndex() + { + return format.getFontIndex(); + } + + /** + * set the cell's using this style to be hidden + * @param hidden - whether the cell using this style should be hidden + */ + + public void setHidden(boolean hidden) + { + format.setIndentNotParentCellOptions(true); + format.setHidden(hidden); + } + + /** + * get whether the cell's using this style are to be hidden + * @return hidden - whether the cell using this style should be hidden + */ + + public boolean getHidden() + { + return format.isHidden(); + } + + /** + * set the cell's using this style to be locked + * @param locked - whether the cell using this style should be locked + */ + + public void setLocked(boolean locked) + { + format.setIndentNotParentCellOptions(true); + format.setLocked(locked); + } + + /** + * get whether the cell's using this style are to be locked + * @return hidden - whether the cell using this style should be locked + */ + + public boolean getLocked() + { + return format.isLocked(); + } + + /** + * set the type of horizontal alignment for the cell + * @param align - the type of alignment + * @see #ALIGN_GENERAL + * @see #ALIGN_LEFT + * @see #ALIGN_CENTER + * @see #ALIGN_RIGHT + * @see #ALIGN_FILL + * @see #ALIGN_JUSTIFY + * @see #ALIGN_CENTER_SELECTION + */ + + public void setAlignment(short align) + { + format.setIndentNotParentAlignment(true); + format.setAlignment(align); + } + + /** + * get the type of horizontal alignment for the cell + * @return align - the type of alignment + * @see #ALIGN_GENERAL + * @see #ALIGN_LEFT + * @see #ALIGN_CENTER + * @see #ALIGN_RIGHT + * @see #ALIGN_FILL + * @see #ALIGN_JUSTIFY + * @see #ALIGN_CENTER_SELECTION + */ + + public short getAlignment() + { + return format.getAlignment(); + } + + /** + * get whether this cell is to be part of a merged block of cells + * + * @returns merged or not + */ + + public boolean getMergeCells() + { + return format.getMergeCells(); + } + + /** + * set whether this cell is to be part of a merged block of cells + * + * @param merged or not + */ + + public void setMergeCells(boolean merge) + { + format.setMergeCells(merge); + } + + /** + * set whether the text should be wrapped + * @param wrap text or not + */ + + public void setWrapText(boolean wrapped) + { + format.setIndentNotParentAlignment(true); + format.setWrapText(wrapped); + } + + /** + * get whether the text should be wrapped + * @return wrap text or not + */ + + public boolean getWrapText() + { + return format.getWrapText(); + } + + /** + * set the type of vertical alignment for the cell + * @param align - the type of alignment + * @see #VERTICAL_TOP + * @see #VERTICAL_CENTER + * @see #VERTICAL_BOTTOM + * @see #VERTICAL_JUSTIFY + */ + + public void setVerticalAlignment(short align) + { + format.setVerticalAlignment(align); + } + + /** + * get the type of vertical alignment for the cell + * @return align - the type of alignment + * @see #VERTICAL_TOP + * @see #VERTICAL_CENTER + * @see #VERTICAL_BOTTOM + * @see #VERTICAL_JUSTIFY + */ + + public short getVerticalAlignment() + { + return format.getVerticalAlignment(); + } + + /** + * set the degree of rotation for the text in the cell + * @param rotation degrees + */ + + public void setRotation(short rotation) + { + format.setRotation(rotation); + } + + /** + * get the degree of rotation for the text in the cell + * @return rotation degrees + */ + + public short getRotation() + { + return format.getRotation(); + } + + /** + * set the number of spaces to indent the text in the cell + * @param indent - number of spaces + */ + + public void setIndention(short indent) + { + format.setIndent(indent); + } + + /** + * get the number of spaces to indent the text in the cell + * @return indent - number of spaces + */ + + public short getIndention() + { + return format.getIndent(); + } + + /** + * set the type of border to use for the left border of the cell + * @param border type + * @see #BORDER_NONE + * @see #BORDER_THIN + * @see #BORDER_MEDIUM + * @see #BORDER_DASHED + * @see #BORDER_DOTTED + * @see #BORDER_THICK + * @see #BORDER_DOUBLE + * @see #BORDER_HAIR + * @see #BORDER_MEDIUM_DASHED + * @see #BORDER_DASH_DOT + * @see #BORDER_MEDIUM_DASH_DOT + * @see #BORDER_DASH_DOT_DOT + * @see #BORDER_MEDIUM_DASH_DOT_DOT + * @see #BORDER_SLANTED_DASH_DOT + */ + + public void setBorderLeft(short border) + { + format.setIndentNotParentBorder(true); + format.setBorderLeft(border); + } + + /** + * get the type of border to use for the left border of the cell + * @return border type + * @see #BORDER_NONE + * @see #BORDER_THIN + * @see #BORDER_MEDIUM + * @see #BORDER_DASHED + * @see #BORDER_DOTTED + * @see #BORDER_THICK + * @see #BORDER_DOUBLE + * @see #BORDER_HAIR + * @see #BORDER_MEDIUM_DASHED + * @see #BORDER_DASH_DOT + * @see #BORDER_MEDIUM_DASH_DOT + * @see #BORDER_DASH_DOT_DOT + * @see #BORDER_MEDIUM_DASH_DOT_DOT + * @see #BORDER_SLANTED_DASH_DOT + */ + + public short getBorderLeft() + { + return format.getBorderLeft(); + } + + /** + * set the type of border to use for the right border of the cell + * @param border type + * @see #BORDER_NONE + * @see #BORDER_THIN + * @see #BORDER_MEDIUM + * @see #BORDER_DASHED + * @see #BORDER_DOTTED + * @see #BORDER_THICK + * @see #BORDER_DOUBLE + * @see #BORDER_HAIR + * @see #BORDER_MEDIUM_DASHED + * @see #BORDER_DASH_DOT + * @see #BORDER_MEDIUM_DASH_DOT + * @see #BORDER_DASH_DOT_DOT + * @see #BORDER_MEDIUM_DASH_DOT_DOT + * @see #BORDER_SLANTED_DASH_DOT + */ + + public void setBorderRight(short border) + { + format.setIndentNotParentBorder(true); + format.setBorderRight(border); + } + + /** + * get the type of border to use for the right border of the cell + * @return border type + * @see #BORDER_NONE + * @see #BORDER_THIN + * @see #BORDER_MEDIUM + * @see #BORDER_DASHED + * @see #BORDER_DOTTED + * @see #BORDER_THICK + * @see #BORDER_DOUBLE + * @see #BORDER_HAIR + * @see #BORDER_MEDIUM_DASHED + * @see #BORDER_DASH_DOT + * @see #BORDER_MEDIUM_DASH_DOT + * @see #BORDER_DASH_DOT_DOT + * @see #BORDER_MEDIUM_DASH_DOT_DOT + * @see #BORDER_SLANTED_DASH_DOT + */ + + public short getBorderRight() + { + return format.getBorderRight(); + } + + /** + * set the type of border to use for the top border of the cell + * @param border type + * @see #BORDER_NONE + * @see #BORDER_THIN + * @see #BORDER_MEDIUM + * @see #BORDER_DASHED + * @see #BORDER_DOTTED + * @see #BORDER_THICK + * @see #BORDER_DOUBLE + * @see #BORDER_HAIR + * @see #BORDER_MEDIUM_DASHED + * @see #BORDER_DASH_DOT + * @see #BORDER_MEDIUM_DASH_DOT + * @see #BORDER_DASH_DOT_DOT + * @see #BORDER_MEDIUM_DASH_DOT_DOT + * @see #BORDER_SLANTED_DASH_DOT + */ + + public void setBorderTop(short border) + { + format.setIndentNotParentBorder(true); + format.setBorderTop(border); + } + + /** + * get the type of border to use for the top border of the cell + * @return border type + * @see #BORDER_NONE + * @see #BORDER_THIN + * @see #BORDER_MEDIUM + * @see #BORDER_DASHED + * @see #BORDER_DOTTED + * @see #BORDER_THICK + * @see #BORDER_DOUBLE + * @see #BORDER_HAIR + * @see #BORDER_MEDIUM_DASHED + * @see #BORDER_DASH_DOT + * @see #BORDER_MEDIUM_DASH_DOT + * @see #BORDER_DASH_DOT_DOT + * @see #BORDER_MEDIUM_DASH_DOT_DOT + * @see #BORDER_SLANTED_DASH_DOT + */ + + public short getBorderTop() + { + return format.getBorderTop(); + } + + /** + * set the type of border to use for the bottom border of the cell + * @param border type + * @see #BORDER_NONE + * @see #BORDER_THIN + * @see #BORDER_MEDIUM + * @see #BORDER_DASHED + * @see #BORDER_DOTTED + * @see #BORDER_THICK + * @see #BORDER_DOUBLE + * @see #BORDER_HAIR + * @see #BORDER_MEDIUM_DASHED + * @see #BORDER_DASH_DOT + * @see #BORDER_MEDIUM_DASH_DOT + * @see #BORDER_DASH_DOT_DOT + * @see #BORDER_MEDIUM_DASH_DOT_DOT + * @see #BORDER_SLANTED_DASH_DOT + */ + + public void setBorderBottom(short border) + { + format.setIndentNotParentBorder(true); + format.setBorderBottom(border); + } + + /** + * get the type of border to use for the bottom border of the cell + * @return border type + * @see #BORDER_NONE + * @see #BORDER_THIN + * @see #BORDER_MEDIUM + * @see #BORDER_DASHED + * @see #BORDER_DOTTED + * @see #BORDER_THICK + * @see #BORDER_DOUBLE + * @see #BORDER_HAIR + * @see #BORDER_MEDIUM_DASHED + * @see #BORDER_DASH_DOT + * @see #BORDER_MEDIUM_DASH_DOT + * @see #BORDER_DASH_DOT_DOT + * @see #BORDER_MEDIUM_DASH_DOT_DOT + * @see #BORDER_SLANTED_DASH_DOT + */ + + public short getBorderBottom() + { + return format.getBorderBottom(); + } + + /** + * set the color to use for the left border + * @param color + */ + + public void setLeftBorderColor(short color) + { + format.setLeftBorderPaletteIdx(color); + } + + /** + * get the color to use for the left border + * @return color + */ + + public short getLeftBorderColor() + { + return format.getLeftBorderPaletteIdx(); + } + + /** + * set the color to use for the right border + * @param color + */ + + public void setRightBorderColor(short color) + { + format.setRightBorderPaletteIdx(color); + } + + /** + * get the color to use for the left border + * @return color + */ + + public short getRightBorderColor() + { + return format.getRightBorderPaletteIdx(); + } + + /** + * set the color to use for the top border + * @param color + */ + + public void setTopBorderColor(short color) + { + format.setTopBorderPaletteIdx(color); + } + + /** + * get the color to use for the top border + * @return color + */ + + public short getTopBorderColor() + { + return format.getTopBorderPaletteIdx(); + } + + /** + * set the color to use for the bottom border + * @param color + */ + + public void setBottomBorderColor(short color) + { + format.setBottomBorderPaletteIdx(color); + } + + /** + * get the color to use for the left border + * @return color + */ + + public short getBottomBorderColor() + { + return format.getBottomBorderPaletteIdx(); + } + + /** + * setting to one fills the cell with the foreground color... No idea about + * other values + * @param fill pattern (set to 1 to fill w/foreground color + */ + + public void setFillPattern(short fp) + { + format.setAdtlFillPattern(fp); + } + + /** + * get the fill pattern (??) - set to 1 to fill with foreground color + * @return fill pattern + */ + + public short getFillPattern() + { + return format.getAdtlFillPattern(); + } + + /** + * set the background fill color + * @param color + */ + + public void setFillBackgroundColor(short bg) + { + format.setFillBackground(bg); + } + + /** + * get the background fill color + * @return fill color + */ + + public short getFillBackgroundColor() + { + return format.getFillBackground(); + } + + /** + * set the foreground fill color + * @param color + */ + + public void setFillForegroundColor(short bg) + { + format.setFillForeground(bg); + } + + /** + * get the foreground fill color + * @return fill color + */ + + public short getFillForegroundColor() + { + return format.getFillForeground(); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFColorConstants.java b/src/java/org/apache/poi/hssf/usermodel/HSSFColorConstants.java new file mode 100644 index 000000000..0204dd252 --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFColorConstants.java @@ -0,0 +1,114 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * HSSFColorConstants.java + * + * Created on December 16, 2001, 8:05 AM + */ +package org.apache.poi.hssf.usermodel; + +/** + * contains constants representing colors in the file. + * + * NOTE WILL MOST LIKELY BE DEPRECATED BY THE END OF THE 2.0 CYCLE IN FAVOR + * OF nsph.util.HSSFColor... + * @author Andrew C. Oliver (acoliver at apache dot org) + */ + +public interface HSSFColorConstants +{ + public final static short AUTOMATIC = 0x7fff; + public final static short BLACK = 0x0; // 0 0 0 + public final static short BROWN = 0x3c; // 153, 51, 0 + public final static short OLIVE_GREEN = 0x3b; // 51, 51, 0 + public final static short DARK_GREEN = 0x3a; // 0, 51, 0 + public final static short DARK_TEAL = 0x38; // 0, 51,102 + public final static short DARK_BLUE = 0x12; // 0, 0,128 + public final static short INDIGO = 0x3e; // 51, 51,153 + public final static short GREY_80_PERCENT = 0x3f; // 51, 51, 51 + public final static short DARK_RED = 0x10; // 128, 0, 0 + public final static short ORANGE = 0x35; // 255,102, 0 + public final static short DARK_YELLOW = 0x13; // 128,128, 0 + public final static short GREEN = 0x11; // 0,128, 0 + public final static short TEAL = 0x15; // 0.128,128 + public final static short BLUE = 0xc; // 0, 0,255 + public final static short BLUE_GREY = 0x36; // 102,102,153 + public final static short GREY_50_PERCENT = 0x17; // 128,128,128 + public final static short RED = 0xa; // 255, 0, 0 + public final static short LIGHT_ORANGE = 0x34; // 255,153, 0 + public final static short LIME = 0x32; // 153,204, 0 + public final static short SEA_GREEN = 0x39; // 51,153,102 + public final static short AQUA = 0x31; // 51,204,204 + public final static short LIGHT_BLUE = 0x30; // 51,102,255 + public final static short VIOLET = 0x14; // 128, 0,128 + public final static short GREY_40_PERCENT = 0x37; // 150,150,150 + public final static short PINK = 0xe; // 255, 0,255 + public final static short GOLD = 0x33; // 255,204, 0 + public final static short YELLOW = 0xd; // 255,255, 0 + public final static short BRIGHT_GREEN = 0xb; // 0,255, 0 + public final static short TURQUOISE = 0xf; // 0,255,255 + public final static short SKY_BLUE = 0x28; // 0,204,255 + public final static short PLUM = 0x3d; // 153, 51,102 + public final static short GREY_25_PERCENT = 0x16; // 192,192,192 + public final static short ROSE = 0x2d; // 255,153,204 + public final static short TAN = 0x2f; // 255,204,153 + public final static short LIGHT_YELLOW = 0x2b; // 255,255,153 + public final static short LIGHT_GREEN = 0x2a; // 204,255,204 + public final static short LIGHT_TURQUOISE = 0x29; // 204,255,255 + public final static short PALE_BLUE = 0x2c; // 153,204,255 + public final static short LAVENDER = 0x2e; // 204,153,255 + public final static short WHITE = 0x9; // 255,255,255 +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormat.java b/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormat.java new file mode 100644 index 000000000..f1d75fe99 --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormat.java @@ -0,0 +1,241 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * HSSFDataFormat.java + * + * Created on December 18, 2001, 12:42 PM + */ +package org.apache.poi.hssf.usermodel; + +import java.util.ArrayList; +import java.util.List; + +/** + * Utility to identify builin formats. The following is a list of the formats as + * returned by this class.

+ *

+ * 0, "General"

+ * 1, "0"

+ * 2, "0.00"

+ * 3, "#,##0"

+ * 4, "#,##0.00"

+ * 5, "($#,##0_);($#,##0)"

+ * 6, "($#,##0_);[Red]($#,##0)"

+ * 7, "($#,##0.00);($#,##0.00)"

+ * 8, "($#,##0.00_);[Red]($#,##0.00)"

+ * 9, "0%"

+ * 0xa, "0.00%"

+ * 0xb, "0.00E+00"

+ * 0xc, "# ?/?"

+ * 0xd, "# ??/??"

+ * 0xe, "m/d/yy"

+ * 0xf, "d-mmm-yy"

+ * 0x10, "d-mmm"

+ * 0x11, "mmm-yy"

+ * 0x12, "h:mm AM/PM"

+ * 0x13, "h:mm:ss AM/PM"

+ * 0x14, "h:mm"

+ * 0x15, "h:mm:ss"

+ * 0x16, "m/d/yy h:mm"

+ *

+ * // 0x17 - 0x24 reserved for international and undocumented + * 0x25, "(#,##0_);(#,##0)"

+ * 0x26, "(#,##0_);[Red](#,##0)"

+ * 0x27, "(#,##0.00_);(#,##0.00)"

+ * 0x28, "(#,##0.00_);[Red](#,##0.00)"

+ * 0x29, "_(*#,##0_);_(*(#,##0);_(* \"-\"_);_(@_)"

+ * 0x2a, "_($*#,##0_);_($*(#,##0);_($* \"-\"_);_(@_)"

+ * 0x2b, "_(*#,##0.00_);_(*(#,##0.00);_(*\"-\"??_);_(@_)"

+ * 0x2c, "_($*#,##0.00_);_($*(#,##0.00);_($*\"-\"??_);_(@_)"

+ * 0x2d, "mm:ss"

+ * 0x2e, "[h]:mm:ss"

+ * 0x2f, "mm:ss.0"

+ * 0x30, "##0.0E+0"

+ * 0x31, "@"

+ * + * + * @author Andrew C. Oliver (acoliver at apache dot org) + */ + +public class HSSFDataFormat +{ + private static ArrayList formats; + + private static synchronized void populateFormats() + { + formats = new ArrayList(); + formats.add(0, "General"); + formats.add(1, "0"); + formats.add(2, "0.00"); + formats.add(3, "#,##0"); + formats.add(4, "#,##0.00"); + formats.add(5, "($#,##0_);($#,##0)"); + formats.add(6, "($#,##0_);[Red]($#,##0)"); + formats.add(7, "($#,##0.00);($#,##0.00)"); + formats.add(8, "($#,##0.00_);[Red]($#,##0.00)"); + formats.add(9, "0%"); + formats.add(0xa, "0.00%"); + formats.add(0xb, "0.00E+00"); + formats.add(0xc, "# ?/?"); + formats.add(0xd, "# ??/??"); + formats.add(0xe, "m/d/yy"); + formats.add(0xf, "d-mmm-yy"); + formats.add(0x10, "d-mmm"); + formats.add(0x11, "mmm-yy"); + formats.add(0x12, "h:mm AM/PM"); + formats.add(0x13, "h:mm:ss AM/PM"); + formats.add(0x14, "h:mm"); + formats.add(0x15, "h:mm:ss"); + formats.add(0x16, "m/d/yy h:mm"); + + // 0x17 - 0x24 reserved for international and undocumented + formats.add(0x17, "0x17"); + formats.add(0x18, "0x18"); + formats.add(0x19, "0x19"); + formats.add(0x1a, "0x1a"); + formats.add(0x1b, "0x1b"); + formats.add(0x1c, "0x1c"); + formats.add(0x1d, "0x1d"); + formats.add(0x1e, "0x1e"); + formats.add(0x1f, "0x1f"); + formats.add(0x20, "0x20"); + formats.add(0x21, "0x21"); + formats.add(0x22, "0x22"); + formats.add(0x23, "0x23"); + formats.add(0x24, "0x24"); + + // 0x17 - 0x24 reserved for international and undocumented + formats.add(0x25, "(#,##0_);(#,##0)"); + formats.add(0x26, "(#,##0_);[Red](#,##0)"); + formats.add(0x27, "(#,##0.00_);(#,##0.00)"); + formats.add(0x28, "(#,##0.00_);[Red](#,##0.00)"); + formats.add(0x29, "_(*#,##0_);_(*(#,##0);_(* \"-\"_);_(@_)"); + formats.add(0x2a, "_($*#,##0_);_($*(#,##0);_($* \"-\"_);_(@_)"); + formats.add(0x2b, "_(*#,##0.00_);_(*(#,##0.00);_(*\"-\"??_);_(@_)"); + formats.add(0x2c, + "_($*#,##0.00_);_($*(#,##0.00);_($*\"-\"??_);_(@_)"); + formats.add(0x2d, "mm:ss"); + formats.add(0x2e, "[h]:mm:ss"); + formats.add(0x2f, "mm:ss.0"); + formats.add(0x30, "##0.0E+0"); + formats.add(0x31, "@"); + } + + public static List getFormats() + { + if (formats == null) + { + populateFormats(); + } + return formats; + } + + /** + * get the format index that matches the given format string + * @param format string matching a built in format + * @return index of format or -1 if undefined. + */ + + public static short getFormat(String format) + { + if (formats == null) + { + populateFormats(); + } + short retval = -1; + + for (short k = 0; k < 0x31; k++) + { + String nformat = ( String ) formats.get(k); + + if ((nformat != null) && nformat.equals(format)) + { + retval = k; + break; + } + } + return retval; + } + + /** + * get the format string that matches the given format index + * @param index of a built in format + * @return string represented at index of format or null if there is not a builtin format at that index + */ + + public static String getFormat(short index) + { + if (formats == null) + { + populateFormats(); + } + return ( String ) formats.get(index); + } + + /** + * get the number of builtin and reserved formats + * @return number of builtin and reserved formats + */ + + public static int getNumberOfBuiltinFormats() + { + if (formats == null) + { + populateFormats(); + } + return formats.size(); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java b/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java new file mode 100644 index 000000000..8d8611a8e --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java @@ -0,0 +1,210 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * DateUtil.java + * + * Created on January 19, 2002, 9:30 AM + */ +package org.apache.poi.hssf.usermodel; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +/** + * Contains methods for dealing with Excel dates. + * + * @author Michael Harhen + * @author Glen Stampoultzis (gstamp at iprimus dot com dot au) + */ + +public class HSSFDateUtil +{ + private HSSFDateUtil() + { + } + + private static final int BAD_DATE = + -1; // used to specify that date is invalid + private static final long DAY_MILLISECONDS = 24 * 60 * 60 * 1000; + private static final double CAL_1900_ABSOLUTE = + ( double ) absoluteDay(new GregorianCalendar(1900, Calendar + .JANUARY, 1)) - 2.0; + + /** + * Given a Date, converts it into a double representing its internal Excel representation, + * which is the number of days since 1/1/1900. Fractional days represent hours, minutes, and seconds. + * + * @return Excel representation of Date (-1 if error - test for error by checking for less than 0.1) + * @param date the Date + */ + + public static double getExcelDate(Date date) + { + Calendar calStart = new GregorianCalendar(); + + calStart.setTime( + date); // If date includes hours, minutes, and seconds, set them to 0 + if (calStart.get(Calendar.YEAR) < 1900) + { + return BAD_DATE; + } + else + { + calStart = dayStart(calStart); + double fraction = (date.getTime() - calStart.getTime().getTime()) + / ( double ) DAY_MILLISECONDS; + + return fraction + ( double ) absoluteDay(calStart) + - CAL_1900_ABSOLUTE; + } + } + + /** + * Given a excel date, converts it into a Date. + * + * @param date the Excel Date + * + * @return Java representation of a date (null if error) + */ + + public static Date getJavaDate(double date) + { + if (isValidExcelDate(date)) + { + int wholeDaysSince1900 = ( int ) Math.floor(date); + GregorianCalendar calendar = new GregorianCalendar(1900, + 0, wholeDaysSince1900 + - 1); + int millisecondsInDay = + ( int ) ((date - Math.floor(date)) + * ( double ) DAY_MILLISECONDS + 0.5); + + calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay); + return calendar.getTime(); + } + else + { + return null; + } + } + + /** + * Given a double, checks if it is a valid Excel date. + * + * @return true if valid + * @param value the double value + */ + + public static boolean isValidExcelDate(double value) + { + return (value > -Double.MIN_VALUE); + } + + /** + * Given a Calendar, return the number of days since 1600/12/31. + * + * @return days number of days since 1600/12/31 + * @param cal the Calendar + * @exception IllegalArgumentException if date is invalid + */ + + private static int absoluteDay(Calendar cal) + { + return cal.get(Calendar.DAY_OF_YEAR) + + daysInPriorYears(cal.get(Calendar.YEAR)); + } + + /** + * Return the number of days in prior years since 1601 + * + * @return days number of days in years prior to yr. + * @param yr a year (1600 < yr < 4000) + * @exception IllegalArgumentException if year is outside of range. + */ + + private static int daysInPriorYears(int yr) + { + if (yr < 1601) + { + throw new IllegalArgumentException( + "'year' must be 1601 or greater"); + } + int y = yr - 1601; + int days = 365 * y // days in prior years + + y / 4 // plus julian leap days in prior years + - y / 100 // minus prior century years + + y / 400; // plus years divisible by 400 + + return days; + } + + // set HH:MM:SS fields of cal to 00:00:00:000 + private static Calendar dayStart(final Calendar cal) + { + cal.get(Calendar + .HOUR_OF_DAY); // force recalculation of internal fields + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + cal.get(Calendar + .HOUR_OF_DAY); // force recalculation of internal fields + return cal; + } + + // --------------------------------------------------------------------------------------------------------- +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFErrorConstants.java b/src/java/org/apache/poi/hssf/usermodel/HSSFErrorConstants.java new file mode 100644 index 000000000..d5ab811ba --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFErrorConstants.java @@ -0,0 +1,77 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * HSSFErrorConstants.java + * + * Created on January 19, 2002, 9:30 AM + */ +package org.apache.poi.hssf.usermodel; + +/** + * contains constants representing Excel error codes. + * @author Michael Harhen + */ + +public interface HSSFErrorConstants +{ + public static final byte ERROR_NULL = 0x00; // #NULL! + public static final byte ERROR_DIV_0 = 0x07; // #DIV/0! + public static final byte ERROR_VALUE = 0x0f; // #VALUE! + public static final byte ERROR_REF = 0x17; // #REF! + public static final byte ERROR_NAME = 0x1d; // #NAME? + public static final byte ERROR_NUM = 0x24; // #NUM! + public static final byte ERROR_NA = 0x2a; // #N/A +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFFont.java b/src/java/org/apache/poi/hssf/usermodel/HSSFFont.java new file mode 100644 index 000000000..0800452dc --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFFont.java @@ -0,0 +1,390 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * HSSFFont.java + * + * Created on December 9, 2001, 10:34 AM + */ +package org.apache.poi.hssf.usermodel; + +import org.apache.poi.hssf.record.FontRecord; + +/** + * Represents a Font used in a workbook. + * + * @version 1.0-pre + * @author Andrew C. Oliver + * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#createFont() + * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getFontAt(short) + * @see org.apache.poi.hssf.usermodel.HSSFCellStyle#setFont(HSSFFont) + */ + +public class HSSFFont + implements HSSFColorConstants +{ + + /** + * Arial font + */ + + public final static String FONT_ARIAL = "Arial"; + + /** + * Normal boldness (not bold) + */ + + public final static short BOLDWEIGHT_NORMAL = 190; + + /** + * Bold boldness (bold) + */ + + public final static short BOLDWEIGHT_BOLD = 0x2bc; + + /** + * normal type of black color + */ + + public final static short COLOR_NORMAL = 0x7fff; + + /** + * Dark Red color + */ + + public final static short COLOR_RED = 0xa; + + /** + * no type offsetting (not super or subscript) + */ + + public final static short SS_NONE = 0; + + /** + * superscript + */ + + public final static short SS_SUPER = 1; + + /** + * subscript + */ + + public final static short SS_SUB = 2; + + /** + * not underlined + */ + + public final static byte U_NONE = 0; + + /** + * single (normal) underline + */ + + public final static byte U_SINGLE = 1; + + /** + * double underlined + */ + + public final static byte U_DOUBLE = 2; + + /** + * accounting style single underline + */ + + public final static byte U_SINGLE_ACCOUNTING = 0x21; + + /** + * accounting style double underline + */ + + public final static byte U_DOUBLE_ACCOUNTING = 0x22; + private FontRecord font; + private short index; + + /** Creates a new instance of HSSFFont */ + + protected HSSFFont(short index, FontRecord rec) + { + font = rec; + this.index = index; + } + + /** + * set the name for the font (i.e. Arial) + * @param String representing the name of the font to use + * @see #FONT_ARIAL + */ + + public void setFontName(String name) + { + font.setFontName(name); + font.setFontNameLength(( byte ) name.length()); + } + + /** + * get the name for the font (i.e. Arial) + * @return String representing the name of the font to use + * @see #FONT_ARIAL + */ + + public String getFontName() + { + return font.getFontName(); + } + + /** + * get the index within the HSSFWorkbook (sequence within the collection of Font objects) + * @return unique index number of the underlying record this Font represents (probably you don't care + * unless you're comparing which one is which) + */ + + public short getIndex() + { + return index; + } + + /** + * set the font height in unit's of 1/20th of a point. Maybe you might want to + * use the setFontHeightInPoints which matches to the familiar 10, 12, 14 etc.. + * @param short - height in 1/20ths of a point + * @see #setFontHeightInPoints(short) + */ + + public void setFontHeight(short height) + { + font.setFontHeight(height); + } + + /** + * set the font height + * @param short - height in the familiar unit of measure - points + * @see #setFontHeight(short) + */ + + public void setFontHeightInPoints(short height) + { + font.setFontHeight(( short ) (height * 20)); + } + + /** + * get the font height in unit's of 1/20th of a point. Maybe you might want to + * use the getFontHeightInPoints which matches to the familiar 10, 12, 14 etc.. + * @return short - height in 1/20ths of a point + * @see #getFontHeightInPoints() + */ + + public short getFontHeight() + { + return font.getFontHeight(); + } + + /** + * get the font height + * @return short - height in the familiar unit of measure - points + * @see #getFontHeight() + */ + + public short getFontHeightInPoints() + { + return ( short ) (font.getFontHeight() / 20); + } + + /** + * set whether to use italics or not + * @param italics or not + */ + + public void setItalic(boolean italic) + { + font.setItalic(italic); + } + + /** + * get whether to use italics or not + * @return italics or not + */ + + public boolean getItalic() + { + return font.isItalic(); + } + + /** + * set whether to use a strikeout horizontal line through the text or not + * @param strikeout or not + */ + + public void setStrikeout(boolean strikeout) + { + font.setStrikeout(strikeout); + } + + /** + * get whether to use a strikeout horizontal line through the text or not + * @return strikeout or not + */ + + public boolean getStrikeout() + { + return font.isStruckout(); + } + + /** + * set the color for the font + * @param color to use + * @see #COLOR_NORMAL + * @see #COLOR_RED + */ + + public void setColor(short color) + { + font.setColorPaletteIndex(color); + } + + /** + * get the color for the font + * @return color to use + * @see #COLOR_NORMAL + * @see #COLOR_RED + */ + + public short getColor() + { + return font.getColorPaletteIndex(); + } + + /** + * set the boldness to use + * @param boldweight + * @see #BOLDWEIGHT_NORMAL + * @see #BOLDWEIGHT_BOLD + */ + + public void setBoldweight(short boldweight) + { + font.setBoldWeight(boldweight); + } + + /** + * get the boldness to use + * @return boldweight + * @see #BOLDWEIGHT_NORMAL + * @see #BOLDWEIGHT_BOLD + */ + + public short getBoldweight() + { + return font.getBoldWeight(); + } + + /** + * set normal,super or subscript. + * @param offset type to use (none,super,sub) + * @see #SS_NONE + * @see #SS_SUPER + * @see #SS_SUB + */ + + public void setTypeOffset(short offset) + { + font.setSuperSubScript(offset); + } + + /** + * get normal,super or subscript. + * @return offset type to use (none,super,sub) + * @see #SS_NONE + * @see #SS_SUPER + * @see #SS_SUB + */ + + public short getTypeOffset() + { + return font.getSuperSubScript(); + } + + /** + * set type of text underlining to use + * @param underlining type + * @see #U_NONE + * @see #U_SINGLE + * @see #U_DOUBLE + * @see #U_SINGLE_ACCOUNTING + * @see #U_DOUBLE_ACCOUNTING + */ + + public void setUnderline(byte underline) + { + font.setUnderline(underline); + } + + /** + * get type of text underlining to use + * @return underlining type + * @see #U_NONE + * @see #U_SINGLE + * @see #U_DOUBLE + * @see #U_SINGLE_ACCOUNTING + * @see #U_DOUBLE_ACCOUNTING + */ + + public byte getUnderline() + { + return font.getUnderline(); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java b/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java new file mode 100644 index 000000000..f75e0570e --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java @@ -0,0 +1,548 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * HSSFRow.java + * + * Created on September 30, 2001, 3:44 PM + */ +package org.apache.poi.hssf.usermodel; + +import java.util.List; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +import org.apache.poi.hssf.model.Workbook; +import org.apache.poi.hssf.model.Sheet; +import org.apache.poi.hssf.record.RowRecord; +import org.apache.poi.hssf.record.CellValueRecordInterface; + +/** + * High level representation of a row of a spreadsheet. + * + * Only rows that have cells should be added to a Sheet. + * @version 1.0-pre + * @author Andrew C. Oliver (acoliver at apache dot org) + */ + +public class HSSFRow + implements Comparable +{ + + // used for collections + public final static int INITIAL_CAPACITY = 5; + private short rowNum; + private HashMap cells; + private short firstcell = -1; + private short lastcell = -1; + + /** + * reference to low level representation + */ + + private RowRecord row; + + /** + * reference to containing low level Workbook + */ + + private Workbook book; + + /** + * reference to containing Sheet + */ + + private Sheet sheet; + + protected HSSFRow() + { + } + + /** + * Creates new HSSFRow from scratch. Only HSSFSheet should do this. + * + * @param book low-level Workbook object containing the sheet that contains this row + * @param sheet low-level Sheet object that contains this Row + * @param rowNum the row number of this row (0 based) + * @see org.apache.poi.hssf.usermodel.HSSFSheet#createRow(short) + */ + + protected HSSFRow(Workbook book, Sheet sheet, short rowNum) + { + this.rowNum = rowNum; + cells = new HashMap(10); // new ArrayList(INITIAL_CAPACITY); + this.book = book; + this.sheet = sheet; + row = new RowRecord(); + row.setHeight(( short ) 0xff); + + // row.setRowNumber(rowNum); + setRowNum(rowNum); + } + + /** + * Creates an HSSFRow from a low level RowRecord object. Only HSSFSheet should do + * this. HSSFSheet uses this when an existing file is read in. + * + * @param book low-level Workbook object containing the sheet that contains this row + * @param sheet low-level Sheet object that contains this Row + * @param RowRecord - the low level api object this row should represent + * @see org.apache.poi.hssf.usermodel.HSSFSheet#createRow(short) + */ + + protected HSSFRow(Workbook book, Sheet sheet, RowRecord record) + { + this.rowNum = rowNum; + cells = new HashMap(); // ArrayList(INITIAL_CAPACITY); + this.book = book; + this.sheet = sheet; + row = record; + + // row.setHeight(record.getHeight()); + // row.setRowNumber(rowNum); + setRowNum(record.getRowNumber()); + +// addColumns(book, sheet, record); + } + + /** + * Use this to create new cells within the row and return it. + *

+ * The cell that is returned is a CELL_TYPE_BLANK. The type can be changed + * either through calling setCellValue or setCellType. + * + * @param column - the column number this cell represents + * + * @return HSSFCell a high level representation of the created cell. + */ + + public HSSFCell createCell(short column) + { + HSSFCell cell = new HSSFCell(book, sheet, getRowNum(), column); + + addCell(cell, true); + sheet.addValueRecord(getRowNum(), cell.getCellValueRecord()); + return cell; + } + + /** + * Use this to create new cells within the row and return it. + *

+ * The cell that is returned is a CELL_TYPE_BLANK. The type can be changed + * either through calling setCellValue or setCellType. + * + * @param column - the column number this cell represents + * + * @return HSSFCell a high level representation of the created cell. + * @deprecated As of 22-Jan-2002 use createCell(short) and use setCellValue to + * specify the type lazily. + */ + + public HSSFCell createCell(short column, int type) + { + HSSFCell cell = new HSSFCell(book, sheet, getRowNum(), column, type); + + addCell(cell, true); + sheet.addValueRecord(getRowNum(), cell.getCellValueRecord()); + return cell; + } + + /** + * remove the HSSFCell from this row. + * @param cell to remove + */ + + public void removeCell(HSSFCell cell) + { + CellValueRecordInterface cval = cell.getCellValueRecord(); + + sheet.removeValueRecord(getRowNum(), cval); + cells.remove(new Integer(cell.getCellNum())); + + /* + * for (int k = 0; k < cells.size(); k++) + * { + * HSSFCell hcell = ( HSSFCell ) cells.get(k); + * + * if (hcell.getCellNum() == cell.getCellNum()) + * { + * cells.remove(k); + * } + * } + */ + if (cell.getCellNum() == lastcell) + { + lastcell = findLastCell(lastcell); + } + else if (cell.getCellNum() == firstcell) + { + firstcell = findFirstCell(firstcell); + } + } + + /** + * create a high level HSSFCell object from an existing low level record. Should + * only be called from HSSFSheet or HSSFRow itself. + * @param cell low level cell to create the high level representation from + * @return HSSFCell representing the low level record passed in + */ + + protected HSSFCell createCellFromRecord(CellValueRecordInterface cell) + { + HSSFCell hcell = new HSSFCell(book, sheet, getRowNum(), cell); + + addCell(hcell, false); + + // sheet.addValueRecord(getRowNum(),cell.getCellValueRecord()); + return hcell; + } + + /** + * set the row number of this row. + * @param row number the row number (0-based) + */ + + public void setRowNum(short rowNum) + { + this.rowNum = rowNum; + if (row != null) + { + row.setRowNumber(rowNum); // used only for KEY comparison (HSSFRow) + } + } + + /** + * get row number this row represents + * @return the row number (0 based) + */ + + public short getRowNum() + { + return rowNum; + } + + /** + * used internally to add a cell. Pass anything in for dummy boolean. (possibly used in later versions) + */ + + private void addCell(HSSFCell cell, boolean dummy) + { + if (firstcell == -1) + { + firstcell = cell.getCellNum(); + } + if (lastcell == -1) + { + lastcell = cell.getCellNum(); + } + cells.put(new Integer(cell.getCellNum()), cell); + +/* if (cells.size() > 0) + { + if ((cell.getCellNum() < firstcell) || (firstcell == -1)) + { + firstcell = cell.getCellNum(); + } + if ((cell.getCellNum() > lastcell) || (lastcell == -1)) + { + lastcell = cell.getCellNum(); + } + for (int k = cells.size() - 1; k > -1; k--) + { + if ((cell.getCellNum() > (( HSSFCell ) cells.get(k)) + .getCellNum()) || (k == 0)) + { + cells.add(k, cell); + break; + } + } + } + else + { + firstcell = cell.getCellNum(); + lastcell = cell.getCellNum(); + cells.add(cell); + } + */ + if (cell.getCellNum() < row.getFirstCol()) + { + row.setFirstCol(cell.getCellNum()); + } + if (cell.getCellNum() > row.getLastCol()) + { + row.setLastCol(cell.getCellNum()); + } + } + + /** + * 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. + */ + + public HSSFCell getCell(short cellnum) + { + +/* for (int k = 0; k < cells.size(); k++) + { + HSSFCell cell = ( HSSFCell ) cells.get(k); + + if (cell.getCellNum() == cellnum) + { + return cell; + } + }*/ + return ( HSSFCell ) cells.get(new Integer(cellnum)); + } + + /** + * get the number of the first cell contained in this row. + * @return short representing the first logical cell in the row + */ + + public short getFirstCellNum() + { + return firstcell; + } + + /** + * get the number of the last cell contained in this row. + * @return short representing the last logical cell in the row + */ + + public short getLastCellNum() + { + + // if (cells.size() == 0) return -1; + // return ((HSSFCell)cells.get(cells.size()-1)).getCellNum(); + return lastcell; + } + + /** + * gets a list of cells in the row. + * @retun List - shallow copy of cells - best you don't modify them + */ + +// public List getCells() +// { // shallow copy, modifying cells changes things + // modifying the array changes nothing! +// return ( ArrayList ) cells.clone(); +// } + + /** + * gets the number of defined cells (NOT number of cells in the actual row!). + * That is to say if only columns 0,4,5 have values then there would be 3. + * @return int representing the number of defined cells in the row. + */ + + public int getPhysicalNumberOfCells() + { + if (cells == null) + { + return 0; // shouldn't be possible but it is due to missing API support for BLANK/MULBLANK + } + return cells.size(); + } + + /** + * gets the phsyically defined cell at location (num) NOT its column number. + * That is to say if only columns 0,4,5 have values then index 2 would equal cell with a column number of 4. + * (though the order is not assured) + * @return HSSFCell physically defined at the given index. + */ + +// public HSSFCell getPhysicalCellAt(int num) +// { +// return ( HSSFCell ) cells.get(num); +// } + + /** + * set the row's height or set to ff (-1) for undefined/default-height. Set the height in "twips" or + * 1/20th of a point. + * @param rowheight or 0xff for undefined (use sheet default) + */ + + public void setHeight(short height) + { + + // row.setOptionFlags( + row.setBadFontHeight(true); + row.setHeight(height); + } + + /** + * set the row's height in points. + * @param rowheight + */ + + public void setHeightInPoints(float height) + { + + // row.setOptionFlags( + row.setBadFontHeight(true); + row.setHeight(( short ) (height * 20)); + } + + /** + * get the row's height or ff (-1) for undefined/default-height in twips (1/20th of a point) + * @return rowheight or 0xff for undefined (use sheet default) + */ + + public short getHeight() + { + return row.getHeight(); + } + + /** + * get the row's height or ff (-1) for undefined/default-height in points (20*getHeight()) + * @return rowheight or 0xff for undefined (use sheet default) + */ + + public float getHeightInPoints() + { + return (row.getHeight() / 20); + } + + /** + * get the lowlevel RowRecord represented by this object - should only be called + * by other parts of the high level API + * + * @return RowRecord this row represents + */ + + protected RowRecord getRowRecord() + { + return row; + } + + /** + * used internally to refresh the "last cell" when the last cell is removed. + */ + + private short findLastCell(short lastcell) + { + short cellnum = ( short ) (lastcell - 1); + HSSFCell r = getCell(cellnum); + + while (r == null) + { + r = getCell(--cellnum); + } + return cellnum; + } + + /** + * used internally to refresh the "first cell" when the first cell is removed. + */ + + private short findFirstCell(short firstcell) + { + short cellnum = ( short ) (firstcell + 1); + HSSFCell r = getCell(cellnum); + + while (r == null) + { + r = getCell(++cellnum); + } + return cellnum; + } + + /** + * @returns cell iterator of the physically defined cells. Note element 4 may + * actually be row cell depending on how many are defined! + */ + + public Iterator cellIterator() + { + return cells.values().iterator(); + } + + public int compareTo(Object obj) + { + HSSFRow loc = ( HSSFRow ) obj; + + if (this.getRowNum() == loc.getRowNum()) + { + return 0; + } + if (this.getRowNum() < loc.getRowNum()) + { + return -1; + } + if (this.getRowNum() > loc.getRowNum()) + { + return 1; + } + return -1; + } + + public boolean equals(Object obj) + { + if (!(obj instanceof HSSFRow)) + { + return false; + } + HSSFRow loc = ( HSSFRow ) obj; + + if (this.getRowNum() == loc.getRowNum()) + { + return true; + } + return false; + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java new file mode 100644 index 000000000..e20c65d9a --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -0,0 +1,758 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * HSSFSheet.java + * + * Created on September 30, 2001, 3:40 PM + */ +package org.apache.poi.hssf.usermodel; + +import org.apache.poi.hssf.HSSFLog; +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.util.Region; +import org.apache.poi.util.POILogger; + +import java.util.Iterator; +import java.util.TreeMap; + +/** + * High level representation of a worksheet. + * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Glen Stampoultzis (gstamp at iprimus dot com dot au) + * @version 1.0-pre + */ + +public class HSSFSheet +{ + private static final int DEBUG = POILogger.DEBUG; + + /** + * Used for compile-time optimization. This is the initial size for the collection of + * rows. It is currently set to 20. If you generate larger sheets you may benefit + * by setting this to a higher number and recompiling a custom edition of HSSFSheet. + */ + + 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 static POILogger log = HSSFLog.getPOILogger(HSSFSheet.class); + + /** + * Creates new HSSFSheet - called by HSSFWorkbook to create a sheet from + * scratch. You should not be calling this from application code (its protected anyhow). + * + * @param book - lowlevel Workbook object associated with the sheet. + * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#createSheet() + */ + + protected HSSFSheet(Workbook book) + { + sheet = Sheet.createSheet(); + rows = new TreeMap(); // new ArrayList(INITIAL_CAPACITY); + this.book = book; + } + + /** + * Creates an HSSFSheet representing the given Sheet object. Should only be + * called by HSSFWorkbook when reading in an exisiting file. + * + * @param book - lowlevel Workbook object associated with the sheet. + * @param sheet - lowlevel Sheet object this sheet will represent + * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#createSheet() + */ + + protected HSSFSheet(Workbook book, Sheet sheet) + { + this.sheet = sheet; + 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 + */ + + private void setPropertiesFromSheet(Sheet sheet) + { + int sloc = sheet.getLoc(); + RowRecord row = sheet.getNextRow(); + + while (row != null) + { + HSSFRow hrow = createRowFromRecord(row); + + row = sheet.getNextRow(); + } + sheet.setLoc(sloc); + CellValueRecordInterface cval = sheet.getNextValueRecord(); + long timestart = System.currentTimeMillis(); + + log.log(DEBUG, "Time at start of cell creating in HSSF sheet = ", + new Long(timestart)); + HSSFRow lastrow = null; + + while (cval != null) + { + long cellstart = System.currentTimeMillis(); + HSSFRow hrow = lastrow; + + if ((lastrow == null) || (lastrow.getRowNum() != cval.getRow())) + { + hrow = getRow(cval.getRow()); + } + lastrow = hrow; + hrow.createCellFromRecord(cval); + cval = sheet.getNextValueRecord(); + log.log(DEBUG, "record took ", + new Long(System.currentTimeMillis() - cellstart)); + } + log.log(DEBUG, "total sheet cell creation took ", + new Long(System.currentTimeMillis() - timestart)); + } + + /** + * Create a new row within the sheet and return the high level representation + * + * @param row number + * @return High level HSSFRow object representing a row in the sheet + * @see org.apache.poi.hssf.usermodel.HSSFRow + * @see #removeRow(HSSFRow) + */ + + public HSSFRow createRow(short rownum) + { + HSSFRow row = new HSSFRow(book, sheet, rownum); + + addRow(row, true); + return row; + } + + /** + * Used internally to create a high level Row object from a low level row object. + * USed when reading an existing file + * @param RowRecord low level record to represent as a high level Row and add to sheet + * @return HSSFRow high level representation + */ + + private HSSFRow createRowFromRecord(RowRecord row) + { + HSSFRow hrow = new HSSFRow(book, sheet, row); + + addRow(hrow, false); + return hrow; + } + + /** + * Remove a row from this sheet. All cells contained in the row are removed as well + * + * @param HSSFRow representing a row to remove. + */ + + public void removeRow(HSSFRow row) + { + sheet.setLoc(sheet.getDimsLoc()); + if (rows.size() > 0) + { + rows.remove(row); + if (row.getRowNum() == getLastRowNum()) + { + lastrow = findLastRow(lastrow); + } + if (row.getRowNum() == getFirstRowNum()) + { + firstrow = findFirstRow(firstrow); + } + Iterator iter = row.cellIterator(); + + while (iter.hasNext()) + { + HSSFCell cell = ( HSSFCell ) iter.next(); + + sheet.removeValueRecord(row.getRowNum(), + cell.getCellValueRecord()); + } + sheet.removeRow(row.getRowRecord()); + } + } + + /** + * used internally to refresh the "last row" when the last row is removed. + */ + + private int findLastRow(int lastrow) + { + int rownum = lastrow - 1; + HSSFRow r = getRow(rownum); + + while (r == null) + { + r = getRow(--rownum); + } + return rownum; + } + + /** + * used internally to refresh the "first row" when the first row is removed. + */ + + private int findFirstRow(int firstrow) + { + int rownum = firstrow + 1; + HSSFRow r = getRow(rownum); + + while (r == null) + { + r = getRow(++rownum); + } + return rownum; + } + + /** + * add a row to the sheet + * + * @param addLow whether to add the row to the low level model - false if its already there + */ + + private void addRow(HSSFRow row, boolean addLow) + { + rows.put(row, row); + if (addLow) + { + sheet.addRow(row.getRowRecord()); + } + if (row.getRowNum() > getLastRowNum()) + { + lastrow = row.getRowNum(); + } + if (row.getRowNum() < getFirstRowNum()) + { + firstrow = row.getRowNum(); + } + } + + /** + * Returns the logical row (not physical) 0-based. If you ask for a row that is not + * defined you get a null. This is to say row 4 represents the fifth row on a sheet. + * @param row to get + * @return HSSFRow representing the rownumber or null if its not defined on the sheet + */ + + public HSSFRow getRow(int rownum) + { + HSSFRow row = new HSSFRow(); + + row.setRowNum(( short ) rownum); + return ( HSSFRow ) rows.get(row); + } + + /** + * Returns the number of phsyically defined rows (NOT the number of rows in the sheet) + */ + + public int getPhysicalNumberOfRows() + { + return rows.size(); + } + + /** + * gets the first row on the sheet + * @return the number of the first logical row on the sheet + */ + + public int getFirstRowNum() + { + return firstrow; + } + + /** + * gets the last row on the sheet + * @return last row contained n this sheet. + */ + + public int getLastRowNum() + { + return lastrow; + } + + /** + * used internally to add cells from a high level row to the low level model + * @param HSSFRow 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 + */ + + public void setColumnWidth(short column, short width) + { + sheet.setColumnWidth(column, width); + } + + /** + * get the width (in units of 1/256th of a character width ) + * @param column - the column to set (0-based) + * @return width - the width in units of 1/256th of a character width + */ + + public short getColumnWidth(short column) + { + return sheet.getColumnWidth(column); + } + + /** + * get the default column width for the sheet (if the columns do not define their own width) in + * characters + * @return default column width + */ + + public short getDefaultColumnWidth() + { + return sheet.getDefaultColumnWidth(); + } + + /** + * get the default row height for the sheet (if the rows do not define their own height) in + * twips (1/20 of a point) + * @param default row height + */ + + public short getDefaultRowHeight() + { + return sheet.getDefaultRowHeight(); + } + + /** + * get the default row height for the sheet (if the rows do not define their own height) in + * points. + * @param default row height + */ + + public float getDefaultRowHeightInPoints() + { + return (sheet.getDefaultRowHeight() / 20); + } + + /** + * set the default column width for the sheet (if the columns do not define their own width) in + * characters + * @param default column width + */ + + public void setDefaultColumnWidth(short width) + { + sheet.setDefaultColumnWidth(width); + } + + /** + * set the default row height for the sheet (if the rows do not define their own height) in + * twips (1/20 of a point) + * @return default row height + */ + + public void setDefaultRowHeight(short height) + { + sheet.setDefaultRowHeight(height); + } + + /** + * set the default row height for the sheet (if the rows do not define their own height) in + * points + * @return default row height + */ + + public void setDefaultRowHeightInPoints(float height) + { + sheet.setDefaultRowHeight(( short ) (height * 20)); + } + + /** + * get whether gridlines are printed. + * @return true if printed + */ + + public boolean isGridsPrinted() + { + return sheet.isGridsPrinted(); + } + + /** + * set whether gridlines printed. + * @return false if not printed. + */ + + public void setGridsPrinted(boolean value) + { + sheet.setGridsPrinted(value); + } + + /** + * adds a merged region of cells (hence those cells form one) + * @param region (rowfrom/colfrom-rowto/colto) to merge + * @return index of this region + */ + + public int addMergedRegion(Region region) + { + return sheet.addMergedRegion(( short ) region.getRowFrom(), + region.getColumnFrom(), + ( short ) region.getRowTo(), + region.getColumnTo()); + } + + /** + * determines whether the output is vertically centered on the page. + * @param value true to vertically center, false otherwise. + */ + + public void setVerticallyCenter(boolean value) + { + VCenterRecord record = + ( VCenterRecord ) sheet.findFirstRecordBySid(VCenterRecord.sid); + + record.setVCenter(value); + } + + /** + * Determine whether printed output for this sheet will be vertically centered. + */ + + public boolean getVerticallyCenter(boolean value) + { + VCenterRecord record = + ( VCenterRecord ) sheet.findFirstRecordBySid(VCenterRecord.sid); + + return record.getVCenter(); + } + + /** + * removes a merged region of cells (hence letting them free) + * @param index of the region to unmerge + */ + + public void removeMergedRegion(int index) + { + sheet.removeMergedRegion(index); + } + + /** + * returns the number of merged regions + * @return number of merged regions + */ + + public int getNumMergedRegions() + { + return sheet.getNumMergedRegions(); + } + + /** + * gets the region at a particular index + * @param index of the region to fetch + * @return the merged region (simple eh?) + */ + + public Region getMergedRegionAt(int index) + { + return new Region(sheet.getMergedRegionAt(index)); + } + + /** + * @returns 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. + */ + + public Iterator rowIterator() + { + return rows.values().iterator(); + } + + /** + * used internally in the API to get the low level Sheet record represented by this + * Object. + * @return Sheet - low level representation of this HSSFSheet. + */ + + protected Sheet getSheet() + { + return sheet; + } + + /** + * whether alternate expression evaluation is on + * @param alternative expression evaluation or not + */ + + public void setAlternativeExpression(boolean b) + { + WSBoolRecord record = + ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + + record.setAlternateExpression(b); + } + + /** + * whether alternative formula entry is on + * @param alternative formulas or not + */ + + public void setAlternativeFormula(boolean b) + { + WSBoolRecord record = + ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + + record.setAlternateFormula(b); + } + + /** + * show automatic page breaks or not + * @param whether to show auto page breaks + */ + + public void setAutobreaks(boolean b) + { + WSBoolRecord record = + ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + + record.setAutobreaks(b); + } + + /** + * set whether sheet is a dialog sheet or not + * @param isDialog or not + */ + + public void setDialog(boolean b) + { + WSBoolRecord record = + ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + + record.setDialog(b); + } + + /** + * set whether to display the guts or not + * + * @param guts or no guts (or glory) + */ + + public void setDisplayGuts(boolean b) + { + WSBoolRecord record = + ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + + record.setDisplayGuts(b); + } + + /** + * fit to page option is on + * @param fit or not + */ + + public void setFitToPage(boolean b) + { + WSBoolRecord record = + ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + + record.setFitToPage(b); + } + + /** + * set if row summaries appear below detail in the outline + * @param below or not + */ + + public void setRowSumsBelow(boolean b) + { + WSBoolRecord record = + ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + + record.setRowSumsBelow(b); + } + + /** + * set if col summaries appear right of the detail in the outline + * @param right or not + */ + + public void setRowSumsRight(boolean b) + { + WSBoolRecord record = + ( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid); + + record.setRowSumsRight(b); + } + + /** + * whether alternate expression evaluation is on + * @return alternative expression evaluation or not + */ + + public boolean getAlternateExpression() + { + return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getAlternateExpression(); + } + + /** + * whether alternative formula entry is on + * @return alternative formulas or not + */ + + public boolean getAlternateFormula() + { + return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getAlternateFormula(); + } + + /** + * show automatic page breaks or not + * @return whether to show auto page breaks + */ + + public boolean getAutobreaks() + { + return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getAutobreaks(); + } + + /** + * get whether sheet is a dialog sheet or not + * @return isDialog or not + */ + + public boolean getDialog() + { + return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getDialog(); + } + + /** + * get whether to display the guts or not + * + * @return guts or no guts (or glory) + */ + + public boolean getDisplayGuts() + { + return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getDisplayGuts(); + } + + /** + * fit to page option is on + * @return fit or not + */ + + public boolean getFitToPage() + { + return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getFitToPage(); + } + + /** + * get if row summaries appear below detail in the outline + * @return below or not + */ + + public boolean getRowSumsBelow() + { + return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getRowSumsBelow(); + } + + /** + * get if col summaries appear right of the detail in the outline + * @return right or not + */ + + public boolean getRowSumsRight() + { + return (( WSBoolRecord ) sheet.findFirstRecordBySid(WSBoolRecord.sid)) + .getRowSumsRight(); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java new file mode 100644 index 000000000..6133d75ff --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -0,0 +1,534 @@ + +/* ==================================================================== + * 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 + * . + */ + +/* + * HSSFWorkbook.java + * + * Created on September 30, 2001, 3:37 PM + */ +package org.apache.poi.hssf.usermodel; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.POILogger; +import org.apache.poi.hssf.HSSFLog; +import org.apache.poi.hssf.model.Workbook; +import org.apache.poi.hssf.model.Sheet; +import org.apache.poi.hssf.record.*; + +/** + * High level representation of a workbook. This is the first object most users + * will construct whether they are reading or writing a workbook. It is also the + * top level object for creating new sheets/etc. + * + * @see org.apache.poi.hssf.model.Workbook + * @see org.apache.poi.hssf.usermodel.HSSFSheet + * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Glen Stampoultzis (gstamp at iprimus dot com dot au) + * @version 2.0-pre + */ + +public class HSSFWorkbook + extends java.lang.Object +{ + private static final int DEBUG = POILogger.DEBUG; + + /** + * used for compile-time performance/memory optimization. This determines the + * initial capacity for the sheet collection. Its currently set to 3. + * Changing it in this release will decrease performance + * since you're never allowed to have more or less than three sheets! + */ + + public final static int INITIAL_CAPACITY = 3; + + /** + * this is the reference to the low level Workbook object + */ + + private Workbook workbook; + + /** + * this holds the HSSFSheet objects attached to this workbook + */ + + private ArrayList sheets; + private static POILogger log = HSSFLog.getPOILogger(HSSFWorkbook.class); + + /** + * Creates new HSSFWorkbook from scratch (start here!) + * + */ + + public HSSFWorkbook() + { + workbook = Workbook.createWorkbook(); + sheets = new ArrayList(INITIAL_CAPACITY); + } + + /** + * given a POI POIFSFileSystem object, read in its Workbook and populate the high and + * low level models. If you're reading in a workbook...start here. + * + * @param fs the POI filesystem that contains the Workbook stream. + * @see org.apache.poi.poifs.filesystem.POIFSFileSystem + * @exception IOException if the stream cannot be read + */ + + public HSSFWorkbook(POIFSFileSystem fs) + throws IOException + { + sheets = new ArrayList(INITIAL_CAPACITY); + InputStream stream = fs.createDocumentInputStream("Workbook"); + List records = RecordFactory.createRecords(stream); + + workbook = Workbook.createWorkbook(records); + setPropertiesFromWorkbook(workbook); + int numRecords = workbook.getNumRecords(); + int sheetnum = 0; + + while (numRecords < records.size()) + { + Sheet sheet = Sheet.createSheet(records, sheetnum, numRecords); + + numRecords += sheet.getNumRecords(); + sheet.convertLabelRecords( + workbook); // convert all LabelRecord records to LabelSSTRecord + HSSFSheet hsheet = new HSSFSheet(workbook, sheet); + + sheets.add(hsheet); + + // workbook.setSheetName(sheets.size() -1, "Sheet"+sheets.size()); + } + } + + /** + * Companion to HSSFWorkbook(POIFSFileSystem), this constructs the POI filesystem around your + * inputstream. + * + * @param fs the POI filesystem that contains the Workbook stream. + * @see org.apache.poi.poifs.filesystem.POIFSFileSystem + * @see #HSSFWorkbook(POIFSFileSystem) + * @exception IOException if the stream cannot be read + */ + + public HSSFWorkbook(InputStream s) + throws IOException + { + this((new POIFSFileSystem(s))); + } + + /** + * used internally to set the workbook properties. + */ + + private void setPropertiesFromWorkbook(Workbook book) + { + this.workbook = book; + + // none currently + } + + /** + * set the sheet name. + * @param sheet number (0 based) + * @param sheet name + */ + + public void setSheetName(int sheet, String name) + { + if (sheet > (sheets.size() - 1)) + { + throw new RuntimeException("Sheet out of bounds"); + } + workbook.setSheetName(sheet, name); + } + + /** + * get the sheet name + * @param sheet Number + * @return Sheet name + */ + + public String getSheetName(int sheet) + { + if (sheet > (sheets.size() - 1)) + { + throw new RuntimeException("Sheet out of bounds"); + } + return workbook.getSheetName(sheet); + } + + /** + * get the sheet's index + * @param sheet name + * @return sheet index or -1 if it was not found. + */ + + public int getSheetIndex(String name) + { + int retval = -1; + + for (int k = 0; k < sheets.size(); k++) + { + String sheet = workbook.getSheetName(k); + + if (sheet.equals(name)) + { + retval = k; + break; + } + } + return retval; + } + + /** + * create an HSSFSheet for this HSSFWorkbook, adds it to the sheets and returns + * the high level representation. Use this to create new sheets. + * + * @return HSSFSheet representing the new sheet. + */ + + public HSSFSheet createSheet() + { + +// if (getNumberOfSheets() == 3) +// throw new RuntimeException("You cannot have more than three sheets in HSSF 1.0"); + HSSFSheet sheet = new HSSFSheet(workbook); + + sheets.add(sheet); + workbook.setSheetName(sheets.size() - 1, + "Sheet" + (sheets.size() - 1)); + return sheet; + } + + /** + * create an HSSFSheet for this HSSFWorkbook, adds it to the sheets and returns + * the high level representation. Use this to create new sheets. + * + * @param Sheetname to set for the sheet. + * @return HSSFSheet representing the new sheet. + */ + + public HSSFSheet createSheet(String sheetname) + { + +// if (getNumberOfSheets() == 3) +// throw new RuntimeException("You cannot have more than three sheets in HSSF 1.0"); + HSSFSheet sheet = new HSSFSheet(workbook); + + sheets.add(sheet); + workbook.setSheetName(sheets.size() - 1, sheetname); + return sheet; + } + + /** + * get the number of spreadsheets in the workbook (this will be three after serialization) + * @return number of sheets + */ + + public int getNumberOfSheets() + { + return sheets.size(); + } + + /** + * Get the HSSFSheet object at the given index. + * @param index of the sheet number (0-based physical & logical) + * @return HSSFSheet at the provided index + */ + + public HSSFSheet getSheetAt(int index) + { + return ( HSSFSheet ) sheets.get(index); + } + + /** + * Get sheet with the given name + * @param name of the sheet + * @return HSSFSheet with the name provided or null if it does not exist + */ + + public HSSFSheet getSheet(String name) + { + HSSFSheet retval = null; + + for (int k = 0; k < sheets.size(); k++) + { + String sheetname = workbook.getSheetName(k); + + if (sheetname.equals(name)) + { + retval = ( HSSFSheet ) sheets.get(k); + } + } + return retval; + } + + /** + * removes sheet at the given index + * @param index of the sheet (0-based) + */ + + public void removeSheetAt(int index) + { + sheets.remove(index); + workbook.removeSheet(index); + } + + /** + * determine whether the Excel GUI will backup the workbook when saving. + * + * @param backupValue true to indicate a backup will be performed. + */ + + public void setBackupFlag(boolean backupValue) + { + BackupRecord backupRecord = workbook.getBackupRecord(); + + backupRecord.setBackup(backupValue ? ( short ) 1 + : ( short ) 0); + } + + /** + * determine whether the Excel GUI will backup the workbook when saving. + * + * @return the current setting for backups. + */ + + public boolean getBackupFlag() + { + BackupRecord backupRecord = workbook.getBackupRecord(); + + return (backupRecord.getBackup() == 0) ? false + : true; + } + + /** + * create a new Font and add it to the workbook's font table + * @return new font object + */ + + public HSSFFont createFont() + { + FontRecord font = workbook.createNewFont(); + short fontindex = ( short ) (getNumberOfFonts() - 1); + + if (fontindex > 3) + { + fontindex++; // THERE IS NO FOUR!! + } + HSSFFont retval = new HSSFFont(fontindex, font); + + return retval; + } + + /** + * get the number of fonts in the font table + * @return number of fonts + */ + + public short getNumberOfFonts() + { + return ( short ) workbook.getNumberOfFontRecords(); + } + + /** + * get the font at the given index number + * @param index number + * @return HSSFFont at the index + */ + + public HSSFFont getFontAt(short idx) + { + FontRecord font = workbook.getFontRecordAt(idx); + HSSFFont retval = new HSSFFont(idx, font); + + return retval; + } + + /** + * create a new Cell style and add it to the workbook's style table + * @return the new Cell Style object + */ + + public HSSFCellStyle createCellStyle() + { + ExtendedFormatRecord xfr = workbook.createCellXF(); + short index = ( short ) (getNumCellStyles() - 1); + HSSFCellStyle style = new HSSFCellStyle(index, xfr); + + return style; + } + + /** + * get the number of styles the workbook contains + * @return count of cell styles + */ + + public short getNumCellStyles() + { + return ( short ) workbook.getNumExFormats(); + } + + /** + * get the cell style object at the given index + * @param index within the set of styles + * @return HSSFCellStyle object at the index + */ + + public HSSFCellStyle getCellStyleAt(short idx) + { + ExtendedFormatRecord xfr = workbook.getExFormatAt(idx); + HSSFCellStyle style = new HSSFCellStyle(idx, xfr); + + return style; + } + + /** + * Method write - write out this workbook to an Outputstream. Constructs + * a new POI POIFSFileSystem, passes in the workbook binary representation and + * writes it out. + * + * @param stream - the java OutputStream you wish to write the XLS to + * + * @exception IOException if anything can't be written. + * @see org.apache.poi.poifs.filesystem.POIFSFileSystem + */ + + public void write(OutputStream stream) + throws IOException + { + byte[] bytes = getBytes(); + POIFSFileSystem fs = new POIFSFileSystem(); + + fs.createDocument(new ByteArrayInputStream(bytes), "Workbook"); + fs.writeFilesystem(stream); + } + + /** + * Method getBytes - get the bytes of just the HSSF portions of the XLS file. + * Use this to construct a POI POIFSFileSystem yourself. + * + * + * @return byte[] array containing the binary representation of this workbook and all contained + * sheets, rows, cells, etc. + * + * @see org.apache.poi.hssf.model.Workbook + * @see org.apache.poi.hssf.model.Sheet + */ + + public byte [] getBytes() + { + log.log(DEBUG, "HSSFWorkbook.getBytes()"); + int wbsize = workbook.getSize(); + + // log.debug("REMOVEME: old sizing method "+workbook.serialize().length); + // ArrayList sheetbytes = new ArrayList(sheets.size()); + int sheetsize = 0; + int totalsize = wbsize; + + for (int k = 0; k < sheets.size(); k++) + { + workbook.setSheetBof(k, totalsize); + + // sheetbytes.add((( HSSFSheet ) sheets.get(k)).getSheet().getSize()); + totalsize += (( HSSFSheet ) sheets.get(k)).getSheet().getSize(); + } + if (totalsize < 4096) + { + totalsize = 4096; + } + byte[] retval = new byte[ totalsize ]; + int pos = workbook.serialize(0, retval); + + // System.arraycopy(wb, 0, retval, 0, wb.length); + for (int k = 0; k < sheets.size(); k++) + { + + // byte[] sb = (byte[])sheetbytes.get(k); + // System.arraycopy(sb, 0, retval, pos, sb.length); + pos += (( HSSFSheet ) sheets.get(k)).getSheet().serialize(pos, + retval); // sb.length; + } + for (int k = pos; k < totalsize; k++) + { + retval[ k ] = 0; + } + return retval; + } + + public int addSSTString(String string) + { + return workbook.addSSTString(string); + } + + public String getSSTString(int index) + { + return workbook.getSSTString(index); + } + + Workbook getWorkbook() + { + return workbook; + } +} diff --git a/src/java/org/apache/poi/hssf/util/HSSFColor.java b/src/java/org/apache/poi/hssf/util/HSSFColor.java new file mode 100644 index 000000000..5ba4291d4 --- /dev/null +++ b/src/java/org/apache/poi/hssf/util/HSSFColor.java @@ -0,0 +1,1538 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.util; + +import java.util.*; + +/** + * Intends to provide support for the very evil index to triplet issue and + * will likely replace the color contants interface for HSSF 2.0. + * This class contains static inner class members for representing colors. + * Each color has an index (for the standard palette in Excel (tm) ), + * native (RGB) triplet and string triplet. The string triplet is as the + * color would be represented by Gnumeric. Having (string) this here is a bit of a + * collusion of function between HSSF and the HSSFSerializer but I think its + * a reasonable one in this case. + * + * @author Andrew C. Oliver (acoliver at apache dot org) + */ + +public class HSSFColor +{ + private final static int PALETTE_SIZE = 50; + + /** Creates a new instance of HSSFColor */ + + public HSSFColor() + { + } + + /** + * this function returns all colors in a hastable. Its not implemented as a + * static member/staticly initialized because that would be dirty in a + * server environment as it is intended. This means you'll eat the time + * it takes to create it once per request but you will not hold onto it + * if you have none of those requests. + * + * @returns a hashtable containing all colors mapped to their gnumeric-like + * triplet string + */ + + public final static Hashtable getTripletHash() + { + Hashtable hash = new Hashtable(PALETTE_SIZE); + + hash.put(HSSFColor.BLACK.hexString, new HSSFColor.BLACK()); + hash.put(HSSFColor.BROWN.hexString, new HSSFColor.BROWN()); + hash.put(HSSFColor.OLIVE_GREEN.hexString, + new HSSFColor.OLIVE_GREEN()); + hash.put(HSSFColor.DARK_GREEN.hexString, new HSSFColor.DARK_GREEN()); + hash.put(HSSFColor.DARK_TEAL.hexString, new HSSFColor.DARK_TEAL()); + hash.put(HSSFColor.DARK_BLUE.hexString, new HSSFColor.DARK_BLUE()); + hash.put(HSSFColor.INDIGO.hexString, new HSSFColor.INDIGO()); + hash.put(HSSFColor.GREY_80_PERCENT.hexString, + new HSSFColor.GREY_80_PERCENT()); + hash.put(HSSFColor.ORANGE.hexString, new HSSFColor.ORANGE()); + hash.put(HSSFColor.DARK_YELLOW.hexString, + new HSSFColor.DARK_YELLOW()); + hash.put(HSSFColor.GREEN.hexString, new HSSFColor.GREEN()); + hash.put(HSSFColor.TEAL.hexString, new HSSFColor.TEAL()); + hash.put(HSSFColor.BLUE.hexString, new HSSFColor.BLUE()); + hash.put(HSSFColor.BLUE_GREY.hexString, new HSSFColor.BLUE_GREY()); + hash.put(HSSFColor.GREY_50_PERCENT.hexString, + new HSSFColor.GREY_50_PERCENT()); + hash.put(HSSFColor.RED.hexString, new HSSFColor.RED()); + hash.put(HSSFColor.LIGHT_ORANGE.hexString, + new HSSFColor.LIGHT_ORANGE()); + hash.put(HSSFColor.LIME.hexString, new HSSFColor.LIME()); + hash.put(HSSFColor.SEA_GREEN.hexString, new HSSFColor.SEA_GREEN()); + hash.put(HSSFColor.AQUA.hexString, new HSSFColor.AQUA()); + hash.put(HSSFColor.LIGHT_BLUE.hexString, new HSSFColor.LIGHT_BLUE()); + hash.put(HSSFColor.VIOLET.hexString, new HSSFColor.VIOLET()); + hash.put(HSSFColor.GREY_40_PERCENT.hexString, + new HSSFColor.GREY_40_PERCENT()); + hash.put(HSSFColor.PINK.hexString, new HSSFColor.PINK()); + hash.put(HSSFColor.GOLD.hexString, new HSSFColor.GOLD()); + hash.put(HSSFColor.YELLOW.hexString, new HSSFColor.YELLOW()); + hash.put(HSSFColor.BRIGHT_GREEN.hexString, + new HSSFColor.BRIGHT_GREEN()); + hash.put(HSSFColor.BRIGHT_GREEN.hexString, new HSSFColor.TURQUOISE()); + hash.put(HSSFColor.SKY_BLUE.hexString, new HSSFColor.SKY_BLUE()); + hash.put(HSSFColor.PLUM.hexString, new HSSFColor.PLUM()); + hash.put(HSSFColor.GREY_25_PERCENT.hexString, + new HSSFColor.GREY_25_PERCENT()); + hash.put(HSSFColor.ROSE.hexString, new HSSFColor.ROSE()); + hash.put(HSSFColor.LIGHT_YELLOW.hexString, + new HSSFColor.LIGHT_YELLOW()); + hash.put(HSSFColor.LIGHT_GREEN.hexString, + new HSSFColor.LIGHT_GREEN()); + hash.put(HSSFColor.LIGHT_TURQUOISE.hexString, + new HSSFColor.LIGHT_TURQUOISE()); + hash.put(HSSFColor.PALE_BLUE.hexString, new HSSFColor.PALE_BLUE()); + hash.put(HSSFColor.LAVENDER.hexString, new HSSFColor.LAVENDER()); + hash.put(HSSFColor.WHITE.hexString, new HSSFColor.WHITE()); + return hash; + } + + /** + * @returns index to the standard palet + */ + + public short getIndex() + { + return BLACK.index; + } + + /** + * @returns short[] triplet representation like that in Excel + */ + + public short [] getTriplet() + { + return BLACK.triplet; + } + + // its a hack but its a good hack + + /** + * @returns a hex string exactly like a gnumeric triplet + */ + + public String getHexString() + { + return BLACK.hexString; + } + + /** + * Class BLACK + * + * + * @author + * @version %I%, %G% + */ + + public final static class BLACK + extends HSSFColor + { + public final static short index = 0x0; + public final static short[] triplet = + { + 0, 0, 0 + }; + public final static String hexString = "0:0:0"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class BROWN + * + * + * @author + * @version %I%, %G% + */ + + public final static class BROWN + extends HSSFColor + { + public final static short index = 0x3c; + public final static short[] triplet = + { + 153, 51, 0 + }; + public final static String hexString = "9999:3333:0"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class OLIVE_GREEN + * + * + * @author + * @version %I%, %G% + */ + + public static class OLIVE_GREEN + extends HSSFColor + { + public final static short index = 0x3b; + public final static short[] triplet = + { + 51, 51, 0 + }; + public final static String hexString = "3333:3333:0"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class DARK_GREEN + * + * + * @author + * @version %I%, %G% + */ + + public final static class DARK_GREEN + extends HSSFColor + { + public final static short index = 0x3a; + public final static short[] triplet = + { + 0, 51, 0 + }; + public final static String hexString = "0:3333:0"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class DARK_TEAL + * + * + * @author + * @version %I%, %G% + */ + + public final static class DARK_TEAL + extends HSSFColor + { + public final static short index = 0x38; + public final static short[] triplet = + { + 0, 51, 102 + }; + public final static String hexString = "0:3333:6666"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class DARK_BLUE + * + * + * @author + * @version %I%, %G% + */ + + public final static class DARK_BLUE + extends HSSFColor + { + public final static short index = 0x12; + public final static short[] triplet = + { + 0, 0, 128 + }; + public final static String hexString = "0:0:8080"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class INDIGO + * + * + * @author + * @version %I%, %G% + */ + + public final static class INDIGO + extends HSSFColor + { + public final static short index = 0x3e; + public final static short[] triplet = + { + 51, 51, 153 + }; + public final static String hexString = "3333:3333:9999"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class GREY_80_PERCENT + * + * + * @author + * @version %I%, %G% + */ + + public final static class GREY_80_PERCENT + extends HSSFColor + { + public final static short index = 0x3f; + public final static short[] triplet = + { + 51, 51, 51 + }; + public final static String hexString = "3333:3333:3333"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class DARK_RED + * + * + * @author + * @version %I%, %G% + */ + + public final static class DARK_RED + extends HSSFColor + { + public final static short index = 0x10; + public final static short[] triplet = + { + 128, 0, 0 + }; + public final static String hexString = "8080:0:0"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class ORANGE + * + * + * @author + * @version %I%, %G% + */ + + public final static class ORANGE + extends HSSFColor + { + public final static short index = 0x35; + public final static short[] triplet = + { + 255, 102, 0 + }; + public final static String hexString = "FFFF:6666:0"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class DARK_YELLOW + * + * + * @author + * @version %I%, %G% + */ + + public final static class DARK_YELLOW + extends HSSFColor + { + public final static short index = 0x13; + public final static short[] triplet = + { + 128, 128, 0 + }; + public final static String hexString = "8080:8080:0"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class GREEN + * + * + * @author + * @version %I%, %G% + */ + + public final static class GREEN + extends HSSFColor + { + public final static short index = 0x11; + public final static short[] triplet = + { + 0, 128, 0 + }; + public final static String hexString = "0:8080:0"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class TEAL + * + * + * @author + * @version %I%, %G% + */ + + public final static class TEAL + extends HSSFColor + { + public final static short index = 0x15; + public final static short[] triplet = + { + 0, 128, 128 + }; + public final static String hexString = "0:8080:8080"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class BLUE + * + * + * @author + * @version %I%, %G% + */ + + public final static class BLUE + extends HSSFColor + { + public final static short index = 0xc; + public final static short[] triplet = + { + 0, 0, 255 + }; + public final static String hexString = "0:0:FFFF"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class BLUE_GREY + * + * + * @author + * @version %I%, %G% + */ + + public final static class BLUE_GREY + extends HSSFColor + { + public final static short index = 0x36; + public final static short[] triplet = + { + 102, 102, 153 + }; + public final static String hexString = "6666:6666:9999"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class GREY_50_PERCENT + * + * + * @author + * @version %I%, %G% + */ + + public final static class GREY_50_PERCENT + extends HSSFColor + { + public final static short index = 0x17; + public final static short[] triplet = + { + 128, 128, 128 + }; + public final static String hexString = "8080:8080:8080"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class RED + * + * + * @author + * @version %I%, %G% + */ + + public final static class RED + extends HSSFColor + { + public final static short index = 0xa; + public final static short[] triplet = + { + 255, 0, 0 + }; + public final static String hexString = "FFFF:0:0"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class LIGHT_ORANGE + * + * + * @author + * @version %I%, %G% + */ + + public final static class LIGHT_ORANGE + extends HSSFColor + { + public final static short index = 0x34; + public final static short[] triplet = + { + 255, 153, 0 + }; + public final static String hexString = "FFF:9999:0"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class LIME + * + * + * @author + * @version %I%, %G% + */ + + public final static class LIME + extends HSSFColor + { + public final static short index = 0x32; + public final static short[] triplet = + { + 153, 204, 0 + }; + public final static String hexString = "9999:CCCC:0"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class SEA_GREEN + * + * + * @author + * @version %I%, %G% + */ + + public final static class SEA_GREEN + extends HSSFColor + { + public final static short index = 0x39; + public final static short[] triplet = + { + 51, 153, 102 + }; + public final static String hexString = "3333:9999:6666"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class AQUA + * + * + * @author + * @version %I%, %G% + */ + + public final static class AQUA + extends HSSFColor + { + public final static short index = 0x31; + public final static short[] triplet = + { + 51, 204, 204 + }; + public final static String hexString = "3333:CCCC:CCCC"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class LIGHT_BLUE + * + * + * @author + * @version %I%, %G% + */ + + public final static class LIGHT_BLUE + extends HSSFColor + { + public final static short index = 0x30; + public final static short[] triplet = + { + 51, 102, 255 + }; + public final static String hexString = "3333:6666:FFFF"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class VIOLET + * + * + * @author + * @version %I%, %G% + */ + + public final static class VIOLET + extends HSSFColor + { + public final static short index = 0x14; + public final static short[] triplet = + { + 128, 0, 128 + }; + public final static String hexString = "8080:0:8080"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class GREY_40_PERCENT + * + * + * @author + * @version %I%, %G% + */ + + public final static class GREY_40_PERCENT + extends HSSFColor + { + public final static short index = 0x37; + public final static short[] triplet = + { + 150, 150, 150 + }; + public final static String hexString = "9696:9696:9696"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class PINK + * + * + * @author + * @version %I%, %G% + */ + + public final static class PINK + extends HSSFColor + { + public final static short index = 0xe; + public final static short[] triplet = + { + 255, 0, 255 + }; + public final static String hexString = "FFFF:0:FFFF"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class GOLD + * + * + * @author + * @version %I%, %G% + */ + + public final static class GOLD + extends HSSFColor + { + public final static short index = 0x33; + public final static short[] triplet = + { + 255, 204, 0 + }; + public final static String hexString = "FFFF:CCCC:0"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class YELLOW + * + * + * @author + * @version %I%, %G% + */ + + public final static class YELLOW + extends HSSFColor + { + public final static short index = 0xd; + public final static short[] triplet = + { + 255, 255, 0 + }; + public final static String hexString = "FFFF:FFFF:0"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class BRIGHT_GREEN + * + * + * @author + * @version %I%, %G% + */ + + public final static class BRIGHT_GREEN + extends HSSFColor + { + public final static short index = 0xb; + public final static short[] triplet = + { + 0, 255, 0 + }; + public final static String hexString = "0:FFFF:0"; + + public short getIndex() + { + return index; + } + + public String getHexString() + { + return hexString; + } + + public short [] getTriplet() + { + return triplet; + } + } + + /** + * Class TURQUOISE + * + * + * @author + * @version %I%, %G% + */ + + public final static class TURQUOISE + extends HSSFColor + { + public final static short index = 0xf; + public final static short[] triplet = + { + 0, 255, 255 + }; + public final static String hexString = "0:FFFF:FFFF"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class SKY_BLUE + * + * + * @author + * @version %I%, %G% + */ + + public final static class SKY_BLUE + extends HSSFColor + { + public final static short index = 0x28; + public final static short[] triplet = + { + 0, 204, 255 + }; + public final static String hexString = "0:CCCC:FFFF"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class PLUM + * + * + * @author + * @version %I%, %G% + */ + + public final static class PLUM + extends HSSFColor + { + public final static short index = 0x3d; + public final static short[] triplet = + { + 153, 51, 102 + }; + public final static String hexString = "9999:3333:6666"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class GREY_25_PERCENT + * + * + * @author + * @version %I%, %G% + */ + + public final static class GREY_25_PERCENT + extends HSSFColor + { + public final static short index = 0x16; + public final static short[] triplet = + { + 192, 192, 192 + }; + public final static String hexString = "C0C0:C0C0:C0C0"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class ROSE + * + * + * @author + * @version %I%, %G% + */ + + public final static class ROSE + extends HSSFColor + { + public final static short index = 0x2d; + public final static short[] triplet = + { + 255, 153, 204 + }; + public final static String hexString = "FFFF:9999:CCCC"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class TAN + * + * + * @author + * @version %I%, %G% + */ + + public final static class TAN + extends HSSFColor + { + public final static short index = 0x2f; + public final static short[] triplet = + { + 255, 204, 153 + }; + public final static String hexString = "FFFF:CCCC:9999"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class LIGHT_YELLOW + * + * + * @author + * @version %I%, %G% + */ + + public final static class LIGHT_YELLOW + extends HSSFColor + { + public final static short index = 0x2b; + public final static short[] triplet = + { + 255, 255, 153 + }; + public final static String hexString = "FFFF:FFFF:9999"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class LIGHT_GREEN + * + * + * @author + * @version %I%, %G% + */ + + public final static class LIGHT_GREEN + extends HSSFColor + { + public final static short index = 0x2a; + public final static short[] triplet = + { + 204, 255, 204 + }; + public final static String hexString = "CCCC:FFFF:CCCC"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class LIGHT_TURQUOISE + * + * + * @author + * @version %I%, %G% + */ + + public final static class LIGHT_TURQUOISE + extends HSSFColor + { + public final static short index = 0x29; + public final static short[] triplet = + { + 204, 255, 255 + }; + public final static String hexString = "CCCC:FFFF:FFFF"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class PALE_BLUE + * + * + * @author + * @version %I%, %G% + */ + + public final static class PALE_BLUE + extends HSSFColor + { + public final static short index = 0x2c; + public final static short[] triplet = + { + 153, 204, 255 + }; + public final static String hexString = "9999:CCCC:FFFF"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class LAVENDER + * + * + * @author + * @version %I%, %G% + */ + + public final static class LAVENDER + extends HSSFColor + { + public final static short index = 0x2e; + public final static short[] triplet = + { + 204, 153, 255 + }; + public final static String hexString = "CCCC:9999:FFFF"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } + + /** + * Class WHITE + * + * + * @author + * @version %I%, %G% + */ + + public final static class WHITE + extends HSSFColor + { + public final static short index = 0x9; + public final static short[] triplet = + { + 255, 255, 255 + }; + public final static String hexString = "FFFF:FFFF:FFFF"; + + public short getIndex() + { + return index; + } + + public short [] getTriplet() + { + return triplet; + } + + public String getHexString() + { + return hexString; + } + } +} diff --git a/src/java/org/apache/poi/hssf/util/Region.java b/src/java/org/apache/poi/hssf/util/Region.java new file mode 100644 index 000000000..8b32597ca --- /dev/null +++ b/src/java/org/apache/poi/hssf/util/Region.java @@ -0,0 +1,257 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.util; + +import org.apache.poi.hssf.record.MergeCellsRecord.MergedRegion; + +/** + * Represents a from/to row/col square. This is a object primitive + * that can be used to represent row,col - row,col just as one would use String + * to represent a string of characters. Its really only useful for HSSF though. + * + * @author Andrew C. Oliver acoliver at apache dot org + */ + +public class Region + implements Comparable +{ + private int rowFrom; + private short colFrom; + private int rowTo; + private short colTo; + + /** + * Creates a new instance of Region (0,0 - 0,0) + */ + + public Region() + { + } + + public Region(int rowFrom, short colFrom, int rowTo, short colTo) + { + this.rowFrom = rowFrom; + this.rowTo = rowTo; + this.colFrom = colFrom; + this.colTo = colTo; + } + + /** + * special constructor (I know this is bad but it is so wrong that its right + * okay) that makes a region from a mergedcells's region subrecord. + */ + + public Region(MergedRegion region) + { + this(region.row_from, region.col_from, region.row_to, region.col_to); + } + + /** + * get the upper left hand corner column number + * + * @return column number for the upper left hand corner + */ + + public short getColumnFrom() + { + return colFrom; + } + + /** + * get the upper left hand corner row number + * + * @return row number for the upper left hand corner + */ + + public int getRowFrom() + { + return rowFrom; + } + + /** + * get the lower right hand corner column number + * + * @return column number for the lower right hand corner + */ + + public short getColumnTo() + { + return colTo; + } + + /** + * get the lower right hand corner row number + * + * @return row number for the lower right hand corner + */ + + public int getRowTo() + { + return rowTo; + } + + /** + * set the upper left hand corner column number + * + * @param column number for the upper left hand corner + */ + + public void setColumnFrom(short colFrom) + { + this.colFrom = colFrom; + } + + /** + * set the upper left hand corner row number + * + * @param row number for the upper left hand corner + */ + + public void setRowFrom(int rowFrom) + { + this.rowFrom = rowFrom; + } + + /** + * set the lower right hand corner column number + * + * @param column number for the lower right hand corner + */ + + public void setColumnTo(short colTo) + { + this.colTo = colTo; + } + + /** + * get the lower right hand corner row number + * + * @param row number for the lower right hand corner + */ + + public void setRowTo(int rowTo) + { + this.rowTo = rowTo; + } + + /** + * Answers: "is the row/column inside this range?" + * + * @returns boolean - true if the cell is in the range and false if it is not + */ + + public boolean contains(int row, short col) + { + if ((this.rowFrom <= row) && (this.rowTo >= row) + && (this.colFrom <= col) && (this.colTo >= col)) + { + +// System.out.println("Region ("+rowFrom+","+colFrom+","+rowTo+","+ +// colTo+") does contain "+row+","+col); + return true; + } + return false; + } + + public boolean equals(Region r) + { + return (compareTo(r) == 0); + } + + /** + * Compares that the given region is the same less than or greater than this + * region. If any regional coordiant passed in is less than this regions + * coordinants then a positive integer is returned. Otherwise a negative + * integer is returned. + * + * @param region + * @see #compareTo(Object) + */ + + public int compareTo(Region r) + { + if ((this.getRowFrom() == r.getRowFrom()) + && (this.getColumnFrom() == r.getColumnFrom()) + && (this.getRowTo() == r.getRowTo()) + && (this.getColumnTo() == r.getColumnTo())) + { + return 0; + } + if ((this.getRowFrom() < r.getRowFrom()) + || (this.getColumnFrom() < r.getColumnFrom()) + || (this.getRowTo() < r.getRowTo()) + || (this.getColumnTo() < r.getColumnTo())) + { + return 1; + } + return -1; + } + + public int compareTo(Object o) + { + return compareTo(( Region ) o); + } + + /** + * @returns the area contained by this region (number of cells) + */ + + public int getArea() + { + return ((1 + (getRowTo() - getRowFrom())) + * (1 + (getColumnTo() - getColumnFrom()))); + } +} diff --git a/src/java/org/apache/poi/poifs/common/PoiFSConstants.java b/src/java/org/apache/poi/poifs/common/PoiFSConstants.java new file mode 100644 index 000000000..bf531dd47 --- /dev/null +++ b/src/java/org/apache/poi/poifs/common/PoiFSConstants.java @@ -0,0 +1,71 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.common; + +/** + * a repository for constants shared by POI classes + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public interface PoiFSConstants +{ + public static final int BIG_BLOCK_SIZE = 0x0200; + public static final int END_OF_CHAIN = -2; + public static final int PROPERTY_SIZE = 0x0080; + public static final int UNUSED_BLOCK = -1; +} // end public interface PoiFSConstants; + diff --git a/src/java/org/apache/poi/poifs/dev/POIFSViewEngine.java b/src/java/org/apache/poi/poifs/dev/POIFSViewEngine.java new file mode 100644 index 000000000..1f0f28963 --- /dev/null +++ b/src/java/org/apache/poi/poifs/dev/POIFSViewEngine.java @@ -0,0 +1,165 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.dev; + +import java.io.*; + +import java.util.*; + +/** + * This class contains methods used to inspect POIFSViewable objects + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class POIFSViewEngine +{ + private static final String _EOL = System.getProperty("line.separator"); + + /** + * Inspect an object that may be viewable, and drill down if told + * to + * + * @param viewable the object to be viewed + * @param drilldown if true, and the object implements + * POIFSViewable, inspect the objects' contents + * (recursively) + * @param indentLevel how far in to indent each string + * @param indentString string to use for indenting + * + * @return a List of Strings holding the content + */ + + public static List inspectViewable(final Object viewable, + final boolean drilldown, + final int indentLevel, + final String indentString) + { + List objects = new ArrayList(); + + if (viewable instanceof POIFSViewable) + { + POIFSViewable inspected = ( POIFSViewable ) viewable; + + objects.add(indent(indentLevel, indentString, + inspected.getShortDescription())); + if (drilldown) + { + if (inspected.preferArray()) + { + Object[] data = inspected.getViewableArray(); + + for (int j = 0; j < data.length; j++) + { + objects.addAll(inspectViewable(data[ j ], drilldown, + indentLevel + 1, + indentString)); + } + } + else + { + Iterator iter = inspected.getViewableIterator(); + + while (iter.hasNext()) + { + objects.addAll(inspectViewable(iter.next(), + drilldown, + indentLevel + 1, + indentString)); + } + } + } + } + else + { + objects.add(indent(indentLevel, indentString, + viewable.toString())); + } + return objects; + } + + private static String indent(final int indentLevel, + final String indentString, final String data) + { + StringBuffer finalBuffer = new StringBuffer(); + StringBuffer indentPrefix = new StringBuffer(); + + for (int j = 0; j < indentLevel; j++) + { + indentPrefix.append(indentString); + } + LineNumberReader reader = + new LineNumberReader(new StringReader(data)); + + try + { + String line = reader.readLine(); + + while (line != null) + { + finalBuffer.append(indentPrefix).append(line).append(_EOL); + line = reader.readLine(); + } + } + catch (IOException e) + { + finalBuffer.append(indentPrefix).append(e.getMessage()) + .append(_EOL); + } + return finalBuffer.toString(); + } +} // end public class POIFSViewEngine + diff --git a/src/java/org/apache/poi/poifs/dev/POIFSViewable.java b/src/java/org/apache/poi/poifs/dev/POIFSViewable.java new file mode 100644 index 000000000..714e74406 --- /dev/null +++ b/src/java/org/apache/poi/poifs/dev/POIFSViewable.java @@ -0,0 +1,115 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.dev; + +import java.util.Iterator; + +/** + * Interface for a drill-down viewable object. Such an object has + * content that may or may not be displayed, at the discretion of the + * viewer. The content is returned to the viewer as an array or as an + * Iterator, and the object provides a clue as to which technique the + * viewer should use to get its content. + * + * A POIFSViewable object is also expected to provide a short + * description of itself, that can be used by a viewer when the + * viewable object is collapsed. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public interface POIFSViewable +{ + + /** + * Get an array of objects, some of which may implement + * POIFSViewable + * + * @return an array of Object; may not be null, but may be empty + */ + + public Object [] getViewableArray(); + + /** + * Get an Iterator of objects, some of which may implement + * POIFSViewable + * + * @return an Iterator; may not be null, but may have an empty + * back end store + */ + + public Iterator getViewableIterator(); + + /** + * Give viewers a hint as to whether to call getViewableArray or + * getViewableIterator + * + * @return true if a viewer should call getViewableArray, false if + * a viewer should call getViewableIterator + */ + + public boolean preferArray(); + + /** + * Provides a short description of the object, to be used when a + * POIFSViewable object has not provided its contents. + * + * @return short description + */ + + public String getShortDescription(); +} // end public interface POIFSViewable + diff --git a/src/java/org/apache/poi/poifs/dev/POIFSViewer.java b/src/java/org/apache/poi/poifs/dev/POIFSViewer.java new file mode 100644 index 000000000..34eb12053 --- /dev/null +++ b/src/java/org/apache/poi/poifs/dev/POIFSViewer.java @@ -0,0 +1,130 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.dev; + +import java.io.*; + +import java.util.*; + +import org.apache.poi.poifs.filesystem.POIFSFileSystem; + +/** + * A simple viewer for POIFS files + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class POIFSViewer +{ + + /** + * Display the contents of multiple POIFS files + * + * @param args the names of the files to be displayed + */ + + public static void main(final String args[]) + { + if (args.length < 0) + { + System.err.println("Must specify at least one file to view"); + System.exit(1); + } + boolean printNames = (args.length > 1); + + for (int j = 0; j < args.length; j++) + { + viewFile(args[ j ], printNames); + } + } + + private static void viewFile(final String filename, + final boolean printName) + { + if (printName) + { + StringBuffer flowerbox = new StringBuffer(); + + flowerbox.append("."); + for (int j = 0; j < filename.length(); j++) + { + flowerbox.append("-"); + } + flowerbox.append("."); + System.out.println(flowerbox); + System.out.println("|" + filename + "|"); + System.out.println(flowerbox); + } + try + { + POIFSViewable fs = + new POIFSFileSystem(new FileInputStream(filename)); + List strings = POIFSViewEngine.inspectViewable(fs, true, + 0, " "); + Iterator iter = strings.iterator(); + + while (iter.hasNext()) + { + System.out.print(iter.next()); + } + } + catch (IOException e) + { + System.out.println(e.getMessage()); + } + } +} // end public class POIFSViewer + diff --git a/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java new file mode 100644 index 000000000..ad7f53476 --- /dev/null +++ b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java @@ -0,0 +1,364 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.eventfilesystem; + +import java.io.*; + +import java.util.*; + +import org.apache.poi.poifs.filesystem.DocumentInputStream; +import org.apache.poi.poifs.filesystem.POIFSDocument; +import org.apache.poi.poifs.filesystem.POIFSDocumentPath; +import org.apache.poi.poifs.property.DirectoryProperty; +import org.apache.poi.poifs.property.Property; +import org.apache.poi.poifs.property.PropertyTable; +import org.apache.poi.poifs.storage.BlockAllocationTableReader; +import org.apache.poi.poifs.storage.BlockList; +import org.apache.poi.poifs.storage.HeaderBlockReader; +import org.apache.poi.poifs.storage.RawDataBlockList; +import org.apache.poi.poifs.storage.SmallBlockTableReader; + +/** + * An event-driven reader for POIFS file systems. Users of this class + * first create an instance of it, then use the registerListener + * methods to register POIFSReaderListener instances for specific + * documents. Once all the listeners have been registered, the read() + * method is called, which results in the listeners being notified as + * their documents are read. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class POIFSReader +{ + private POIFSReaderRegistry registry; + private boolean registryClosed; + + /** + * Create a POIFSReader + */ + + public POIFSReader() + { + registry = new POIFSReaderRegistry(); + registryClosed = false; + } + + /** + * Read from an InputStream and process the documents we get + * + * @param stream the InputStream from which to read the data + * + * @exception IOException on errors reading, or on invalid data + */ + + public void read(final InputStream stream) + throws IOException + { + registryClosed = true; + + // read the header block from the stream + HeaderBlockReader header_block_reader = new HeaderBlockReader(stream); + + // read the rest of the stream into blocks + RawDataBlockList data_blocks = new RawDataBlockList(stream); + + // set up the block allocation table (necessary for the + // data_blocks to be manageable + new BlockAllocationTableReader(header_block_reader.getBATCount(), + header_block_reader.getBATArray(), + header_block_reader.getXBATCount(), + header_block_reader.getXBATIndex(), + data_blocks); + + // get property table from the document + PropertyTable properties = + new PropertyTable(header_block_reader.getPropertyStart(), + data_blocks); + + // process documents + processProperties(SmallBlockTableReader + .getSmallDocumentBlocks(data_blocks, properties + .getRoot(), header_block_reader + .getSBATStart()), data_blocks, properties.getRoot() + .getChildren(), new POIFSDocumentPath()); + } + + /** + * Register a POIFSReaderListener for all documents + * + * @param listener the listener to be registered + * + * @exception NullPointerException if listener is null + * @exception IllegalStateException if read() has already been + * called + */ + + public void registerListener(final POIFSReaderListener listener) + { + if (listener == null) + { + throw new NullPointerException(); + } + if (registryClosed) + { + throw new IllegalStateException(); + } + registry.registerListener(listener); + } + + /** + * Register a POIFSReaderListener for a document in the root + * directory + * + * @param listener the listener to be registered + * @param name the document name + * + * @exception NullPointerException if listener is null or name is + * null or empty + * @exception IllegalStateException if read() has already been + * called + */ + + public void registerListener(final POIFSReaderListener listener, + final String name) + { + registerListener(listener, null, name); + } + + /** + * Register a POIFSReaderListener for a document in the specified + * directory + * + * @param listener the listener to be registered + * @param path the document path; if null, the root directory is + * assumed + * @param name the document name + * + * @exception NullPointerException if listener is null or name is + * null or empty + * @exception IllegalStateException if read() has already been + * called + */ + + public void registerListener(final POIFSReaderListener listener, + final POIFSDocumentPath path, + final String name) + { + if ((listener == null) || (name == null) || (name.length() == 0)) + { + throw new NullPointerException(); + } + if (registryClosed) + { + throw new IllegalStateException(); + } + registry.registerListener(listener, + (path == null) ? new POIFSDocumentPath() + : path, name); + } + + /** + * read in files + * + * @param args names of the files + * + * @exception IOException + */ + + public static void main(String args[]) + throws IOException + { + if (args.length == 0) + { + System.err + .println("at least one argument required: input filename(s)"); + System.exit(1); + } + + // register for all + for (int j = 0; j < args.length; j++) + { + POIFSReader reader = new POIFSReader(); + POIFSReaderListener listener = new SampleListener(); + + reader.registerListener(listener); + System.out.println("reading " + args[ j ]); + FileInputStream istream = new FileInputStream(args[ j ]); + + reader.read(istream); + istream.close(); + } + } + + private void processProperties(final BlockList small_blocks, + final BlockList big_blocks, + final Iterator properties, + final POIFSDocumentPath path) + throws IOException + { + while (properties.hasNext()) + { + Property property = ( Property ) properties.next(); + String name = property.getName(); + + if (property.isDirectory()) + { + POIFSDocumentPath new_path = new POIFSDocumentPath(path, + new String[] + { + name + }); + + processProperties( + small_blocks, big_blocks, + (( DirectoryProperty ) property).getChildren(), new_path); + } + else + { + int startBlock = property.getStartBlock(); + Iterator listeners = registry.getListeners(path, name); + + if (listeners.hasNext()) + { + int size = property.getSize(); + POIFSDocument document = null; + + if (property.shouldUseSmallBlocks()) + { + document = + new POIFSDocument(name, small_blocks + .fetchBlocks(startBlock), size); + } + else + { + document = + new POIFSDocument(name, big_blocks + .fetchBlocks(startBlock), size); + } + while (listeners.hasNext()) + { + POIFSReaderListener listener = + ( POIFSReaderListener ) listeners.next(); + + listener.processPOIFSReaderEvent( + new POIFSReaderEvent( + new DocumentInputStream(document), path, + name)); + } + } + else + { + + // consume the document's data and discard it + if (property.shouldUseSmallBlocks()) + { + small_blocks.fetchBlocks(startBlock); + } + else + { + big_blocks.fetchBlocks(startBlock); + } + } + } + } + } + + private static class SampleListener + implements POIFSReaderListener + { + + /** + * Constructor SampleListener + */ + + SampleListener() + { + } + + /** + * Method processPOIFSReaderEvent + * + * @param event + */ + + public void processPOIFSReaderEvent(final POIFSReaderEvent event) + { + DocumentInputStream istream = event.getStream(); + POIFSDocumentPath path = event.getPath(); + String name = event.getName(); + + try + { + byte[] data = new byte[ istream.available() ]; + + istream.read(data); + int pathLength = path.length(); + + for (int k = 0; k < pathLength; k++) + { + System.out.print("/" + path.getComponent(k)); + } + System.out.println("/" + name + ": " + data.length + + " bytes read"); + } + catch (IOException ignored) + { + } + } + } // end private class SampleListener +} // end public class POIFSReader + diff --git a/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReaderEvent.java b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReaderEvent.java new file mode 100644 index 000000000..d98e71c46 --- /dev/null +++ b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReaderEvent.java @@ -0,0 +1,117 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.eventfilesystem; + +import org.apache.poi.poifs.filesystem.DocumentInputStream; +import org.apache.poi.poifs.filesystem.POIFSDocumentPath; + +/** + * Class POIFSReaderEvent + * + * @author Marc Johnson (mjohnson at apache dot org) + * @version %I%, %G% + */ + +public class POIFSReaderEvent +{ + private DocumentInputStream stream; + private POIFSDocumentPath path; + private String documentName; + + /** + * package scoped constructor + * + * @param stream the DocumentInputStream, freshly opened + * @param path the path of the document + * @param documentName the name of the document + */ + + POIFSReaderEvent(final DocumentInputStream stream, + final POIFSDocumentPath path, final String documentName) + { + this.stream = stream; + this.path = path; + this.documentName = documentName; + } + + /** + * @return the DocumentInputStream, freshly opened + */ + + public DocumentInputStream getStream() + { + return stream; + } + + /** + * @return the document's path + */ + + public POIFSDocumentPath getPath() + { + return path; + } + + /** + * @return the document's name + */ + + public String getName() + { + return documentName; + } +} // end public class POIFSReaderEvent + diff --git a/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReaderListener.java b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReaderListener.java new file mode 100644 index 000000000..f95bf6dd6 --- /dev/null +++ b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReaderListener.java @@ -0,0 +1,77 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.eventfilesystem; + +/** + * Interface POIFSReaderListener + * + * @author Marc Johnson (mjohnson at apache dot org) + * @version %I%, %G% + */ + +public interface POIFSReaderListener +{ + + /** + * Process a POIFSReaderEvent that this listener had registered + * for + * + * @param event the POIFSReaderEvent + */ + + public void processPOIFSReaderEvent(POIFSReaderEvent event); +} // end public interface POIFSReaderListener + diff --git a/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReaderRegistry.java b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReaderRegistry.java new file mode 100644 index 000000000..a8f37945b --- /dev/null +++ b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReaderRegistry.java @@ -0,0 +1,221 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.eventfilesystem; + +import java.util.*; + +import org.apache.poi.poifs.filesystem.DocumentDescriptor; +import org.apache.poi.poifs.filesystem.POIFSDocumentPath; + +/** + * A registry for POIFSReaderListeners and the DocumentDescriptors of + * the documents those listeners are interested in + * + * @author Marc Johnson (mjohnson at apache dot org) + * @version %I%, %G% + */ + +class POIFSReaderRegistry +{ + + // the POIFSReaderListeners who listen to all POIFSReaderEvents + private Set omnivorousListeners; + + // Each mapping in this Map has a key consisting of a + // POIFSReaderListener and a value cosisting of a Set of + // DocumentDescriptors for the documents that POIFSReaderListener + // is interested in; used to efficiently manage the registry + private Map selectiveListeners; + + // Each mapping in this Map has a key consisting of a + // DocumentDescriptor and a value consisting of a Set of + // POIFSReaderListeners for the document matching that + // DocumentDescriptor; used when a document is found, to quickly + // get the listeners interested in that document + private Map chosenDocumentDescriptors; + + /** + * Construct the registry + */ + + POIFSReaderRegistry() + { + omnivorousListeners = new HashSet(); + selectiveListeners = new HashMap(); + chosenDocumentDescriptors = new HashMap(); + } + + /** + * register a POIFSReaderListener for a particular document + * + * @param listener the listener + * @param path the path of the document of interest + * @param documentName the name of the document of interest + */ + + void registerListener(final POIFSReaderListener listener, + final POIFSDocumentPath path, + final String documentName) + { + if (!omnivorousListeners.contains(listener)) + { + + // not an omnivorous listener (if it was, this method is a + // no-op) + Set descriptors = ( Set ) selectiveListeners.get(listener); + + if (descriptors == null) + { + + // this listener has not registered before + descriptors = new HashSet(); + selectiveListeners.put(listener, descriptors); + } + DocumentDescriptor descriptor = new DocumentDescriptor(path, + documentName); + + if (descriptors.add(descriptor)) + { + + // this listener wasn't already listening for this + // document -- add the listener to the set of + // listeners for this document + Set listeners = + ( Set ) chosenDocumentDescriptors.get(descriptor); + + if (listeners == null) + { + + // nobody was listening for this document before + listeners = new HashSet(); + chosenDocumentDescriptors.put(descriptor, listeners); + } + listeners.add(listener); + } + } + } + + /** + * register for all documents + * + * @param listener the listener who wants to get all documents + */ + + void registerListener(final POIFSReaderListener listener) + { + if (!omnivorousListeners.contains(listener)) + { + + // wasn't already listening for everything, so drop + // anything listener might have been listening for and + // then add the listener to the set of omnivorous + // listeners + removeSelectiveListener(listener); + omnivorousListeners.add(listener); + } + } + + /** + * get am iterator of listeners for a particular document + * + * @param path the document path + * @param name the name of the document + * + * @return an Iterator POIFSReaderListeners; may be empty + */ + + Iterator getListeners(final POIFSDocumentPath path, final String name) + { + Set rval = new HashSet(omnivorousListeners); + Set selectiveListeners = + ( Set ) chosenDocumentDescriptors.get(new DocumentDescriptor(path, + name)); + + if (selectiveListeners != null) + { + rval.addAll(selectiveListeners); + } + return rval.iterator(); + } + + private void removeSelectiveListener(final POIFSReaderListener listener) + { + Set selectedDescriptors = ( Set ) selectiveListeners.remove(listener); + + if (selectedDescriptors != null) + { + Iterator iter = selectedDescriptors.iterator(); + + while (iter.hasNext()) + { + dropDocument(listener, ( DocumentDescriptor ) iter.next()); + } + } + } + + private void dropDocument(final POIFSReaderListener listener, + final DocumentDescriptor descriptor) + { + Set listeners = ( Set ) chosenDocumentDescriptors.get(descriptor); + + listeners.remove(listener); + if (listeners.size() == 0) + { + chosenDocumentDescriptors.remove(descriptor); + } + } +} // end package scope class POIFSReaderRegistry + diff --git a/src/java/org/apache/poi/poifs/filesystem/BATManaged.java b/src/java/org/apache/poi/poifs/filesystem/BATManaged.java new file mode 100644 index 000000000..0c9b36bcc --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/BATManaged.java @@ -0,0 +1,85 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +/** + * This interface defines behaviors for objects managed by the Block + * Allocation Table (BAT). + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public interface BATManaged +{ + + /** + * Return the number of BigBlock's this instance uses + * + * @return count of BigBlock instances + */ + + public int countBlocks(); + + /** + * Set the start block for this instance + * + * @param index index into the array of BigBlock instances making + * up the the filesystem + */ + + public void setStartBlock(final int index); +} // end public interface BATManaged + diff --git a/src/java/org/apache/poi/poifs/filesystem/DirectoryEntry.java b/src/java/org/apache/poi/poifs/filesystem/DirectoryEntry.java new file mode 100644 index 000000000..87f3dd064 --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/DirectoryEntry.java @@ -0,0 +1,164 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +import java.io.*; + +import java.util.*; + +/** + * This interface defines methods specific to Directory objects + * managed by a Filesystem instance. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public interface DirectoryEntry + extends Entry +{ + + /** + * get an iterator of the Entry instances contained directly in + * this instance (in other words, children only; no grandchildren + * etc.) + * + * @return iterator; never null, but hasNext() may return false + * immediately (i.e., this DirectoryEntry is empty). All + * objects retrieved by next() are guaranteed to be + * implementations of Entry. + */ + + public Iterator getEntries(); + + /** + * is this DirectoryEntry empty? + * + * @return true if this instance contains no Entry instances + */ + + public boolean isEmpty(); + + /** + * find out how many Entry instances are contained directly within + * this DirectoryEntry + * + * @return number of immediately (no grandchildren etc.) contained + * Entry instances + */ + + public int getEntryCount(); + + /** + * get a specified Entry by name + * + * @param name the name of the Entry to obtain. + * + * @return the specified Entry, if it is directly contained in + * this DirectoryEntry + * + * @exception FileNotFoundException if no Entry with the specified + * name exists in this DirectoryEntry + */ + + public Entry getEntry(final String name) + throws FileNotFoundException; + + /** + * create a new DocumentEntry + * + * @param name the name of the new DocumentEntry + * @param stream the InputStream from which to create the new + * DocumentEntry + * + * @return the new DocumentEntry + * + * @exception IOException + */ + + public DocumentEntry createDocument(final String name, + final InputStream stream) + throws IOException; + + /** + * create a new DocumentEntry; the data will be provided later + * + * @param name the name of the new DocumentEntry + * @param size the size of the new DocumentEntry + * @param writer the writer of the new DocumentEntry + * + * @return the new DocumentEntry + * + * @exception IOException + */ + + public DocumentEntry createDocument(final String name, final int size, + final POIFSWriterListener writer) + throws IOException; + + /** + * create a new DirectoryEntry + * + * @param name the name of the new DirectoryEntry + * + * @return the new DirectoryEntry + * + * @exception IOException + */ + + public DirectoryEntry createDirectory(final String name) + throws IOException; +} // end public interface DirectoryEntry + diff --git a/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java b/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java new file mode 100644 index 000000000..58a712368 --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java @@ -0,0 +1,446 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +import java.io.*; + +import java.util.*; + +import org.apache.poi.poifs.dev.POIFSViewable; +import org.apache.poi.poifs.property.DirectoryProperty; +import org.apache.poi.poifs.property.DocumentProperty; +import org.apache.poi.poifs.property.Property; + +/** + * Simple implementation of DirectoryEntry + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class DirectoryNode + extends EntryNode + implements DirectoryEntry, POIFSViewable +{ + + // Map of Entry instances, keyed by their names + private Map _entries; + + // the POIFSFileSystem we belong to + private POIFSFileSystem _filesystem; + + // the path described by this document + private POIFSDocumentPath _path; + + /** + * create a DirectoryNode. This method is not public by design; it + * is intended strictly for the internal use of this package + * + * @param property the DirectoryProperty for this DirectoryEntry + * @param filesystem the POIFSFileSystem we belong to + * @param parent the parent of this entry + */ + + DirectoryNode(final DirectoryProperty property, + final POIFSFileSystem filesystem, + final DirectoryNode parent) + { + super(property, parent); + if (parent == null) + { + _path = new POIFSDocumentPath(); + } + else + { + _path = new POIFSDocumentPath(parent._path, new String[] + { + property.getName() + }); + } + _filesystem = filesystem; + _entries = new HashMap(); + Iterator iter = property.getChildren(); + + while (iter.hasNext()) + { + Property child = ( Property ) iter.next(); + Entry childNode = null; + + if (child.isDirectory()) + { + childNode = new DirectoryNode(( DirectoryProperty ) child, + _filesystem, this); + } + else + { + childNode = new DocumentNode(( DocumentProperty ) child, + this); + } + _entries.put(childNode.getName(), childNode); + } + } + + /** + * @return this directory's path representation + */ + + public POIFSDocumentPath getPath() + { + return _path; + } + + /** + * create a new DocumentEntry + * + * @param document the new document + * + * @return the new DocumentEntry + * + * @exception IOException + */ + + DocumentEntry createDocument(final POIFSDocument document) + throws IOException + { + DocumentProperty property = document.getDocumentProperty(); + DocumentNode rval = new DocumentNode(property, this); + + (( DirectoryProperty ) getProperty()).addChild(property); + _filesystem.addDocument(document); + _entries.put(property.getName(), rval); + return rval; + } + + /** + * Change a contained Entry's name + * + * @param oldName the original name + * @param newName the new name + * + * @return true if the operation succeeded, else false + */ + + boolean changeName(final String oldName, final String newName) + { + boolean rval = false; + EntryNode child = ( EntryNode ) _entries.get(oldName); + + if (child != null) + { + rval = (( DirectoryProperty ) getProperty()) + .changeName(child.getProperty(), newName); + if (rval) + { + _entries.remove(oldName); + _entries.put(child.getProperty().getName(), child); + } + } + return rval; + } + + /** + * Delete an entry + * + * @param entry the EntryNode to be deleted + * + * @return true if the entry was deleted, else false + */ + + boolean deleteEntry(final EntryNode entry) + { + boolean rval = + (( DirectoryProperty ) getProperty()) + .deleteChild(entry.getProperty()); + + if (rval) + { + _entries.remove(entry.getName()); + _filesystem.remove(entry); + } + return rval; + } + + /* ********** START implementation of DirectoryEntry ********** */ + + /** + * get an iterator of the Entry instances contained directly in + * this instance (in other words, children only; no grandchildren + * etc.) + * + * @return iterator; never null, but hasNext() may return false + * immediately (i.e., this DirectoryEntry is empty). All + * objects retrieved by next() are guaranteed to be + * implementations of Entry. + */ + + public Iterator getEntries() + { + return _entries.values().iterator(); + } + + /** + * is this DirectoryEntry empty? + * + * @return true if this instance contains no Entry instances + */ + + public boolean isEmpty() + { + return _entries.isEmpty(); + } + + /** + * find out how many Entry instances are contained directly within + * this DirectoryEntry + * + * @return number of immediately (no grandchildren etc.) contained + * Entry instances + */ + + public int getEntryCount() + { + return _entries.size(); + } + + /** + * get a specified Entry by name + * + * @param name the name of the Entry to obtain. + * + * @return the specified Entry, if it is directly contained in + * this DirectoryEntry + * + * @exception FileNotFoundException if no Entry with the specified + * name exists in this DirectoryEntry + */ + + public Entry getEntry(final String name) + throws FileNotFoundException + { + Entry rval = null; + + if (name != null) + { + rval = ( Entry ) _entries.get(name); + } + if (rval == null) + { + + // either a null name was given, or there is no such name + throw new FileNotFoundException("no such entry: \"" + name + + "\""); + } + return rval; + } + + /** + * create a new DocumentEntry + * + * @param name the name of the new DocumentEntry + * @param stream the InputStream from which to create the new + * DocumentEntry + * + * @return the new DocumentEntry + * + * @exception IOException + */ + + public DocumentEntry createDocument(final String name, + final InputStream stream) + throws IOException + { + return createDocument(new POIFSDocument(name, stream)); + } + + /** + * create a new DocumentEntry; the data will be provided later + * + * @param name the name of the new DocumentEntry + * @param size the size of the new DocumentEntry + * @param writer the writer of the new DocumentEntry + * + * @return the new DocumentEntry + * + * @exception IOException + */ + + public DocumentEntry createDocument(final String name, final int size, + final POIFSWriterListener writer) + throws IOException + { + return createDocument(new POIFSDocument(name, size, _path, writer)); + } + + /** + * create a new DirectoryEntry + * + * @param name the name of the new DirectoryEntry + * + * @return the new DirectoryEntry + * + * @exception IOException + */ + + public DirectoryEntry createDirectory(final String name) + throws IOException + { + DirectoryProperty property = new DirectoryProperty(name); + DirectoryNode rval = new DirectoryNode(property, _filesystem, + this); + + (( DirectoryProperty ) getProperty()).addChild(property); + _filesystem.addDirectory(property); + _entries.put(name, rval); + return rval; + } + + /* ********** END implementation of DirectoryEntry ********** */ + /* ********** START implementation of Entry ********** */ + + /** + * is this a DirectoryEntry? + * + * @return true if the Entry is a DirectoryEntry, else false + */ + + public boolean isDirectoryEntry() + { + return true; + } + + /* ********** END implementation of Entry ********** */ + /* ********** START extension of Entry ********** */ + + /** + * extensions use this method to verify internal rules regarding + * deletion of the underlying store. + * + * @return true if it's ok to delete the underlying store, else + * false + */ + + protected boolean isDeleteOK() + { + + // if this directory is empty, we can delete it + return isEmpty(); + } + + /* ********** END extension of Entry ********** */ + /* ********** START begin implementation of POIFSViewable ********** */ + + /** + * Get an array of objects, some of which may implement + * POIFSViewable + * + * @return an array of Object; may not be null, but may be empty + */ + + public Object [] getViewableArray() + { + return new Object[ 0 ]; + } + + /** + * Get an Iterator of objects, some of which may implement + * POIFSViewable + * + * @return an Iterator; may not be null, but may have an empty + * back end store + */ + + public Iterator getViewableIterator() + { + List components = new ArrayList(); + + components.add(getProperty()); + SortedMap sortedEntries = new TreeMap(_entries); + Iterator iter = sortedEntries.values().iterator(); + + while (iter.hasNext()) + { + components.add(iter.next()); + } + return components.iterator(); + } + + /** + * Give viewers a hint as to whether to call getViewableArray or + * getViewableIterator + * + * @return true if a viewer should call getViewableArray, false if + * a viewer should call getViewableIterator + */ + + public boolean preferArray() + { + return false; + } + + /** + * Provides a short description of the object, to be used when a + * POIFSViewable object has not provided its contents. + * + * @return short description + */ + + public String getShortDescription() + { + return getName(); + } + + /* ********** END begin implementation of POIFSViewable ********** */ +} // end public class DirectoryNode + diff --git a/src/java/org/apache/poi/poifs/filesystem/DocumentDescriptor.java b/src/java/org/apache/poi/poifs/filesystem/DocumentDescriptor.java new file mode 100644 index 000000000..41faad45a --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/DocumentDescriptor.java @@ -0,0 +1,153 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +/** + * Class DocumentDescriptor + * + * @author Marc Johnson (mjohnson at apache dot org) + * @version %I%, %G% + */ + +public class DocumentDescriptor +{ + private POIFSDocumentPath path; + private String name; + private int hashcode = 0; + + /** + * Trivial constructor + * + * @param path the Document path + * @param name the Document name + */ + + public DocumentDescriptor(final POIFSDocumentPath path, final String name) + { + if (path == null) + { + throw new NullPointerException("path must not be null"); + } + if (name == null) + { + throw new NullPointerException("name must not be null"); + } + if (name.length() == 0) + { + throw new IllegalArgumentException("name cannot be empty"); + } + this.path = path; + this.name = name; + } + + /** + * equality. Two DocumentDescriptor instances are equal if they + * have equal paths and names + * + * @param o the object we're checking equality for + * + * @return true if the object is equal to this object + */ + + public boolean equals(final Object o) + { + boolean rval = false; + + if ((o != null) && (o.getClass() == this.getClass())) + { + if (this == o) + { + rval = true; + } + else + { + DocumentDescriptor descriptor = ( DocumentDescriptor ) o; + + rval = this.path.equals(descriptor.path) + && this.name.equals(descriptor.name); + } + } + return rval; + } + + /** + * calculate and return the hashcode + * + * @return hashcode + */ + + public int hashCode() + { + if (hashcode == 0) + { + hashcode = path.hashCode() ^ name.hashCode(); + } + return hashcode; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(40 * (path.length() + 1)); + + for (int j = 0; j < path.length(); j++) + { + buffer.append(path.getComponent(j)).append("/"); + } + buffer.append(name); + return buffer.toString(); + } +} // end public class DocumentDescriptor + diff --git a/src/java/org/apache/poi/poifs/filesystem/DocumentEntry.java b/src/java/org/apache/poi/poifs/filesystem/DocumentEntry.java new file mode 100644 index 000000000..e14600ab3 --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/DocumentEntry.java @@ -0,0 +1,77 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +/** + * This interface defines methods specific to Document objects + * managed by a Filesystem instance. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public interface DocumentEntry + extends Entry +{ + + /** + * get the zize of the document, in bytes + * + * @return size in bytes + */ + + public int getSize(); +} // end public interface DocumentEntry + diff --git a/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java b/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java new file mode 100644 index 000000000..0f581aa36 --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java @@ -0,0 +1,487 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +import java.io.*; + +/** + * This class provides methods to read a DocumentEntry managed by a + * Filesystem instance. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class DocumentInputStream + extends InputStream +{ + + // current offset into the Document + private int _current_offset; + + // current marked offset into the Document (used by mark and + // reset) + private int _marked_offset; + + // the Document's size + private int _document_size; + + // have we been closed? + private boolean _closed; + + // the actual Document + private POIFSDocument _document; + + // buffer used to read one byte at a time + private byte[] _tiny_buffer; + + // returned by read operations if we're at end of document + static private final int EOD = -1; + + /** + * Create an InputStream from the specified DocumentEntry + * + * @param document the DocumentEntry to be read + * + * @exception IOException if the DocumentEntry cannot be opened + * (like, maybe it has been deleted?) + */ + + public DocumentInputStream(final DocumentEntry document) + throws IOException + { + _current_offset = 0; + _marked_offset = 0; + _document_size = document.getSize(); + _closed = false; + _tiny_buffer = null; + if (document instanceof DocumentNode) + { + _document = (( DocumentNode ) document).getDocument(); + } + else + { + throw new IOException("Cannot open internal document storage"); + } + } + + /** + * Create an InputStream from the specified Document + * + * @param document the Document to be read + * + * @exception IOException if the DocumentEntry cannot be opened + * (like, maybe it has been deleted?) + */ + + public DocumentInputStream(final POIFSDocument document) + throws IOException + { + _current_offset = 0; + _marked_offset = 0; + _document_size = document.getSize(); + _closed = false; + _tiny_buffer = null; + _document = document; + } + + /** + * Returns the number of bytes that can be read (or skipped over) + * from this input stream without blocking by the next caller of a + * method for this input stream. The next caller might be the same + * thread or or another thread. + * + * @return the number of bytes that can be read from this input + * stream without blocking. + * + * @exception IOException on error (such as the stream has been + * closed) + */ + + public int available() + throws IOException + { + dieIfClosed(); + return _document_size - _current_offset; + } + + /** + * Closes this input stream and releases any system resources + * associated with the stream. + * + * @exception IOException + */ + + public void close() + throws IOException + { + _closed = true; + } + + /** + * Marks the current position in this input stream. A subsequent + * call to the reset method repositions this stream at the last + * marked position so that subsequent reads re-read the same + * bytes. + *

+ * The readlimit arguments tells this input stream to allow that + * many bytes to be read before the mark position gets + * invalidated. This implementation, however, does not care. + *

+ * The general contract of mark is that, if the method + * markSupported returns true, the stream somehow remembers all + * the bytes read after the call to mark and stands ready to + * supply those same bytes again if and whenever the method reset + * is called. However, the stream is not required to remember any + * data at all if more than readlimit bytes are read from the + * stream before reset is called. But this stream will. + * + * @param ignoredReadlimit the maximum limit of bytes that can be + * read before the mark position becomes + * invalid. Ignored by this + * implementation. + */ + + public void mark(int ignoredReadlimit) + { + _marked_offset = _current_offset; + } + + /** + * Tests if this input stream supports the mark and reset methods. + * + * @return true + */ + + public boolean markSupported() + { + return true; + } + + /** + * Reads the next byte of data from the input stream. The value + * byte is returned as an int in the range 0 to 255. If no byte is + * available because the end of the stream has been reached, the + * value -1 is returned. The definition of this method in + * java.io.InputStream allows this method to block, but it won't. + * + * @return the next byte of data, or -1 if the end of the stream + * is reached. + * + * @exception IOException + */ + + public int read() + throws IOException + { + dieIfClosed(); + if (atEOD()) + { + return EOD; + } + if (_tiny_buffer == null) + { + _tiny_buffer = new byte[ 1 ]; + } + _document.read(_tiny_buffer, _current_offset++); + return _tiny_buffer[ 0 ]; + } + + /** + * Reads some number of bytes from the input stream and stores + * them into the buffer array b. The number of bytes actually read + * is returned as an integer. The definition of this method in + * java.io.InputStream allows this method to block, but it won't. + *

+ * If b is null, a NullPointerException is thrown. If the length + * of b is zero, then no bytes are read and 0 is returned; + * otherwise, there is an attempt to read at least one byte. If no + * byte is available because the stream is at end of file, the + * value -1 is returned; otherwise, at least one byte is read and + * stored into b. + *

+ * The first byte read is stored into element b[0], the next one + * into b[1], and so on. The number of bytes read is, at most, + * equal to the length of b. Let k be the number of bytes actually + * read; these bytes will be stored in elements b[0] through + * b[k-1], leaving elements b[k] through b[b.length-1] unaffected. + *

+ * If the first byte cannot be read for any reason other than end + * of file, then an IOException is thrown. In particular, an + * IOException is thrown if the input stream has been closed. + *

+ * The read(b) method for class InputStream has the same effect as: + *

+ * read(b, 0, b.length) + * + * @param b the buffer into which the data is read. + * + * @return the total number of bytes read into the buffer, or -1 + * if there is no more data because the end of the stream + * has been reached. + * + * @exception IOException + * @exception NullPointerException + */ + + public int read(final byte [] b) + throws IOException, NullPointerException + { + return read(b, 0, b.length); + } + + /** + * Reads up to len bytes of data from the input stream into an + * array of bytes. An attempt is made to read as many as len + * bytes, but a smaller number may be read, possibly zero. The + * number of bytes actually read is returned as an integer. + *

+ * The definition of this method in java.io.InputStream allows it + * to block, but it won't. + *

+ * If b is null, a NullPointerException is thrown. + *

+ * If off is negative, or len is negative, or off+len is greater + * than the length of the array b, then an + * IndexOutOfBoundsException is thrown. + *

+ * If len is zero, then no bytes are read and 0 is returned; + * otherwise, there is an attempt to read at least one byte. If no + * byte is available because the stream is at end of file, the + * value -1 is returned; otherwise, at least one byte is read and + * stored into b. + *

+ * The first byte read is stored into element b[off], the next one + * into b[off+1], and so on. The number of bytes read is, at most, + * equal to len. Let k be the number of bytes actually read; these + * bytes will be stored in elements b[off] through b[off+k-1], + * leaving elements b[off+k] through b[off+len-1] unaffected. + *

+ * In every case, elements b[0] through b[off] and elements + * b[off+len] through b[b.length-1] are unaffected. + *

+ * If the first byte cannot be read for any reason other than end + * of file, then an IOException is thrown. In particular, an + * IOException is thrown if the input stream has been closed. + * + * @param b the buffer into which the data is read. + * @param off the start offset in array b at which the data is + * written. + * @param len the maximum number of bytes to read. + * + * @return the total number of bytes read into the buffer, or -1 + * if there is no more data because the end of the stream + * has been reached. + * + * @exception IOException + * @exception NullPointerException + * @exception IndexOutOfBoundsException + */ + + public int read(final byte [] b, final int off, final int len) + throws IOException, NullPointerException, IndexOutOfBoundsException + { + dieIfClosed(); + if (b == null) + { + throw new NullPointerException("buffer is null"); + } + if ((off < 0) || (len < 0) || (b.length < (off + len))) + { + throw new IndexOutOfBoundsException( + "can't read past buffer boundaries"); + } + if (len == 0) + { + return 0; + } + if (atEOD()) + { + return EOD; + } + int limit = Math.min(available(), len); + + if ((off == 0) && (limit == b.length)) + { + _document.read(b, _current_offset); + } + else + { + byte[] buffer = new byte[ limit ]; + + _document.read(buffer, _current_offset); + System.arraycopy(buffer, 0, b, off, limit); + } + _current_offset += limit; + return limit; + } + + /** + * Repositions this stream to the position at the time the mark + * method was last called on this input stream. + *

+ * The general contract of reset is: + *

+ *

    + *
  • + * If the method markSupported returns true, then: + *
      + *
    • + * If the method mark has not been called since the + * stream was created, or the number of bytes read + * from the stream since mark was last called is + * larger than the argument to mark at that last + * call, then an IOException might be thrown. + *
    • + *
    • + * If such an IOException is not thrown, then the + * stream is reset to a state such that all the + * bytes read since the most recent call to mark + * (or since the start of the file, if mark has not + * been called) will be resupplied to subsequent + * callers of the read method, followed by any + * bytes that otherwise would have been the next + * input data as of the time of the call to reset. + *
    • + *
    + *
  • + *
  • + * If the method markSupported returns false, then: + *
      + *
    • + * The call to reset may throw an IOException. + *
    • + *
    • + * If an IOException is not thrown, then the + * stream is reset to a fixed state that depends + * on the particular type of the input and how it + * was created. The bytes that will be supplied to + * subsequent callers of the read method depend on + * the particular type of the input stream. + *
    • + *
    + *
  • + *
+ *

+ * All well and good ... this class's markSupported method returns + * true and this method does not care whether you've called mark + * at all, or whether you've exceeded the number of bytes + * specified in the last call to mark. We're basically walking a + * byte array ... mark and reset to your heart's content. + */ + + public void reset() + { + _current_offset = _marked_offset; + } + + /** + * Skips over and discards n bytes of data from this input + * stream. The skip method may, for a variety of reasons, end up + * skipping over some smaller number of bytes, possibly 0. This + * may result from any of a number of conditions; reaching end of + * file before n bytes have been skipped is only one + * possibility. The actual number of bytes skipped is returned. If + * n is negative, no bytes are skipped. + * + * @param n the number of bytes to be skipped. + * + * @return the actual number of bytes skipped. + * + * @exception IOException + */ + + public long skip(final long n) + throws IOException + { + dieIfClosed(); + if (n < 0) + { + return 0; + } + int new_offset = _current_offset + ( int ) n; + + if (new_offset < _current_offset) + { + + // wrap around in converting a VERY large long to an int + new_offset = _document_size; + } + else if (new_offset > _document_size) + { + new_offset = _document_size; + } + long rval = new_offset - _current_offset; + + _current_offset = new_offset; + return rval; + } + + private void dieIfClosed() + throws IOException + { + if (_closed) + { + throw new IOException( + "cannot perform requested operation on a closed stream"); + } + } + + private boolean atEOD() + { + return _current_offset == _document_size; + } +} // end public class DocumentInputStream + diff --git a/src/java/org/apache/poi/poifs/filesystem/DocumentNode.java b/src/java/org/apache/poi/poifs/filesystem/DocumentNode.java new file mode 100644 index 000000000..4f3048eae --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/DocumentNode.java @@ -0,0 +1,204 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +import java.util.*; + +import org.apache.poi.poifs.dev.POIFSViewable; +import org.apache.poi.poifs.property.DocumentProperty; + +/** + * Simple implementation of DocumentEntry + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class DocumentNode + extends EntryNode + implements DocumentEntry, POIFSViewable +{ + + // underlying POIFSDocument instance + private POIFSDocument _document; + + /** + * create a DocumentNode. This method is not public by design; it + * is intended strictly for the internal use of this package + * + * @param property the DocumentProperty for this DocumentEntry + * @param parent the parent of this entry + */ + + DocumentNode(final DocumentProperty property, final DirectoryNode parent) + { + super(property, parent); + _document = property.getDocument(); + } + + /** + * get the POIFSDocument + * + * @return the internal POIFSDocument + */ + + POIFSDocument getDocument() + { + return _document; + } + + /* ********** START implementation of DocumentEntry ********** */ + + /** + * get the zize of the document, in bytes + * + * @return size in bytes + */ + + public int getSize() + { + return getProperty().getSize(); + } + + /* ********** END implementation of DocumentEntry ********** */ + /* ********** START implementation of Entry ********** */ + + /** + * is this a DocumentEntry? + * + * @return true if the Entry is a DocumentEntry, else false + */ + + public boolean isDocumentEntry() + { + return true; + } + + /* ********** END implementation of Entry ********** */ + /* ********** START extension of Entry ********** */ + + /** + * extensions use this method to verify internal rules regarding + * deletion of the underlying store. + * + * @return true if it's ok to delete the underlying store, else + * false + */ + + protected boolean isDeleteOK() + { + return true; + } + + /* ********** END extension of Entry ********** */ + /* ********** START begin implementation of POIFSViewable ********** */ + + /** + * Get an array of objects, some of which may implement + * POIFSViewable + * + * @return an array of Object; may not be null, but may be empty + */ + + public Object [] getViewableArray() + { + return new Object[ 0 ]; + } + + /** + * Get an Iterator of objects, some of which may implement + * POIFSViewable + * + * @return an Iterator; may not be null, but may have an empty + * back end store + */ + + public Iterator getViewableIterator() + { + List components = new ArrayList(); + + components.add(getProperty()); + components.add(_document); + return components.iterator(); + } + + /** + * Give viewers a hint as to whether to call getViewableArray or + * getViewableIterator + * + * @return true if a viewer should call getViewableArray, false if + * a viewer should call getViewableIterator + */ + + public boolean preferArray() + { + return false; + } + + /** + * Provides a short description of the object, to be used when a + * POIFSViewable object has not provided its contents. + * + * @return short description + */ + + public String getShortDescription() + { + return getName(); + } + + /* ********** END begin implementation of POIFSViewable ********** */ +} // end public class DocumentNode + diff --git a/src/java/org/apache/poi/poifs/filesystem/DocumentOutputStream.java b/src/java/org/apache/poi/poifs/filesystem/DocumentOutputStream.java new file mode 100644 index 000000000..fa00e1ecf --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/DocumentOutputStream.java @@ -0,0 +1,214 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +import java.io.*; + +import java.util.*; + +/** + * This class provides a wrapper over an OutputStream so that Document + * writers can't accidently go over their size limits + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class DocumentOutputStream + extends OutputStream +{ + private OutputStream stream; + private int limit; + private int written; + + /** + * Create a DocumentOutputStream + * + * @param stream the OutputStream to which the data is actually + * read + * @param limit the maximum number of bytes that can be written + */ + + DocumentOutputStream(final OutputStream stream, final int limit) + { + this.stream = stream; + this.limit = limit; + this.written = 0; + } + + /** + * Writes the specified byte to this output stream. The general + * contract for write is that one byte is written to the output + * stream. The byte to be written is the eight low-order bits of + * the argument b. The 24 high-order bits of b are ignored. + * + * @param b the byte. + * @exception IOException if an I/O error occurs. In particular, + * an IOException may be thrown if the + * output stream has been closed, or if the + * writer tries to write too much data. + */ + + public void write(final int b) + throws IOException + { + limitCheck(1); + stream.write(b); + } + + /** + * Writes b.length bytes from the specified byte array + * to this output stream. + * + * @param b the data. + * @exception IOException if an I/O error occurs. + */ + + public void write(final byte b[]) + throws IOException + { + write(b, 0, b.length); + } + + /** + * Writes len bytes from the specified byte array starting at + * offset off to this output stream. The general contract for + * write(b, off, len) is that some of the bytes in the array b are + * written to the output stream in order; element b[off] is the + * first byte written and b[off+len-1] is the last byte written by + * this operation.

+ * If b is null, a NullPointerException is thrown.

+ * If off is negative, or len is negative, or off+len is greater + * than the length of the array b, then an + * IndexOutOfBoundsException is thrown. + * + * @param b the data. + * @param off the start offset in the data. + * @param len the number of bytes to write. + * @exception IOException if an I/O error occurs. In particular, + * an IOException is thrown if the + * output stream is closed or if the writer + * tries to write too many bytes. + */ + + public void write(final byte b[], final int off, final int len) + throws IOException + { + limitCheck(len); + stream.write(b, off, len); + } + + /** + * Flushes this output stream and forces any buffered output bytes + * to be written out. + * + * @exception IOException if an I/O error occurs. + */ + + public void flush() + throws IOException + { + stream.flush(); + } + + /** + * Closes this output stream and releases any system resources + * associated with this stream. The general contract of close is + * that it closes the output stream. A closed stream cannot + * perform output operations and cannot be reopened. + * + * @exception IOException if an I/O error occurs. + */ + + public void close() + throws IOException + { + + // ignore this call + } + + /** + * write the rest of the document's data (fill in at the end) + * + * @param totalLimit the actual number of bytes the corresponding + * document must fill + * @param fill the byte to fill remaining space with + * + * @exception IOException on I/O error + */ + + void writeFiller(final int totalLimit, final byte fill) + throws IOException + { + if (totalLimit > written) + { + byte[] filler = new byte[ totalLimit - written ]; + + Arrays.fill(filler, fill); + stream.write(filler); + } + } + + private void limitCheck(final int toBeWritten) + throws IOException + { + if ((written + toBeWritten) > limit) + { + throw new IOException("tried to write too much data"); + } + written += toBeWritten; + } +} // end public class DocumentOutputStream + diff --git a/src/java/org/apache/poi/poifs/filesystem/Entry.java b/src/java/org/apache/poi/poifs/filesystem/Entry.java new file mode 100644 index 000000000..501d06f7f --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/Entry.java @@ -0,0 +1,133 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +/** + * This interface provides access to an object managed by a Filesystem + * instance. Entry objects are further divided into DocumentEntry and + * DirectoryEntry instances. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public interface Entry +{ + + /** + * get the name of the Entry + * + * @return name + */ + + public String getName(); + + /** + * is this a DirectoryEntry? + * + * @return true if the Entry is a DirectoryEntry, else false + */ + + public boolean isDirectoryEntry(); + + /** + * is this a DocumentEntry? + * + * @return true if the Entry is a DocumentEntry, else false + */ + + public boolean isDocumentEntry(); + + /** + * get this Entry's parent (the DirectoryEntry that owns this + * Entry). All Entry objects, except the root Entry, has a parent. + * + * @return this Entry's parent; null iff this is the root Entry + */ + + public DirectoryEntry getParent(); + + /** + * Delete this Entry. This operation should succeed, but there are + * special circumstances when it will not: + * + * If this Entry is the root of the Entry tree, it cannot be + * deleted, as there is no way to create another one. + * + * If this Entry is a directory, it cannot be deleted unless it is + * empty. + * + * @return true if the Entry was successfully deleted, else false + */ + + public boolean delete(); + + /** + * Rename this Entry. This operation will fail if: + * + * There is a sibling Entry (i.e., an Entry whose parent is the + * same as this Entry's parent) with the same name. + * + * This Entry is the root of the Entry tree. Its name is dictated + * by the Filesystem and many not be changed. + * + * @param newName the new name for this Entry + * + * @return true if the operation succeeded, else false + */ + + public boolean renameTo(final String newName); +} // end public interface Entry + diff --git a/src/java/org/apache/poi/poifs/filesystem/EntryNode.java b/src/java/org/apache/poi/poifs/filesystem/EntryNode.java new file mode 100644 index 000000000..c0dbd54fa --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/EntryNode.java @@ -0,0 +1,231 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +import java.io.*; + +import java.util.*; + +import org.apache.poi.poifs.property.Property; + +/** + * Abstract implementation of Entry + * + * Extending classes should override isDocument() or isDirectory(), as + * appropriate + * + * Extending classes must override isDeleteOK() + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public abstract class EntryNode + implements Entry +{ + + // the DocumentProperty backing this object + private Property _property; + + // this object's parent Entry + private DirectoryNode _parent; + + /** + * create a DocumentNode. This method is not public by design; it + * is intended strictly for the internal use of extending classes + * + * @param property the Property for this Entry + * @param parent the parent of this entry + */ + + protected EntryNode(final Property property, final DirectoryNode parent) + { + _property = property; + _parent = parent; + } + + /** + * grant access to the property + * + * @return the property backing this entry + */ + + protected Property getProperty() + { + return _property; + } + + /** + * is this the root of the tree? + * + * @return true if so, else false + */ + + protected boolean isRoot() + { + + // only the root Entry has no parent ... + return (_parent == null); + } + + /** + * extensions use this method to verify internal rules regarding + * deletion of the underlying store. + * + * @return true if it's ok to delete the underlying store, else + * false + */ + + protected abstract boolean isDeleteOK(); + + /* ********** START implementation of Entry ********** */ + + /** + * get the name of the Entry + * + * @return name + */ + + public String getName() + { + return _property.getName(); + } + + /** + * is this a DirectoryEntry? + * + * @return true if the Entry is a DirectoryEntry, else false + */ + + public boolean isDirectoryEntry() + { + return false; + } + + /** + * is this a DocumentEntry? + * + * @return true if the Entry is a DocumentEntry, else false + */ + + public boolean isDocumentEntry() + { + return false; + } + + /** + * get this Entry's parent (the DocumentEntry that owns this + * Entry). All Entry objects, except the root Entry, has a parent. + * + * @return this Entry's parent; null iff this is the root Entry + */ + + public DirectoryEntry getParent() + { + return _parent; + } + + /** + * Delete this Entry. This operation should succeed, but there are + * special circumstances when it will not: + * + * If this Entry is the root of the Entry tree, it cannot be + * deleted, as there is no way to create another one. + * + * If this Entry is a directory, it cannot be deleted unless it is + * empty. + * + * @return true if the Entry was successfully deleted, else false + */ + + public boolean delete() + { + boolean rval = false; + + if ((!isRoot()) && isDeleteOK()) + { + rval = _parent.deleteEntry(this); + } + return rval; + } + + /** + * Rename this Entry. This operation will fail if: + * + * There is a sibling Entry (i.e., an Entry whose parent is the + * same as this Entry's parent) with the same name. + * + * This Entry is the root of the Entry tree. Its name is dictated + * by the Filesystem and many not be changed. + * + * @param newName the new name for this Entry + * + * @return true if the operation succeeded, else false + */ + + public boolean renameTo(final String newName) + { + boolean rval = false; + + if (!isRoot()) + { + rval = _parent.changeName(getName(), newName); + } + return rval; + } + + /* ********** END implementation of Entry ********** */ +} // end public class EntryNode + diff --git a/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java b/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java new file mode 100644 index 000000000..907557de4 --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java @@ -0,0 +1,669 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +import java.io.*; + +import java.util.*; + +import org.apache.poi.poifs.common.PoiFSConstants; +import org.apache.poi.poifs.dev.POIFSViewable; +import org.apache.poi.poifs.property.DocumentProperty; +import org.apache.poi.poifs.property.Property; +import org.apache.poi.poifs.storage.BlockWritable; +import org.apache.poi.poifs.storage.ListManagedBlock; +import org.apache.poi.poifs.storage.DocumentBlock; +import org.apache.poi.poifs.storage.RawDataBlock; +import org.apache.poi.poifs.storage.SmallDocumentBlock; +import org.apache.poi.util.HexDump; + +/** + * This class manages a document in the POIFS filesystem. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class POIFSDocument + implements BATManaged, BlockWritable, POIFSViewable +{ + private DocumentProperty _property; + private int _size; + + // one of these stores will be valid + private SmallBlockStore _small_store; + private BigBlockStore _big_store; + + /** + * Constructor from large blocks + * + * @param name the name of the POIFSDocument + * @param blocks the big blocks making up the POIFSDocument + * @param length the actual length of the POIFSDocument + * + * @exception IOException + */ + + public POIFSDocument(final String name, final RawDataBlock [] blocks, + final int length) + throws IOException + { + _size = length; + _big_store = new BigBlockStore(blocks); + _property = new DocumentProperty(name, _size); + _small_store = new SmallBlockStore(new BlockWritable[ 0 ]); + _property.setDocument(this); + } + + /** + * Constructor from small blocks + * + * @param name the name of the POIFSDocument + * @param blocks the small blocks making up the POIFSDocument + * @param length the actual length of the POIFSDocument + */ + + public POIFSDocument(final String name, + final SmallDocumentBlock [] blocks, final int length) + { + _size = length; + try + { + _big_store = new BigBlockStore(new RawDataBlock[ 0 ]); + } + catch (IOException ignored) + { + + // can't happen with that constructor + } + _property = new DocumentProperty(name, _size); + _small_store = new SmallBlockStore(blocks); + _property.setDocument(this); + } + + /** + * Constructor from small blocks + * + * @param name the name of the POIFSDocument + * @param blocks the small blocks making up the POIFSDocument + * @param length the actual length of the POIFSDocument + * + * @exception IOException + */ + + public POIFSDocument(final String name, final ListManagedBlock [] blocks, + final int length) + throws IOException + { + _size = length; + _property = new DocumentProperty(name, _size); + _property.setDocument(this); + if (Property.isSmall(_size)) + { + _big_store = new BigBlockStore(new RawDataBlock[ 0 ]); + _small_store = new SmallBlockStore(blocks); + } + else + { + _big_store = new BigBlockStore(blocks); + _small_store = new SmallBlockStore(new BlockWritable[ 0 ]); + } + } + + /** + * Constructor + * + * @param name the name of the POIFSDocument + * @param stream the InputStream we read data from + * + * @exception IOException thrown on read errors + */ + + public POIFSDocument(final String name, final InputStream stream) + throws IOException + { + List blocks = new ArrayList(); + + _size = 0; + while (true) + { + DocumentBlock block = new DocumentBlock(stream); + int blockSize = block.size(); + + if (blockSize > 0) + { + blocks.add(block); + _size += blockSize; + } + if (block.partiallyRead()) + { + break; + } + } + DocumentBlock[] bigBlocks = + ( DocumentBlock [] ) blocks.toArray(new DocumentBlock[ 0 ]); + + _big_store = new BigBlockStore(bigBlocks); + _property = new DocumentProperty(name, _size); + _property.setDocument(this); + if (_property.shouldUseSmallBlocks()) + { + _small_store = + new SmallBlockStore(SmallDocumentBlock.convert(bigBlocks, + _size)); + _big_store = new BigBlockStore(new DocumentBlock[ 0 ]); + } + else + { + _small_store = new SmallBlockStore(new BlockWritable[ 0 ]); + } + } + + /** + * Constructor + * + * @param name the name of the POIFSDocument + * @param size the length of the POIFSDocument + * @param path the path of the POIFSDocument + * @param writer the writer who will eventually write the document + * contents + * + * @exception IOException thrown on read errors + */ + + public POIFSDocument(final String name, final int size, + final POIFSDocumentPath path, + final POIFSWriterListener writer) + throws IOException + { + _size = size; + _property = new DocumentProperty(name, _size); + _property.setDocument(this); + if (_property.shouldUseSmallBlocks()) + { + _small_store = new SmallBlockStore(path, name, size, writer); + _big_store = new BigBlockStore(new Object[ 0 ]); + } + else + { + _small_store = new SmallBlockStore(new BlockWritable[ 0 ]); + _big_store = new BigBlockStore(path, name, size, writer); + } + } + + /** + * return the array of SmallDocumentBlocks used + * + * @return array of SmallDocumentBlocks; may be empty, cannot be null + */ + + public BlockWritable [] getSmallBlocks() + { + return _small_store.getBlocks(); + } + + /** + * @return size of the document + */ + + public int getSize() + { + return _size; + } + + /** + * read data from the internal stores + * + * @param buffer the buffer to write to + * @param offset the offset into our storage to read from + */ + + void read(final byte [] buffer, final int offset) + { + if (_property.shouldUseSmallBlocks()) + { + SmallDocumentBlock.read(_small_store.getBlocks(), buffer, offset); + } + else + { + DocumentBlock.read(_big_store.getBlocks(), buffer, offset); + } + } + + /** + * Get the DocumentProperty + * + * @return the instance's DocumentProperty + */ + + DocumentProperty getDocumentProperty() + { + return _property; + } + + /* ********** START implementation of BlockWritable ********** */ + + /** + * Write the storage to an OutputStream + * + * @param stream the OutputStream to which the stored data should + * be written + * + * @exception IOException on problems writing to the specified + * stream + */ + + public void writeBlocks(final OutputStream stream) + throws IOException + { + _big_store.writeBlocks(stream); + } + + /* ********** END implementation of BlockWritable ********** */ + /* ********** START implementation of BATManaged ********** */ + + /** + * Return the number of BigBlock's this instance uses + * + * @return count of BigBlock instances + */ + + public int countBlocks() + { + return _big_store.countBlocks(); + } + + /** + * Set the start block for this instance + * + * @param index index into the array of blocks making up the + * filesystem + */ + + public void setStartBlock(final int index) + { + _property.setStartBlock(index); + } + + /* ********** END implementation of BATManaged ********** */ + /* ********** START begin implementation of POIFSViewable ********** */ + + /** + * Get an array of objects, some of which may implement + * POIFSViewable + * + * @return an array of Object; may not be null, but may be empty + */ + + public Object [] getViewableArray() + { + Object[] results = new Object[ 1 ]; + String result; + + try + { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + BlockWritable[] blocks = null; + + if (_big_store.isValid()) + { + blocks = _big_store.getBlocks(); + } + else if (_small_store.isValid()) + { + blocks = _small_store.getBlocks(); + } + if (blocks != null) + { + for (int k = 0; k < blocks.length; k++) + { + blocks[ k ].writeBlocks(output); + } + byte[] data = output.toByteArray(); + + if (data.length > _property.getSize()) + { + byte[] tmp = new byte[ _property.getSize() ]; + + System.arraycopy(data, 0, tmp, 0, tmp.length); + data = tmp; + } + output = new ByteArrayOutputStream(); + HexDump.dump(data, 0, output, 0); + result = output.toString(); + } + else + { + result = ""; + } + } + catch (IOException e) + { + result = e.getMessage(); + } + results[ 0 ] = result; + return results; + } + + /** + * Get an Iterator of objects, some of which may implement + * POIFSViewable + * + * @return an Iterator; may not be null, but may have an empty + * back end store + */ + + public Iterator getViewableIterator() + { + return Collections.EMPTY_LIST.iterator(); + } + + /** + * Give viewers a hint as to whether to call getViewableArray or + * getViewableIterator + * + * @return true if a viewer should call getViewableArray, false if + * a viewer should call getViewableIterator + */ + + public boolean preferArray() + { + return true; + } + + /** + * Provides a short description of the object, to be used when a + * POIFSViewable object has not provided its contents. + * + * @return short description + */ + + public String getShortDescription() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("Document: \"").append(_property.getName()) + .append("\""); + buffer.append(" size = ").append(getSize()); + return buffer.toString(); + } + + /* ********** END begin implementation of POIFSViewable ********** */ + private class SmallBlockStore + { + private SmallDocumentBlock[] smallBlocks; + private POIFSDocumentPath path; + private String name; + private int size; + private POIFSWriterListener writer; + + /** + * Constructor + * + * @param blocks blocks to construct the store from + */ + + SmallBlockStore(final Object [] blocks) + { + smallBlocks = new SmallDocumentBlock[ blocks.length ]; + for (int j = 0; j < blocks.length; j++) + { + smallBlocks[ j ] = ( SmallDocumentBlock ) blocks[ j ]; + } + this.path = null; + this.name = null; + this.size = -1; + this.writer = null; + } + + /** + * Constructor for a small block store that will be written + * later + * + * @param path path of the document + * @param name name of the document + * @param size length of the document + * @param writer the object that will eventually write the document + */ + + SmallBlockStore(final POIFSDocumentPath path, final String name, + final int size, final POIFSWriterListener writer) + { + smallBlocks = new SmallDocumentBlock[ 0 ]; + this.path = path; + this.name = name; + this.size = size; + this.writer = writer; + } + + /** + * @return true if this store is a valid source of data + */ + + boolean isValid() + { + return ((smallBlocks.length > 0) || (writer != null)); + } + + /** + * @return the SmallDocumentBlocks + */ + + BlockWritable [] getBlocks() + { + if (isValid() && (writer != null)) + { + ByteArrayOutputStream stream = + new ByteArrayOutputStream(size); + DocumentOutputStream dstream = + new DocumentOutputStream(stream, size); + + writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream, + path, name, size)); + smallBlocks = SmallDocumentBlock.convert(stream.toByteArray(), + size); + } + return smallBlocks; + } + } // end private class SmallBlockStore + + private class BigBlockStore + { + private DocumentBlock[] bigBlocks; + private POIFSDocumentPath path; + private String name; + private int size; + private POIFSWriterListener writer; + + /** + * Constructor + * + * @param blocks the blocks making up the store + * + * @exception IOException on I/O error + */ + + BigBlockStore(final Object [] blocks) + throws IOException + { + bigBlocks = new DocumentBlock[ blocks.length ]; + for (int j = 0; j < blocks.length; j++) + { + if (blocks[ j ] instanceof DocumentBlock) + { + bigBlocks[ j ] = ( DocumentBlock ) blocks[ j ]; + } + else + { + bigBlocks[ j ] = + new DocumentBlock(( RawDataBlock ) blocks[ j ]); + } + } + this.path = null; + this.name = null; + this.size = -1; + this.writer = null; + } + + /** + * Constructor for a big block store that will be written + * later + * + * @param path path of the document + * @param name name of the document + * @param size length of the document + * @param writer the object that will eventually write the + * document + */ + + BigBlockStore(final POIFSDocumentPath path, final String name, + final int size, final POIFSWriterListener writer) + { + bigBlocks = new DocumentBlock[ 0 ]; + this.path = path; + this.name = name; + this.size = size; + this.writer = writer; + } + + /** + * @return true if this store is a valid source of data + */ + + boolean isValid() + { + return ((bigBlocks.length > 0) || (writer != null)); + } + + /** + * @return the DocumentBlocks + */ + + DocumentBlock [] getBlocks() + { + if (isValid() && (writer != null)) + { + ByteArrayOutputStream stream = + new ByteArrayOutputStream(size); + DocumentOutputStream dstream = + new DocumentOutputStream(stream, size); + + writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream, + path, name, size)); + bigBlocks = DocumentBlock.convert(stream.toByteArray(), size); + } + return bigBlocks; + } + + /** + * write the blocks to a stream + * + * @param stream the stream to which the data is to be written + * + * @exception IOException on error + */ + + void writeBlocks(OutputStream stream) + throws IOException + { + if (isValid()) + { + if (writer != null) + { + DocumentOutputStream dstream = + new DocumentOutputStream(stream, size); + + writer.processPOIFSWriterEvent( + new POIFSWriterEvent(dstream, path, name, size)); + dstream.writeFiller(countBlocks() + * PoiFSConstants + .BIG_BLOCK_SIZE, DocumentBlock + .getFillByte()); + } + else + { + for (int k = 0; k < bigBlocks.length; k++) + { + bigBlocks[ k ].writeBlocks(stream); + } + } + } + } + + /** + * @return number of big blocks making up this document + */ + + int countBlocks() + { + int rval = 0; + + if (isValid()) + { + if (writer != null) + { + rval = (size + PoiFSConstants.BIG_BLOCK_SIZE - 1) + / PoiFSConstants.BIG_BLOCK_SIZE; + } + else + { + rval = bigBlocks.length; + } + } + return rval; + } + } // end private class BigBlockStore +} // end class POIFSDocument + diff --git a/src/java/org/apache/poi/poifs/filesystem/POIFSDocumentPath.java b/src/java/org/apache/poi/poifs/filesystem/POIFSDocumentPath.java new file mode 100644 index 000000000..3003729b1 --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/POIFSDocumentPath.java @@ -0,0 +1,314 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +import java.io.File; + +/** + * Class POIFSDocumentPath + * + * @author Marc Johnson (mjohnson at apache dot org) + * @version %I%, %G% + */ + +public class POIFSDocumentPath +{ + private String[] components; + private int hashcode = 0; + + /** + * constructor for the path of a document that is not in the root + * of the POIFSFileSystem + * + * @param components the Strings making up the path to a document. + * The Strings must be ordered as they appear in + * the directory hierarchy of the the document + * -- the first string must be the name of a + * directory in the root of the POIFSFileSystem, + * and every Nth (for N > 1) string thereafter + * must be the name of a directory in the + * directory identified by the (N-1)th string. + *

+ * If the components parameter is null or has + * zero length, the POIFSDocumentPath is + * appropriate for a document that is in the + * root of a POIFSFileSystem + * + * @exception IllegalArgumentException if any of the elements in + * the components parameter + * are null or have zero + * length + */ + + public POIFSDocumentPath(final String [] components) + throws IllegalArgumentException + { + if (components == null) + { + this.components = new String[ 0 ]; + } + else + { + this.components = new String[ components.length ]; + for (int j = 0; j < components.length; j++) + { + if ((components[ j ] == null) + || (components[ j ].length() == 0)) + { + throw new IllegalArgumentException( + "components cannot contain null or empty strings"); + } + this.components[ j ] = components[ j ]; + } + } + } + + /** + * simple constructor for the path of a document that is in the + * root of the POIFSFileSystem. The constructor that takes an + * array of Strings can also be used to create such a + * POIFSDocumentPath by passing it a null or empty String array + */ + + public POIFSDocumentPath() + { + this.components = new String[ 0 ]; + } + + /** + * constructor that adds additional subdirectories to an existing + * path + * + * @param path the existing path + * @param components the additional subdirectory names to be added + * + * @exception IllegalArgumentException if any of the Strings in + * components is null or zero + * length + */ + + public POIFSDocumentPath(final POIFSDocumentPath path, + final String [] components) + throws IllegalArgumentException + { + if (components == null) + { + this.components = new String[ path.components.length ]; + } + else + { + this.components = + new String[ path.components.length + components.length ]; + } + for (int j = 0; j < path.components.length; j++) + { + this.components[ j ] = path.components[ j ]; + } + if (components != null) + { + for (int j = 0; j < components.length; j++) + { + if ((components[ j ] == null) + || (components[ j ].length() == 0)) + { + throw new IllegalArgumentException( + "components cannot contain null or empty strings"); + } + this.components[ j + path.components.length ] = + components[ j ]; + } + } + } + + /** + * equality. Two POIFSDocumentPath instances are equal if they + * have the same number of component Strings, and if each + * component String is equal to its coresponding component String + * + * @param o the object we're checking equality for + * + * @return true if the object is equal to this object + */ + + public boolean equals(final Object o) + { + boolean rval = false; + + if ((o != null) && (o.getClass() == this.getClass())) + { + if (this == o) + { + rval = true; + } + else + { + POIFSDocumentPath path = ( POIFSDocumentPath ) o; + + if (path.components.length == this.components.length) + { + rval = true; + for (int j = 0; j < this.components.length; j++) + { + if (!path.components[ j ] + .equals(this.components[ j ])) + { + rval = false; + break; + } + } + } + } + } + return rval; + } + + /** + * calculate and return the hashcode + * + * @return hashcode + */ + + public int hashCode() + { + if (hashcode == 0) + { + for (int j = 0; j < components.length; j++) + { + hashcode += components[ j ].hashCode(); + } + } + return hashcode; + } + + /** + * @return the number of components + */ + + public int length() + { + return components.length; + } + + /** + * get the specified component + * + * @param n which component (0 ... length() - 1) + * + * @return the nth component; + * + * @exception ArrayIndexOutOfBoundsException if n < 0 or n >= + * length() + */ + + public String getComponent(int n) + throws ArrayIndexOutOfBoundsException + { + return components[ n ]; + } + + /** + *

Returns the path's parent or null if this path + * is the root path.

+ * + * @author Rainer Klute (klute@rainer-klute.de) + * @since 2002-01-24 + * + * @return path of parent, or null if this path is the root path + */ + + public POIFSDocumentPath getParent() + { + final int length = components.length - 1; + + if (length < 0) + { + return null; + } + POIFSDocumentPath parent = new POIFSDocumentPath(null); + + parent.components = new String[ length ]; + System.arraycopy(components, 0, parent.components, 0, length); + return parent; + } + + /** + *

Returns a string representation of the path. Components are + * separated by the platform-specific file separator.

+ * + * @author Rainer Klute (klute@rainer-klute.de) + * @since 2002-01-24 + * + * @return string representation + */ + + public String toString() + { + final StringBuffer b = new StringBuffer(); + final int l = length(); + + b.append(File.separatorChar); + for (int i = 0; i < l; i++) + { + b.append(getComponent(i)); + if (i < l - 1) + { + b.append(File.separatorChar); + } + } + return b.toString(); + } +} // end public class POIFSDocumentPath + diff --git a/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java b/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java new file mode 100644 index 000000000..de1ca3072 --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java @@ -0,0 +1,519 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +import java.io.*; + +import java.util.*; + +import org.apache.poi.poifs.common.PoiFSConstants; +import org.apache.poi.poifs.dev.POIFSViewable; +import org.apache.poi.poifs.property.DirectoryProperty; +import org.apache.poi.poifs.property.DocumentProperty; +import org.apache.poi.poifs.property.Property; +import org.apache.poi.poifs.property.PropertyTable; +import org.apache.poi.poifs.storage.BATBlock; +import org.apache.poi.poifs.storage.BlockAllocationTableReader; +import org.apache.poi.poifs.storage.BlockAllocationTableWriter; +import org.apache.poi.poifs.storage.BlockList; +import org.apache.poi.poifs.storage.BlockWritable; +import org.apache.poi.poifs.storage.HeaderBlockReader; +import org.apache.poi.poifs.storage.HeaderBlockWriter; +import org.apache.poi.poifs.storage.RawDataBlock; +import org.apache.poi.poifs.storage.RawDataBlockList; +import org.apache.poi.poifs.storage.SmallBlockTableReader; +import org.apache.poi.poifs.storage.SmallBlockTableWriter; +import org.apache.poi.poifs.storage.SmallDocumentBlock; + +/** + * This is the main class of the POIFS system; it manages the entire + * life cycle of the filesystem. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class POIFSFileSystem + implements POIFSViewable +{ + private PropertyTable _property_table; + private List _documents; + private DirectoryNode _root; + + /** + * Constructor, intended for writing + */ + + public POIFSFileSystem() + { + _property_table = new PropertyTable(); + _documents = new ArrayList(); + _root = null; + } + + /** + * Create a POIFSFileSystem from an InputStream + * + * @param stream the InputStream from which to read the data + * + * @exception IOException on errors reading, or on invalid data + */ + + public POIFSFileSystem(final InputStream stream) + throws IOException + { + this(); + + // read the header block from the stream + HeaderBlockReader header_block_reader = new HeaderBlockReader(stream); + + // read the rest of the stream into blocks + RawDataBlockList data_blocks = new RawDataBlockList(stream); + + // set up the block allocation table (necessary for the + // data_blocks to be manageable + new BlockAllocationTableReader(header_block_reader.getBATCount(), + header_block_reader.getBATArray(), + header_block_reader.getXBATCount(), + header_block_reader.getXBATIndex(), + data_blocks); + + // get property table from the document + PropertyTable properties = + new PropertyTable(header_block_reader.getPropertyStart(), + data_blocks); + + // init documents + processProperties(SmallBlockTableReader + .getSmallDocumentBlocks(data_blocks, properties + .getRoot(), header_block_reader + .getSBATStart()), data_blocks, properties.getRoot() + .getChildren(), null); + } + + /** + * Create a new document to be added to the root directory + * + * @param stream the InputStream from which the document's data + * will be obtained + * @param name the name of the new POIFSDocument + * + * @return the new DocumentEntry + * + * @exception IOException on error creating the new POIFSDocument + */ + + public DocumentEntry createDocument(final InputStream stream, + final String name) + throws IOException + { + return getRoot().createDocument(name, stream); + } + + /** + * create a new DocumentEntry in the root entry; the data will be + * provided later + * + * @param name the name of the new DocumentEntry + * @param size the size of the new DocumentEntry + * @param writer the writer of the new DocumentEntry + * + * @return the new DocumentEntry + * + * @exception IOException + */ + + public DocumentEntry createDocument(final String name, final int size, + final POIFSWriterListener writer) + throws IOException + { + return getRoot().createDocument(name, size, writer); + } + + /** + * create a new DirectoryEntry in the root directory + * + * @param name the name of the new DirectoryEntry + * + * @return the new DirectoryEntry + * + * @exception IOException on name duplication + */ + + public DirectoryEntry createDirectory(final String name) + throws IOException + { + return getRoot().createDirectory(name); + } + + /** + * Write the filesystem out + * + * @param stream the OutputStream to which the filesystem will be + * written + * + * @exception IOException thrown on errors writing to the stream + */ + + public void writeFilesystem(final OutputStream stream) + throws IOException + { + + // get the property table ready + _property_table.preWrite(); + + // create the small block store, and the SBAT + SmallBlockTableWriter sbtw = + new SmallBlockTableWriter(_documents, _property_table.getRoot()); + + // create the block allocation table + BlockAllocationTableWriter bat = + new BlockAllocationTableWriter(); + + // create a list of BATManaged objects: the documents plus the + // property table and the small block table + List bm_objects = new ArrayList(); + + bm_objects.addAll(_documents); + bm_objects.add(_property_table); + bm_objects.add(sbtw); + bm_objects.add(sbtw.getSBAT()); + + // walk the list, allocating space for each and assigning each + // a starting block number + Iterator iter = bm_objects.iterator(); + + while (iter.hasNext()) + { + BATManaged bmo = ( BATManaged ) iter.next(); + int block_count = bmo.countBlocks(); + + if (block_count != 0) + { + bmo.setStartBlock(bat.allocateSpace(block_count)); + } + else + { + + // Either the BATManaged object is empty or its data + // is composed of SmallBlocks; in either case, + // allocating space in the BAT is inappropriate + } + } + + // allocate space for the block allocation table and take its + // starting block + int batStartBlock = bat.createBlocks(); + + // get the extended block allocation table blocks + HeaderBlockWriter header_block_writer = new HeaderBlockWriter(); + BATBlock[] xbat_blocks = + header_block_writer.setBATBlocks(bat.countBlocks(), + batStartBlock); + + // set the property table start block + header_block_writer.setPropertyStart(_property_table.getStartBlock()); + + // set the small block allocation table start block + header_block_writer.setSBATStart(sbtw.getSBAT().getStartBlock()); + + // the header is now properly initialized. Make a list of + // writers (the header block, followed by the documents, the + // property table, the small block store, the small block + // allocation table, the block allocation table, and the + // extended block allocation table blocks) + List writers = new ArrayList(); + + writers.add(header_block_writer); + writers.addAll(_documents); + writers.add(_property_table); + writers.add(sbtw); + writers.add(sbtw.getSBAT()); + writers.add(bat); + for (int j = 0; j < xbat_blocks.length; j++) + { + writers.add(xbat_blocks[ j ]); + } + + // now, write everything out + iter = writers.iterator(); + while (iter.hasNext()) + { + BlockWritable writer = ( BlockWritable ) iter.next(); + + writer.writeBlocks(stream); + } + } + + /** + * read in a file and write it back out again + * + * @param args names of the files; arg[ 0 ] is the input file, + * arg[ 1 ] is the output file + * + * @exception IOException + */ + + public static void main(String args[]) + throws IOException + { + if (args.length != 2) + { + System.err.println( + "two arguments required: input filename and output filename"); + System.exit(1); + } + FileInputStream istream = new FileInputStream(args[ 0 ]); + FileOutputStream ostream = new FileOutputStream(args[ 1 ]); + + new POIFSFileSystem(istream).writeFilesystem(ostream); + istream.close(); + ostream.close(); + } + + /** + * get the root entry + * + * @return the root entry + */ + + public DirectoryEntry getRoot() + { + if (_root == null) + { + _root = new DirectoryNode(_property_table.getRoot(), this, null); + } + return _root; + } + + /** + * open a document in the root entry's list of entries + * + * @param documentName the name of the document to be opened + * + * @return a newly opened DocumentInputStream + * + * @exception IOException if the document does not exist or the + * name is that of a DirectoryEntry + */ + + public DocumentInputStream createDocumentInputStream( + final String documentName) + throws IOException + { + Entry document = getRoot().getEntry(documentName); + + if (!document.isDocumentEntry()) + { + throw new IOException("Entry '" + documentName + + "' is not a DocumentEntry"); + } + return new DocumentInputStream(( DocumentEntry ) document); + } + + /** + * add a new POIFSDocument + * + * @param document the POIFSDocument being added + */ + + void addDocument(final POIFSDocument document) + { + _documents.add(document); + _property_table.addProperty(document.getDocumentProperty()); + } + + /** + * add a new DirectoryProperty + * + * @param directory the DirectoryProperty being added + */ + + void addDirectory(final DirectoryProperty directory) + { + _property_table.addProperty(directory); + } + + /** + * remove an entry + * + * @param entry to be removed + */ + + void remove(EntryNode entry) + { + _property_table.removeProperty(entry.getProperty()); + if (entry.isDocumentEntry()) + { + _documents.remove((( DocumentNode ) entry).getDocument()); + } + } + + private void processProperties(final BlockList small_blocks, + final BlockList big_blocks, + final Iterator properties, + final DirectoryNode dir) + throws IOException + { + while (properties.hasNext()) + { + Property property = ( Property ) properties.next(); + String name = property.getName(); + DirectoryNode parent = (dir == null) + ? (( DirectoryNode ) getRoot()) + : dir; + + if (property.isDirectory()) + { + DirectoryNode new_dir = + ( DirectoryNode ) parent.createDirectory(name); + + processProperties( + small_blocks, big_blocks, + (( DirectoryProperty ) property).getChildren(), new_dir); + } + else + { + int startBlock = property.getStartBlock(); + int size = property.getSize(); + POIFSDocument document = null; + + if (property.shouldUseSmallBlocks()) + { + document = + new POIFSDocument(name, small_blocks + .fetchBlocks(startBlock), size); + } + else + { + document = + new POIFSDocument(name, + big_blocks.fetchBlocks(startBlock), + size); + } + parent.createDocument(document); + } + } + } + + /* ********** START begin implementation of POIFSViewable ********** */ + + /** + * Get an array of objects, some of which may implement + * POIFSViewable + * + * @return an array of Object; may not be null, but may be empty + */ + + public Object [] getViewableArray() + { + if (preferArray()) + { + return (( POIFSViewable ) getRoot()).getViewableArray(); + } + else + { + return new Object[ 0 ]; + } + } + + /** + * Get an Iterator of objects, some of which may implement + * POIFSViewable + * + * @return an Iterator; may not be null, but may have an empty + * back end store + */ + + public Iterator getViewableIterator() + { + if (!preferArray()) + { + return (( POIFSViewable ) getRoot()).getViewableIterator(); + } + else + { + return Collections.EMPTY_LIST.iterator(); + } + } + + /** + * Give viewers a hint as to whether to call getViewableArray or + * getViewableIterator + * + * @return true if a viewer should call getViewableArray, false if + * a viewer should call getViewableIterator + */ + + public boolean preferArray() + { + return (( POIFSViewable ) getRoot()).preferArray(); + } + + /** + * Provides a short description of the object, to be used when a + * POIFSViewable object has not provided its contents. + * + * @return short description + */ + + public String getShortDescription() + { + return "POIFS FileSystem"; + } + + /* ********** END begin implementation of POIFSViewable ********** */ +} // end public class POIFSFileSystem + diff --git a/src/java/org/apache/poi/poifs/filesystem/POIFSWriterEvent.java b/src/java/org/apache/poi/poifs/filesystem/POIFSWriterEvent.java new file mode 100644 index 000000000..e8e3d5503 --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/POIFSWriterEvent.java @@ -0,0 +1,128 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +/** + * Class POIFSWriterEvent + * + * @author Marc Johnson (mjohnson at apache dot org) + * @version %I%, %G% + */ + +public class POIFSWriterEvent +{ + private DocumentOutputStream stream; + private POIFSDocumentPath path; + private String documentName; + private int limit; + + /** + * package scoped constructor + * + * @param stream the DocumentOutputStream, freshly opened + * @param path the path of the document + * @param documentName the name of the document + * @param limit the limit, in bytes, that can be written to the + * stream + */ + + POIFSWriterEvent(final DocumentOutputStream stream, + final POIFSDocumentPath path, final String documentName, + final int limit) + { + this.stream = stream; + this.path = path; + this.documentName = documentName; + this.limit = limit; + } + + /** + * @return the DocumentOutputStream, freshly opened + */ + + public DocumentOutputStream getStream() + { + return stream; + } + + /** + * @return the document's path + */ + + public POIFSDocumentPath getPath() + { + return path; + } + + /** + * @return the document's name + */ + + public String getName() + { + return documentName; + } + + /** + * @return the limit on writing, in bytes + */ + + public int getLimit() + { + return limit; + } +} // end public class POIFSWriterEvent + diff --git a/src/java/org/apache/poi/poifs/filesystem/POIFSWriterListener.java b/src/java/org/apache/poi/poifs/filesystem/POIFSWriterListener.java new file mode 100644 index 000000000..9d79e9add --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/POIFSWriterListener.java @@ -0,0 +1,77 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.filesystem; + +/** + * Interface POIFSWriterListener + * + * @author Marc Johnson (mjohnson at apache dot org) + * @version %I%, %G% + */ + +public interface POIFSWriterListener +{ + + /** + * Process a POIFSWriterEvent that this listener had registered + * for + * + * @param event the POIFSWriterEvent + */ + + public void processPOIFSWriterEvent(POIFSWriterEvent event); +} // end public interface POIFSWriterListener + diff --git a/src/java/org/apache/poi/poifs/property/Child.java b/src/java/org/apache/poi/poifs/property/Child.java new file mode 100644 index 000000000..d92a03b5c --- /dev/null +++ b/src/java/org/apache/poi/poifs/property/Child.java @@ -0,0 +1,102 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.property; + +/** + * This interface defines methods for finding and setting sibling + * Property instances + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public interface Child +{ + + /** + * Get the next Child, if any + * + * @return the next Child; may return null + */ + + public Child getNextChild(); + + /** + * Get the previous Child, if any + * + * @return the previous Child; may return null + */ + + public Child getPreviousChild(); + + /** + * Set the next Child + * + * @param child the new 'next' child; may be null, which has the + * effect of saying there is no 'next' child + */ + + public void setNextChild(final Child child); + + /** + * Set the previous Child + * + * @param child the new 'previous' child; may be null, which has + * the effect of saying there is no 'previous' child + */ + + public void setPreviousChild(final Child child); +} // end public interface Child + diff --git a/src/java/org/apache/poi/poifs/property/DirectoryProperty.java b/src/java/org/apache/poi/poifs/property/DirectoryProperty.java new file mode 100644 index 000000000..deeb4afdc --- /dev/null +++ b/src/java/org/apache/poi/poifs/property/DirectoryProperty.java @@ -0,0 +1,310 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.property; + +import java.util.*; + +import java.io.IOException; + +import org.apache.poi.poifs.storage.SmallDocumentBlock; + +/** + * Directory property + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class DirectoryProperty + extends Property + implements Parent +{ + + // List of Property instances + private List _children; + + // set of children's names + private Set _children_names; + + /** + * Default constructor + * + * @param name the name of the directory + */ + + public DirectoryProperty(String name) + { + super(); + _children = new ArrayList(); + _children_names = new HashSet(); + setName(name); + setSize(0); + setPropertyType(PropertyConstants.DIRECTORY_TYPE); + setStartBlock(0); + setNodeColor(_NODE_BLACK); // simplification + } + + /** + * reader constructor + * + * @param index index number + * @param array byte data + * @param offset offset into byte data + */ + + protected DirectoryProperty(final int index, final byte [] array, + final int offset) + { + super(index, array, offset); + _children = new ArrayList(); + _children_names = new HashSet(); + } + + /** + * Change a Property's name + * + * @param property the Property whose name is being changed + * @param newName the new name for the Property + * + * @return true if the name change could be made, else false + */ + + public boolean changeName(final Property property, final String newName) + { + boolean result; + String oldName = property.getName(); + + property.setName(newName); + String cleanNewName = property.getName(); + + if (_children_names.contains(cleanNewName)) + { + + // revert the change + property.setName(oldName); + result = false; + } + else + { + _children_names.add(cleanNewName); + _children_names.remove(oldName); + result = true; + } + return result; + } + + /** + * Delete a Property + * + * @param property the Property being deleted + * + * @return true if the Property could be deleted, else false + */ + + public boolean deleteChild(final Property property) + { + boolean result = _children.remove(property); + + if (result) + { + _children_names.remove(property.getName()); + } + return result; + } + + private class PropertyComparator + implements Comparator + { + + /** + * Object equality, implemented as object identity + * + * @param o Object we're being compared to + * + * @return true if identical, else false + */ + + public boolean equals(Object o) + { + return this == o; + } + + /** + * compare method. Assumes both parameters are non-null + * instances of Property. One property is less than another if + * its name is shorter than the other property's name. If the + * names are the same length, the property whose name comes + * before the other property's name, alphabetically, is less + * than the other property. + * + * @param o1 first object to compare, better be a Property + * @param o2 second object to compare, better be a Property + * + * @return negative value if o1 < o2, + * zero if o1 == o2, + * positive value if o1 > o2. + */ + + public int compare(Object o1, Object o2) + { + String name1 = (( Property ) o1).getName(); + String name2 = (( Property ) o2).getName(); + int result = name1.length() - name2.length(); + + if (result == 0) + { + result = name1.compareTo(name2); + } + return result; + } + } // end private class PropertyComparator + + /* ********** START extension of Property ********** */ + + /** + * @return true if a directory type Property + */ + + public boolean isDirectory() + { + return true; + } + + /** + * Perform whatever activities need to be performed prior to + * writing + */ + + protected void preWrite() + { + if (_children.size() > 0) + { + Property[] children = + ( Property [] ) _children.toArray(new Property[ 0 ]); + + Arrays.sort(children, new PropertyComparator()); + int midpoint = children.length / 2; + + setChildProperty(children[ midpoint ].getIndex()); + children[ 0 ].setPreviousChild(null); + children[ 0 ].setNextChild(null); + for (int j = 1; j < midpoint; j++) + { + children[ j ].setPreviousChild(children[ j - 1 ]); + children[ j ].setNextChild(null); + } + if (midpoint != 0) + { + children[ midpoint ] + .setPreviousChild(children[ midpoint - 1 ]); + } + if (midpoint != (children.length - 1)) + { + children[ midpoint ].setNextChild(children[ midpoint + 1 ]); + for (int j = midpoint + 1; j < children.length - 1; j++) + { + children[ j ].setPreviousChild(null); + children[ j ].setNextChild(children[ j + 1 ]); + } + children[ children.length - 1 ].setPreviousChild(null); + children[ children.length - 1 ].setNextChild(null); + } + else + { + children[ midpoint ].setNextChild(null); + } + } + } + + /* ********** END extension of Property ********** */ + /* ********** START implementation of Parent ********** */ + + /** + * Get an iterator over the children of this Parent; all elements + * are instances of Property. + * + * @return Iterator of children; may refer to an empty collection + */ + + public Iterator getChildren() + { + return _children.iterator(); + } + + /** + * Add a new child to the collection of children + * + * @param property the new child to be added; must not be null + * + * @exception IOException if we already have a child with the same + * name + */ + + public void addChild(final Property property) + throws IOException + { + String name = property.getName(); + + if (_children_names.contains(name)) + { + throw new IOException("Duplicate name \"" + name + "\""); + } + _children_names.add(name); + _children.add(property); + } + + /* ********** END implementation of Parent ********** */ +} // end public class DirectoryProperty + diff --git a/src/java/org/apache/poi/poifs/property/DocumentProperty.java b/src/java/org/apache/poi/poifs/property/DocumentProperty.java new file mode 100644 index 000000000..487b7da3e --- /dev/null +++ b/src/java/org/apache/poi/poifs/property/DocumentProperty.java @@ -0,0 +1,162 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.property; + +import org.apache.poi.poifs.filesystem.POIFSDocument; + +/** + * Trivial extension of Property for POIFSDocuments + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class DocumentProperty + extends Property +{ + + // the POIFSDocument this property is associated with + private POIFSDocument _document; + + /** + * Constructor + * + * @param name POIFSDocument name + * @param size POIFSDocument size + */ + + public DocumentProperty(final String name, final int size) + { + super(); + _document = null; + setName(name); + setSize(size); + setNodeColor(_NODE_BLACK); // simplification + setPropertyType(PropertyConstants.DOCUMENT_TYPE); + } + + /** + * reader constructor + * + * @param index index number + * @param array byte data + * @param offset offset into byte data + */ + + protected DocumentProperty(final int index, final byte [] array, + final int offset) + { + super(index, array, offset); + _document = null; + } + + /** + * set the POIFSDocument + * + * @param doc the associated POIFSDocument + */ + + public void setDocument(POIFSDocument doc) + { + _document = doc; + } + + /** + * get the POIFSDocument + * + * @return the associated document + */ + + public POIFSDocument getDocument() + { + return _document; + } + + /* ********** START extension of Property ********** */ + + /** + * give method more visibility + * + * @return true if this property should use small blocks + */ + + public boolean shouldUseSmallBlocks() + { + return super.shouldUseSmallBlocks(); + } + + /** + * @return true if a directory type Property + */ + + public boolean isDirectory() + { + return false; + } + + /** + * Perform whatever activities need to be performed prior to + * writing + */ + + protected void preWrite() + { + + // do nothing + } + + /* ********** END extension of Property ********** */ +} // end public class DocumentProperty + diff --git a/src/java/org/apache/poi/poifs/property/Parent.java b/src/java/org/apache/poi/poifs/property/Parent.java new file mode 100644 index 000000000..fc2dd8baf --- /dev/null +++ b/src/java/org/apache/poi/poifs/property/Parent.java @@ -0,0 +1,114 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.property; + +import java.util.Iterator; + +import java.io.IOException; + +/** + * Behavior for parent (directory) properties + * + * @author Marc Johnson27591@hotmail.com + */ + +public interface Parent + extends Child +{ + + /** + * Get an iterator over the children of this Parent; all elements + * are instances of Property. + * + * @return Iterator of children; may refer to an empty collection + */ + + public Iterator getChildren(); + + /** + * Add a new child to the collection of children + * + * @param property the new child to be added; must not be null + * + * @exception IOException if the Parent already has a child with + * the same name + */ + + public void addChild(final Property property) + throws IOException; + + /** + * Set the previous Child + * + * @param child the new 'previous' child; may be null, which has + * the effect of saying there is no 'previous' child + */ + + public void setPreviousChild(final Child child); + + /** + * Set the next Child + * + * @param child the new 'next' child; may be null, which has the + * effect of saying there is no 'next' child + */ + + public void setNextChild(final Child child); + + /** *** end methods from interface Child *** */ + +} // end public interface Parent + diff --git a/src/java/org/apache/poi/poifs/property/Property.java b/src/java/org/apache/poi/poifs/property/Property.java new file mode 100644 index 000000000..d7560ab17 --- /dev/null +++ b/src/java/org/apache/poi/poifs/property/Property.java @@ -0,0 +1,576 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.property; + +import java.io.*; + +import java.util.*; + +import org.apache.poi.poifs.common.PoiFSConstants; +import org.apache.poi.poifs.dev.POIFSViewable; +import org.apache.poi.util.ByteField; +import org.apache.poi.util.IntegerField; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.ShortField; + +/** + * This abstract base class is the ancestor of all classes + * implementing POIFS Property behavior. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public abstract class Property + implements Child, POIFSViewable +{ + static final private byte _default_fill = ( byte ) 0x00; + static final private int _name_size_offset = 0x40; + static final private int _max_name_length = + (_name_size_offset / LittleEndianConsts.SHORT_SIZE) - 1; + static final protected int _NO_INDEX = -1; + + // useful offsets + static final private int _node_color_offset = 0x43; + static final private int _previous_property_offset = 0x44; + static final private int _next_property_offset = 0x48; + static final private int _child_property_offset = 0x4C; + static final private int _seconds_1_offset = 0x64; + static final private int _days_1_offset = 0x68; + static final private int _seconds_2_offset = 0x6C; + static final private int _days_2_offset = 0x70; + static final private int _start_block_offset = 0x74; + static final private int _size_offset = 0x78; + + // node colors + static final protected byte _NODE_BLACK = 1; + static final protected byte _NODE_RED = 0; + + // documents must be at least this size to be stored in big blocks + static final private int _big_block_minimum_bytes = 4096; + private String _name; + private ShortField _name_size; + private ByteField _property_type; + private ByteField _node_color; + private IntegerField _previous_property; + private IntegerField _next_property; + private IntegerField _child_property; + private IntegerField _seconds_1; + private IntegerField _days_1; + private IntegerField _seconds_2; + private IntegerField _days_2; + private IntegerField _start_block; + private IntegerField _size; + private byte[] _raw_data; + private int _index; + private Child _next_child; + private Child _previous_child; + + /** + * Default constructor + */ + + protected Property() + { + _raw_data = new byte[ PoiFSConstants.PROPERTY_SIZE ]; + Arrays.fill(_raw_data, _default_fill); + _name_size = new ShortField(_name_size_offset); + _property_type = + new ByteField(PropertyConstants.PROPERTY_TYPE_OFFSET); + _node_color = new ByteField(_node_color_offset); + _previous_property = new IntegerField(_previous_property_offset, + _NO_INDEX, _raw_data); + _next_property = new IntegerField(_next_property_offset, + _NO_INDEX, _raw_data); + _child_property = new IntegerField(_child_property_offset, + _NO_INDEX, _raw_data); + _seconds_1 = new IntegerField(_seconds_1_offset, 0, + _raw_data); + _days_1 = new IntegerField(_days_1_offset, 0, _raw_data); + _seconds_2 = new IntegerField(_seconds_2_offset, 0, + _raw_data); + _days_2 = new IntegerField(_days_2_offset, 0, _raw_data); + _start_block = new IntegerField(_start_block_offset); + _size = new IntegerField(_size_offset, 0, _raw_data); + _index = _NO_INDEX; + setName(""); + setNextChild(null); + setPreviousChild(null); + } + + /** + * Constructor from byte data + * + * @param index index number + * @param array byte data + * @param offset offset into byte data + */ + + protected Property(final int index, final byte [] array, final int offset) + { + _raw_data = new byte[ PoiFSConstants.PROPERTY_SIZE ]; + System.arraycopy(array, offset, _raw_data, 0, + PoiFSConstants.PROPERTY_SIZE); + _name_size = new ShortField(_name_size_offset, _raw_data); + _property_type = + new ByteField(PropertyConstants.PROPERTY_TYPE_OFFSET, _raw_data); + _node_color = new ByteField(_node_color_offset, _raw_data); + _previous_property = new IntegerField(_previous_property_offset, + _raw_data); + _next_property = new IntegerField(_next_property_offset, + _raw_data); + _child_property = new IntegerField(_child_property_offset, + _raw_data); + _seconds_1 = new IntegerField(_seconds_1_offset, _raw_data); + _days_1 = new IntegerField(_days_1_offset, _raw_data); + _seconds_2 = new IntegerField(_seconds_2_offset, _raw_data); + _days_2 = new IntegerField(_days_2_offset, _raw_data); + _start_block = new IntegerField(_start_block_offset, _raw_data); + _size = new IntegerField(_size_offset, _raw_data); + _index = index; + int name_length = (_name_size.get() / LittleEndianConsts.SHORT_SIZE) + - 1; + + if (name_length < 1) + { + _name = ""; + } + else + { + char[] char_array = new char[ name_length ]; + int name_offset = 0; + + for (int j = 0; j < name_length; j++) + { + char_array[ j ] = ( char ) new ShortField(name_offset, + _raw_data).get(); + name_offset += LittleEndianConsts.SHORT_SIZE; + } + _name = new String(char_array, 0, name_length); + } + _next_child = null; + _previous_child = null; + } + + /** + * Write the raw data to an OutputStream. + * + * @param stream the OutputStream to which the data should be + * written. + * + * @exception IOException on problems writing to the specified + * stream. + */ + + public void writeData(final OutputStream stream) + throws IOException + { + stream.write(_raw_data); + } + + /** + * Set the start block for the document referred to by this + * Property. + * + * @param startBlock the start block index + */ + + public void setStartBlock(final int startBlock) + { + _start_block.set(startBlock, _raw_data); + } + + /** + * @return the start block + */ + + public int getStartBlock() + { + return _start_block.get(); + } + + /** + * find out the document size + * + * @return size in bytes + */ + + public int getSize() + { + return _size.get(); + } + + /** + * Based on the currently defined size, should this property use + * small blocks? + * + * @return true if the size is less than _big_block_minimum_bytes + */ + + public boolean shouldUseSmallBlocks() + { + return Property.isSmall(_size.get()); + } + + /** + * does the length indicate a small document? + * + * @param length length in bytes + * + * @return true if the length is less than + * _big_block_minimum_bytes + */ + + public static boolean isSmall(final int length) + { + return length < _big_block_minimum_bytes; + } + + /** + * Get the name of this property + * + * @return property name as String + */ + + public String getName() + { + return _name; + } + + /** + * @return true if a directory type Property + */ + + abstract public boolean isDirectory(); + + /** + * Set the name; silently truncates the name if it's too long. + * + * @param name the new name + */ + + protected final void setName(final String name) + { + char[] char_array = name.toCharArray(); + int limit = Math.min(char_array.length, _max_name_length); + + _name = new String(char_array, 0, limit); + short offset = 0; + int j = 0; + + for (; j < limit; j++) + { + new ShortField(offset, ( short ) char_array[ j ], _raw_data); + offset += LittleEndianConsts.SHORT_SIZE; + } + for (; j < _max_name_length + 1; j++) + { + new ShortField(offset, ( short ) 0, _raw_data); + offset += LittleEndianConsts.SHORT_SIZE; + } + + // double the count, and include the null at the end + _name_size + .set(( short ) ((limit + 1) + * LittleEndianConsts.SHORT_SIZE), _raw_data); + } + + /** + * Set the property type. Makes no attempt to validate the value. + * + * @param propertyType the property type (root, file, directory) + */ + + protected void setPropertyType(final byte propertyType) + { + _property_type.set(propertyType, _raw_data); + } + + /** + * Set the node color. + * + * @param nodeColor the node color (red or black) + */ + + protected void setNodeColor(final byte nodeColor) + { + _node_color.set(nodeColor, _raw_data); + } + + /** + * Set the child property. + * + * @param child the child property's index in the Property Table + */ + + protected void setChildProperty(final int child) + { + _child_property.set(child, _raw_data); + } + + /** + * Get the child property (its index in the Property Table) + * + * @return child property index + */ + + protected int getChildIndex() + { + return _child_property.get(); + } + + /** + * Set the size of the document associated with this Property + * + * @param size the size of the document, in bytes + */ + + protected void setSize(final int size) + { + _size.set(size, _raw_data); + } + + /** + * Set the index for this Property + * + * @param index this Property's index within its containing + * Property Table + */ + + protected void setIndex(final int index) + { + _index = index; + } + + /** + * get the index for this Property + * + * @return the index of this Property within its Property Table + */ + + protected int getIndex() + { + return _index; + } + + /** + * Perform whatever activities need to be performed prior to + * writing + */ + + abstract protected void preWrite(); + + /** + * get the next sibling + * + * @return index of next sibling + */ + + int getNextChildIndex() + { + return _next_property.get(); + } + + /** + * get the previous sibling + * + * @return index of previous sibling + */ + + int getPreviousChildIndex() + { + return _previous_property.get(); + } + + /** + * determine whether the specified index is valid + * + * @param index value to be checked + * + * @return true if the index is valid + */ + + static boolean isValidIndex(int index) + { + return index != _NO_INDEX; + } + + /* ********** START implementation of Child ********** */ + + /** + * Get the next Child, if any + * + * @return the next Child; may return null + */ + + public Child getNextChild() + { + return _next_child; + } + + /** + * Get the previous Child, if any + * + * @return the previous Child; may return null + */ + + public Child getPreviousChild() + { + return _previous_child; + } + + /** + * Set the next Child + * + * @param child the new 'next' child; may be null, which has the + * effect of saying there is no 'next' child + */ + + public void setNextChild(final Child child) + { + _next_child = child; + _next_property.set((child == null) ? _NO_INDEX + : (( Property ) child) + .getIndex(), _raw_data); + } + + /** + * Set the previous Child + * + * @param child the new 'previous' child; may be null, which has + * the effect of saying there is no 'previous' child + */ + + public void setPreviousChild(final Child child) + { + _previous_child = child; + _previous_property.set((child == null) ? _NO_INDEX + : (( Property ) child) + .getIndex(), _raw_data); + } + + /* ********** END implementation of Child ********** */ + /* ********** START begin implementation of POIFSViewable ********** */ + + /** + * Get an array of objects, some of which may implement + * POIFSViewable + * + * @return an array of Object; may not be null, but may be empty + */ + + public Object [] getViewableArray() + { + Object[] results = new Object[ 5 ]; + + results[ 0 ] = "Name = \"" + getName() + "\""; + results[ 1 ] = "Property Type = " + _property_type.get(); + results[ 2 ] = "Node Color = " + _node_color.get(); + long time = _days_1.get(); + + time <<= 32; + time += (( long ) _seconds_1.get()) & 0x0000FFFFL; + results[ 3 ] = "Time 1 = " + time; + time = _days_2.get(); + time <<= 32; + time += (( long ) _seconds_2.get()) & 0x0000FFFFL; + results[ 4 ] = "Time 2 = " + time; + return results; + } + + /** + * Get an Iterator of objects, some of which may implement + * POIFSViewable + * + * @return an Iterator; may not be null, but may have an empty + * back end store + */ + + public Iterator getViewableIterator() + { + return Collections.EMPTY_LIST.iterator(); + } + + /** + * Give viewers a hint as to whether to call getViewableArray or + * getViewableIterator + * + * @return true if a viewer should call getViewableArray, false if + * a viewer should call getViewableIterator + */ + + public boolean preferArray() + { + return true; + } + + /** + * Provides a short description of the object, to be used when a + * POIFSViewable object has not provided its contents. + * + * @return short description + */ + + public String getShortDescription() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("Property: \"").append(getName()).append("\""); + return buffer.toString(); + } + + /* ********** END begin implementation of POIFSViewable ********** */ +} // end public abstract class Property + diff --git a/src/java/org/apache/poi/poifs/property/PropertyConstants.java b/src/java/org/apache/poi/poifs/property/PropertyConstants.java new file mode 100644 index 000000000..59b0dac4a --- /dev/null +++ b/src/java/org/apache/poi/poifs/property/PropertyConstants.java @@ -0,0 +1,75 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.property; + +/** + * Interface PropertyConstants + * + * + * @author + * @version %I%, %G% + */ + +public interface PropertyConstants +{ + public static final int PROPERTY_TYPE_OFFSET = 0x42; + + // the property types + public static final byte DIRECTORY_TYPE = 1; + public static final byte DOCUMENT_TYPE = 2; + public static final byte ROOT_TYPE = 5; +} // end public interface PropertyConstants + diff --git a/src/java/org/apache/poi/poifs/property/PropertyFactory.java b/src/java/org/apache/poi/poifs/property/PropertyFactory.java new file mode 100644 index 000000000..20f0dc1e8 --- /dev/null +++ b/src/java/org/apache/poi/poifs/property/PropertyFactory.java @@ -0,0 +1,139 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.property; + +import java.io.IOException; + +import java.util.*; + +import org.apache.poi.poifs.common.PoiFSConstants; +import org.apache.poi.poifs.storage.ListManagedBlock; + +/** + * Factory for turning an array of RawDataBlock instances containing + * Proprty data into an array of proper Property objects. + * + * The array produced may be sparse, in that any portion of data that + * should correspond to a Property, but which does not map to a proper + * Property (i.e., a DirectoryProperty, DocumentProperty, or + * RootProperty) will get mapped to a null Property in the array. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +class PropertyFactory +{ + + // no need for an accessible constructor + private PropertyFactory() + { + } + + /** + * Convert raw data blocks to an array of Property's + * + * @param blocks to be converted + * + * @return the converted List of Property objects. May contain + * nulls, but will not be null + * + * @exception IOException if any of the blocks are empty + */ + + static List convertToProperties(ListManagedBlock [] blocks) + throws IOException + { + List properties = new ArrayList(); + + for (int j = 0; j < blocks.length; j++) + { + byte[] data = blocks[ j ].getData(); + int property_count = data.length + / PoiFSConstants.PROPERTY_SIZE; + int offset = 0; + + for (int k = 0; k < property_count; k++) + { + switch (data[ offset + PropertyConstants.PROPERTY_TYPE_OFFSET ]) + { + + case PropertyConstants.DIRECTORY_TYPE : + properties + .add(new DirectoryProperty(properties.size(), + data, offset)); + break; + + case PropertyConstants.DOCUMENT_TYPE : + properties.add(new DocumentProperty(properties.size(), + data, offset)); + break; + + case PropertyConstants.ROOT_TYPE : + properties.add(new RootProperty(properties.size(), + data, offset)); + break; + + default : + properties.add(null); + break; + } + offset += PoiFSConstants.PROPERTY_SIZE; + } + } + return properties; + } +} // end package scope class PropertyFactory + diff --git a/src/java/org/apache/poi/poifs/property/PropertyTable.java b/src/java/org/apache/poi/poifs/property/PropertyTable.java new file mode 100644 index 000000000..d744e9bb3 --- /dev/null +++ b/src/java/org/apache/poi/poifs/property/PropertyTable.java @@ -0,0 +1,281 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.property; + +import java.io.IOException; +import java.io.OutputStream; + +import java.util.*; + +import org.apache.poi.poifs.common.PoiFSConstants; +import org.apache.poi.poifs.filesystem.BATManaged; +import org.apache.poi.poifs.storage.BlockWritable; +import org.apache.poi.poifs.storage.PropertyBlock; +import org.apache.poi.poifs.storage.RawDataBlock; +import org.apache.poi.poifs.storage.RawDataBlockList; + +/** + * This class embodies the Property Table for the filesystem; this is + * basically the dsirectory for all of the documents in the + * filesystem. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class PropertyTable + implements BATManaged, BlockWritable +{ + private int _start_block; + private List _properties; + private BlockWritable[] _blocks; + + /** + * Default constructor + */ + + public PropertyTable() + { + _start_block = PoiFSConstants.END_OF_CHAIN; + _properties = new ArrayList(); + addProperty(new RootProperty()); + _blocks = null; + } + + /** + * reading constructor (used when we've read in a file and we want + * to extract the property table from it). Populates the + * properties thoroughly + * + * @param startBlock the first block of the property table + * @param blockList the list of blocks + * + * @exception IOException if anything goes wrong (which should be + * a result of the input being NFG) + */ + + public PropertyTable(final int startBlock, + final RawDataBlockList blockList) + throws IOException + { + _start_block = PoiFSConstants.END_OF_CHAIN; + _blocks = null; + _properties = + PropertyFactory + .convertToProperties(blockList.fetchBlocks(startBlock)); + populatePropertyTree(( DirectoryProperty ) _properties.get(0)); + } + + /** + * Add a property to the list of properties we manage + * + * @param property the new Property to manage + */ + + public void addProperty(final Property property) + { + _properties.add(property); + } + + /** + * Remove a property from the list of properties we manage + * + * @param property the Property to be removed + */ + + public void removeProperty(final Property property) + { + _properties.remove(property); + } + + /** + * Get the root property + * + * @return the root property + */ + + public RootProperty getRoot() + { + + // it's always the first element in the List + return ( RootProperty ) _properties.get(0); + } + + /** + * Prepare to be written + */ + + public void preWrite() + { + Property[] properties = + ( Property [] ) _properties.toArray(new Property[ 0 ]); + + // give each property its index + for (int k = 0; k < properties.length; k++) + { + properties[ k ].setIndex(k); + } + + // allocate the blocks for the property table + _blocks = PropertyBlock.createPropertyBlockArray(_properties); + + // prepare each property for writing + for (int k = 0; k < properties.length; k++) + { + properties[ k ].preWrite(); + } + } + + /** + * Get the start block for the property table + * + * @return start block index + */ + + public int getStartBlock() + { + return _start_block; + } + + private void populatePropertyTree(DirectoryProperty root) + throws IOException + { + int index = root.getChildIndex(); + + if (!Property.isValidIndex(index)) + { + + // property has no children + return; + } + Stack children = new Stack(); + + children.push(_properties.get(index)); + while (!children.empty()) + { + Property property = ( Property ) children.pop(); + + root.addChild(property); + if (property.isDirectory()) + { + populatePropertyTree(( DirectoryProperty ) property); + } + index = property.getPreviousChildIndex(); + if (Property.isValidIndex(index)) + { + children.push(_properties.get(index)); + } + index = property.getNextChildIndex(); + if (Property.isValidIndex(index)) + { + children.push(_properties.get(index)); + } + } + } + + /* ********** START implementation of BATManaged ********** */ + + /** + * Return the number of BigBlock's this instance uses + * + * @return count of BigBlock instances + */ + + public int countBlocks() + { + return (_blocks == null) ? 0 + : _blocks.length; + } + + /** + * Set the start block for this instance + * + * @param index index into the array of BigBlock instances making + * up the the filesystem + */ + + public void setStartBlock(final int index) + { + _start_block = index; + } + + /* ********** END implementation of BATManaged ********** */ + /* ********** START implementation of BlockWritable ********** */ + + /** + * Write the storage to an OutputStream + * + * @param stream the OutputStream to which the stored data should + * be written + * + * @exception IOException on problems writing to the specified + * stream + */ + + public void writeBlocks(final OutputStream stream) + throws IOException + { + if (_blocks != null) + { + for (int j = 0; j < _blocks.length; j++) + { + _blocks[ j ].writeBlocks(stream); + } + } + } + + /* ********** END implementation of BlockWritable ********** */ +} // end public class PropertyTable + diff --git a/src/java/org/apache/poi/poifs/property/RootProperty.java b/src/java/org/apache/poi/poifs/property/RootProperty.java new file mode 100644 index 000000000..7a275eb0a --- /dev/null +++ b/src/java/org/apache/poi/poifs/property/RootProperty.java @@ -0,0 +1,114 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.property; + +import java.util.*; + +import java.io.IOException; + +import org.apache.poi.poifs.common.PoiFSConstants; +import org.apache.poi.poifs.storage.SmallDocumentBlock; + +/** + * Root property + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class RootProperty + extends DirectoryProperty +{ + + /** + * Default constructor + */ + + RootProperty() + { + super("Root Entry"); + + // overrides + setNodeColor(_NODE_BLACK); + setPropertyType(PropertyConstants.ROOT_TYPE); + setStartBlock(PoiFSConstants.END_OF_CHAIN); + } + + /** + * reader constructor + * + * @param index index number + * @param array byte data + * @param offset offset into byte data + */ + + protected RootProperty(final int index, final byte [] array, + final int offset) + { + super(index, array, offset); + } + + /** + * set size + * + * @param size size in terms of small blocks + */ + + public void setSize(int size) + { + super.setSize(SmallDocumentBlock.calcSize(size)); + } +} // end public class RootProperty + diff --git a/src/java/org/apache/poi/poifs/storage/BATBlock.java b/src/java/org/apache/poi/poifs/storage/BATBlock.java new file mode 100644 index 000000000..0b54bb6d6 --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/BATBlock.java @@ -0,0 +1,274 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import java.io.IOException; +import java.io.OutputStream; + +import java.util.Arrays; + +import org.apache.poi.poifs.common.PoiFSConstants; +import org.apache.poi.util.IntegerField; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; + +/** + * A block of block allocation table entries. BATBlocks are created + * only through a static factory method: createBATBlocks. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class BATBlock + extends BigBlock +{ + private static final int _entries_per_block = + PoiFSConstants.BIG_BLOCK_SIZE / LittleEndianConsts.INT_SIZE; + private static final int _entries_per_xbat_block = _entries_per_block + - 1; + private static final int _xbat_chain_offset = + _entries_per_xbat_block * LittleEndianConsts.INT_SIZE; + private static final byte _default_value = ( byte ) 0xFF; + private IntegerField[] _fields; + private byte[] _data; + + /** + * Create a single instance initialized with default values + */ + + private BATBlock() + { + _data = new byte[ PoiFSConstants.BIG_BLOCK_SIZE ]; + Arrays.fill(_data, _default_value); + _fields = new IntegerField[ _entries_per_block ]; + int offset = 0; + + for (int j = 0; j < _entries_per_block; j++) + { + _fields[ j ] = new IntegerField(offset); + offset += LittleEndianConsts.INT_SIZE; + } + } + + /** + * Create an array of BATBlocks from an array of int block + * allocation table entries + * + * @param entries the array of int entries + * + * @return the newly created array of BATBlocks + */ + + public static BATBlock [] createBATBlocks(final int [] entries) + { + int block_count = calculateStorageRequirements(entries.length); + BATBlock[] blocks = new BATBlock[ block_count ]; + int index = 0; + int remaining = entries.length; + + for (int j = 0; j < entries.length; j += _entries_per_block) + { + blocks[ index++ ] = new BATBlock(entries, j, + (remaining > _entries_per_block) + ? j + _entries_per_block + : entries.length); + remaining -= _entries_per_block; + } + return blocks; + } + + /** + * Create an array of XBATBlocks from an array of int block + * allocation table entries + * + * @param entries the array of int entries + * @param startBlock the start block of the array of XBAT blocks + * + * @return the newly created array of BATBlocks + */ + + public static BATBlock [] createXBATBlocks(final int [] entries, + final int startBlock) + { + int block_count = + calculateXBATStorageRequirements(entries.length); + BATBlock[] blocks = new BATBlock[ block_count ]; + int index = 0; + int remaining = entries.length; + + if (block_count != 0) + { + for (int j = 0; j < entries.length; j += _entries_per_xbat_block) + { + blocks[ index++ ] = + new BATBlock(entries, j, + (remaining > _entries_per_xbat_block) + ? j + _entries_per_xbat_block + : entries.length); + remaining -= _entries_per_xbat_block; + } + for (index = 0; index < blocks.length - 1; index++) + { + blocks[ index ].setXBATChain(startBlock + index + 1); + } + blocks[ index ].setXBATChain(PoiFSConstants.END_OF_CHAIN); + } + return blocks; + } + + /** + * Calculate how many BATBlocks are needed to hold a specified + * number of BAT entries. + * + * @param entryCount the number of entries + * + * @return the number of BATBlocks needed + */ + + public static int calculateStorageRequirements(final int entryCount) + { + return (entryCount + _entries_per_block - 1) / _entries_per_block; + } + + /** + * Calculate how many XBATBlocks are needed to hold a specified + * number of BAT entries. + * + * @param entryCount the number of entries + * + * @return the number of XBATBlocks needed + */ + + public static int calculateXBATStorageRequirements(final int entryCount) + { + return (entryCount + _entries_per_xbat_block - 1) + / _entries_per_xbat_block; + } + + /** + * @return number of entries per block + */ + + public static final int entriesPerBlock() + { + return _entries_per_block; + } + + /** + * @return number of entries per XBAT block + */ + + public static final int entriesPerXBATBlock() + { + return _entries_per_xbat_block; + } + + /** + * @return offset of chain index of XBAT block + */ + + public static final int getXBATChainOffset() + { + return _xbat_chain_offset; + } + + private void setXBATChain(int chainIndex) + { + _fields[ _entries_per_xbat_block ].set(chainIndex, _data); + } + + /** + * Create a single instance initialized (perhaps partially) with entries + * + * @param entries the array of block allocation table entries + * @param start_index the index of the first entry to be written + * to the block + * @param end_index the index, plus one, of the last entry to be + * written to the block (writing is for all index + * k, start_index <= k < end_index) + */ + + private BATBlock(final int [] entries, final int start_index, + final int end_index) + { + this(); + for (int k = start_index; k < end_index; k++) + { + _fields[ k - start_index ].set(entries[ k ], _data); + } + } + + /* ********** START extension of BigBlock ********** */ + + /** + * Write the block's data to an OutputStream + * + * @param stream the OutputStream to which the stored data should + * be written + * + * @exception IOException on problems writing to the specified + * stream + */ + + void writeData(final OutputStream stream) + throws IOException + { + doWriteData(stream, _data); + } + + /* ********** END extension of BigBlock ********** */ +} // end public class BATBlock + diff --git a/src/java/org/apache/poi/poifs/storage/BigBlock.java b/src/java/org/apache/poi/poifs/storage/BigBlock.java new file mode 100644 index 000000000..148cc0c38 --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/BigBlock.java @@ -0,0 +1,127 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +/** + * Abstract base class of all POIFS block storage classes. All + * extensions of BigBlock should write 512 bytes of data when + * requested to write their data. + * + * This class has package scope, as there is no reason at this time to + * make the class public. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +import java.io.IOException; +import java.io.OutputStream; + +abstract class BigBlock + implements BlockWritable +{ + + /** + * Default implementation of write for extending classes that + * contain their data in a simple array of bytes. + * + * @param stream the OutputStream to which the data should be + * written. + * @param data the byte array of to be written. + * + * @exception IOException on problems writing to the specified + * stream. + */ + + protected void doWriteData(final OutputStream stream, final byte [] data) + throws IOException + { + stream.write(data); + } + + /** + * Write the block's data to an OutputStream + * + * @param stream the OutputStream to which the stored data should + * be written + * + * @exception IOException on problems writing to the specified + * stream + */ + + abstract void writeData(final OutputStream stream) + throws IOException; + + /* ********** START implementation of BlockWritable ********** */ + + /** + * Write the storage to an OutputStream + * + * @param stream the OutputStream to which the stored data should + * be written + * + * @exception IOException on problems writing to the specified + * stream + */ + + public void writeBlocks(final OutputStream stream) + throws IOException + { + writeData(stream); + } + + /* ********** END implementation of BlockWritable ********** */ +} // end abstract class BigBlock + diff --git a/src/java/org/apache/poi/poifs/storage/BlockAllocationTableReader.java b/src/java/org/apache/poi/poifs/storage/BlockAllocationTableReader.java new file mode 100644 index 000000000..357be636a --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/BlockAllocationTableReader.java @@ -0,0 +1,322 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import java.io.IOException; +import java.io.OutputStream; + +import java.util.*; + +import org.apache.poi.poifs.common.PoiFSConstants; +import org.apache.poi.util.IntList; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; + +/** + * This class manages and creates the Block Allocation Table, which is + * basically a set of linked lists of block indices. + *

+ * Each block of the filesystem has an index. The first block, the + * header, is skipped; the first block after the header is index 0, + * the next is index 1, and so on. + *

+ * A block's index is also its index into the Block Allocation + * Table. The entry that it finds in the Block Allocation Table is the + * index of the next block in the linked list of blocks making up a + * file, or it is set to -2: end of list. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class BlockAllocationTableReader +{ + private IntList _entries; + + /** + * create a BlockAllocationTableReader for an existing filesystem. Side + * effect: when this method finishes, the BAT blocks will have + * been removed from the raw block list, and any blocks labeled as + * 'unused' in the block allocation table will also have been + * removed from the raw block list. + * + * @param block_count the number of BAT blocks making up the block + * allocation table + * @param block_array the array of BAT block indices from the + * filesystem's header + * @param xbat_count the number of XBAT blocks + * @param xbat_index the index of the first XBAT block + * @param raw_block_list the list of RawDataBlocks + * + * @exception IOException if, in trying to create the table, we + * encounter logic errors + */ + + public BlockAllocationTableReader(final int block_count, + final int [] block_array, + final int xbat_count, + final int xbat_index, + final BlockList raw_block_list) + throws IOException + { + this(); + if (block_count <= 0) + { + throw new IOException( + "Illegal block count; minimum count is 1, got " + block_count + + " instead"); + } + + // acquire raw data blocks containing the BAT block data + RawDataBlock blocks[] = new RawDataBlock[ block_count ]; + int limit = Math.min(block_count, block_array.length); + int block_index; + + for (block_index = 0; block_index < limit; block_index++) + { + blocks[ block_index ] = + ( RawDataBlock ) raw_block_list + .remove(block_array[ block_index ]); + } + if (block_index < block_count) + { + + // must have extended blocks + if (xbat_index < 0) + { + throw new IOException( + "BAT count exceeds limit, yet XBAT index indicates no valid entries"); + } + int chain_index = xbat_index; + int max_entries_per_block = BATBlock.entriesPerXBATBlock(); + int chain_index_offset = BATBlock.getXBATChainOffset(); + + for (int j = 0; j < xbat_count; j++) + { + limit = Math.min(block_count - block_index, + max_entries_per_block); + byte[] data = raw_block_list.remove(chain_index).getData(); + int offset = 0; + + for (int k = 0; k < limit; k++) + { + blocks[ block_index++ ] = + ( RawDataBlock ) raw_block_list + .remove(LittleEndian.getInt(data, offset)); + offset += LittleEndianConsts.INT_SIZE; + } + chain_index = LittleEndian.getInt(data, chain_index_offset); + if (chain_index == PoiFSConstants.END_OF_CHAIN) + { + break; + } + } + } + if (block_index != block_count) + { + throw new IOException("Could not find all blocks"); + } + + // now that we have all of the raw data blocks, go through and + // create the indices + setEntries(blocks, raw_block_list); + } + + /** + * create a BlockAllocationTableReader from an array of raw data blocks + * + * @param blocks the raw data + * @param raw_block_list the list holding the managed blocks + * + * @exception IOException + */ + + BlockAllocationTableReader(final ListManagedBlock [] blocks, + final BlockList raw_block_list) + throws IOException + { + this(); + setEntries(blocks, raw_block_list); + } + + /** + * Constructor BlockAllocationTableReader + * + * + */ + + BlockAllocationTableReader() + { + _entries = new IntList(); + } + + /** + * walk the entries from a specified point and return the + * associated blocks. The associated blocks are removed from the + * block list + * + * @param startBlock the first block in the chain + * @param blockList the raw data block list + * + * @return array of ListManagedBlocks, in their correct order + * + * @exception IOException if there is a problem acquiring the blocks + */ + + ListManagedBlock [] fetchBlocks(final int startBlock, + final BlockList blockList) + throws IOException + { + List blocks = new ArrayList(); + int currentBlock = startBlock; + + while (currentBlock != PoiFSConstants.END_OF_CHAIN) + { + blocks.add(blockList.remove(currentBlock)); + currentBlock = _entries.get(currentBlock); + } + return ( ListManagedBlock [] ) blocks + .toArray(new ListManagedBlock[ 0 ]); + } + + // methods for debugging reader + + /** + * determine whether the block specified by index is used or not + * + * @param index index of block in question + * + * @return true if the specific block is used, else false + */ + + boolean isUsed(final int index) + { + boolean rval = false; + + try + { + rval = _entries.get(index) != -1; + } + catch (IndexOutOfBoundsException ignored) + { + } + return rval; + } + + /** + * return the next block index + * + * @param index of the current block + * + * @return index of the next block (may be + * PoiFSConstants.END_OF_CHAIN, indicating end of chain + * (duh)) + * + * @exception IOException if the current block is unused + */ + + int getNextBlockIndex(final int index) + throws IOException + { + if (isUsed(index)) + { + return _entries.get(index); + } + else + { + throw new IOException("index " + index + " is unused"); + } + } + + /** + * Convert an array of blocks into a set of integer indices + * + * @param blocks the array of blocks containing the indices + * @param raw_blocks the list of blocks being managed. Unused + * blocks will be eliminated from the list + * + * @exception IOException + */ + + private void setEntries(final ListManagedBlock [] blocks, + final BlockList raw_blocks) + throws IOException + { + int limit = BATBlock.entriesPerBlock(); + + for (int block_index = 0; block_index < blocks.length; block_index++) + { + byte[] data = blocks[ block_index ].getData(); + int offset = 0; + + for (int k = 0; k < limit; k++) + { + int entry = LittleEndian.getInt(data, offset); + + if (entry == PoiFSConstants.UNUSED_BLOCK) + { + raw_blocks.zap(_entries.size()); + } + _entries.add(entry); + offset += LittleEndianConsts.INT_SIZE; + } + + // discard block + blocks[ block_index ] = null; + } + raw_blocks.setBAT(this); + } +} // end class BlockAllocationTableReader + diff --git a/src/java/org/apache/poi/poifs/storage/BlockAllocationTableWriter.java b/src/java/org/apache/poi/poifs/storage/BlockAllocationTableWriter.java new file mode 100644 index 000000000..4fa181955 --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/BlockAllocationTableWriter.java @@ -0,0 +1,241 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import java.io.IOException; +import java.io.OutputStream; + +import java.util.*; + +import org.apache.poi.poifs.common.PoiFSConstants; +import org.apache.poi.poifs.filesystem.BATManaged; +import org.apache.poi.util.IntList; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; + +/** + * This class manages and creates the Block Allocation Table, which is + * basically a set of linked lists of block indices. + *

+ * Each block of the filesystem has an index. The first block, the + * header, is skipped; the first block after the header is index 0, + * the next is index 1, and so on. + *

+ * A block's index is also its index into the Block Allocation + * Table. The entry that it finds in the Block Allocation Table is the + * index of the next block in the linked list of blocks making up a + * file, or it is set to -2: end of list. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class BlockAllocationTableWriter + implements BlockWritable, BATManaged +{ + private IntList _entries; + private BATBlock[] _blocks; + private int _start_block; + + /** + * create a BlockAllocationTableWriter + */ + + public BlockAllocationTableWriter() + { + _start_block = PoiFSConstants.END_OF_CHAIN; + _entries = new IntList(); + _blocks = new BATBlock[ 0 ]; + } + + /** + * Create the BATBlocks we need + * + * @return start block index of BAT blocks + */ + + public int createBlocks() + { + int xbat_blocks = 0; + int bat_blocks = 0; + + while (true) + { + int calculated_bat_blocks = + BATBlock.calculateStorageRequirements(bat_blocks + + xbat_blocks + + _entries.size()); + int calculated_xbat_blocks = + HeaderBlockWriter + .calculateXBATStorageRequirements(calculated_bat_blocks); + + if ((bat_blocks == calculated_bat_blocks) + && (xbat_blocks == calculated_xbat_blocks)) + { + + // stable ... we're OK + break; + } + else + { + bat_blocks = calculated_bat_blocks; + xbat_blocks = calculated_xbat_blocks; + } + } + int startBlock = allocateSpace(bat_blocks); + + allocateSpace(xbat_blocks); + simpleCreateBlocks(); + return startBlock; + } + + /** + * Allocate space for a block of indices + * + * @param blockCount the number of blocks to allocate space for + * + * @return the starting index of the blocks + */ + + public int allocateSpace(final int blockCount) + { + int startBlock = _entries.size(); + + if (blockCount > 0) + { + int limit = blockCount - 1; + int index = startBlock + 1; + + for (int k = 0; k < limit; k++) + { + _entries.add(index++); + } + _entries.add(PoiFSConstants.END_OF_CHAIN); + } + return startBlock; + } + + /** + * get the starting block + * + * @return the starting block index + */ + + public int getStartBlock() + { + return _start_block; + } + + /** + * create the BATBlocks + */ + + void simpleCreateBlocks() + { + _blocks = BATBlock.createBATBlocks(_entries.toArray()); + } + + /* ********** START implementation of BlockWritable ********** */ + + /** + * Write the storage to an OutputStream + * + * @param stream the OutputStream to which the stored data should + * be written + * + * @exception IOException on problems writing to the specified + * stream + */ + + public void writeBlocks(final OutputStream stream) + throws IOException + { + for (int j = 0; j < _blocks.length; j++) + { + _blocks[ j ].writeBlocks(stream); + } + } + + /* ********** END implementation of BlockWritable ********** */ + /* ********** START implementation of BATManaged ********** */ + + /** + * Return the number of BigBlock's this instance uses + * + * @return count of BigBlock instances + */ + + public int countBlocks() + { + return _blocks.length; + } + + /** + * Set the start block for this instance + * + * @param index index into the array of BigBlock instances making + * up the the filesystem + * + * @param start_block + */ + + public void setStartBlock(int start_block) + { + _start_block = start_block; + } + + /* ********** END implementation of BATManaged ********** */ +} // end class BlockAllocationTableWriter + diff --git a/src/java/org/apache/poi/poifs/storage/BlockList.java b/src/java/org/apache/poi/poifs/storage/BlockList.java new file mode 100644 index 000000000..db1bad039 --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/BlockList.java @@ -0,0 +1,118 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import java.io.IOException; + +/** + * Interface for lists of blocks that are mapped by block allocation + * tables + * + * @author Marc Johnson (mjohnson at apache dot org + */ + +public interface BlockList +{ + + /** + * remove the specified block from the list + * + * @param index the index of the specified block; if the index is + * out of range, that's ok + */ + + public void zap(final int index); + + /** + * remove and return the specified block from the list + * + * @param index the index of the specified block + * + * @return the specified block + * + * @exception IOException if the index is out of range or has + * already been removed + */ + + public ListManagedBlock remove(final int index) + throws IOException; + + /** + * get the blocks making up a particular stream in the list. The + * blocks are removed from the list. + * + * @param startBlock the index of the first block in the stream + * + * @return the stream as an array of correctly ordered blocks + * + * @exception IOException if blocks are missing + */ + + public ListManagedBlock [] fetchBlocks(final int startBlock) + throws IOException; + + /** + * set the associated BlockAllocationTable + * + * @param bat the associated BlockAllocationTable + * + * @exception IOException + */ + + public void setBAT(final BlockAllocationTableReader bat) + throws IOException; +} // end public interface BlockList + diff --git a/src/java/org/apache/poi/poifs/storage/BlockListImpl.java b/src/java/org/apache/poi/poifs/storage/BlockListImpl.java new file mode 100644 index 000000000..f16bf045f --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/BlockListImpl.java @@ -0,0 +1,189 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import java.io.*; + +import java.util.*; + +/** + * A simple implementation of BlockList + * + * @author Marc Johnson (mjohnson at apache dot org + */ + +class BlockListImpl + implements BlockList +{ + private ListManagedBlock[] _blocks; + private BlockAllocationTableReader _bat; + + /** + * Constructor BlockListImpl + */ + + protected BlockListImpl() + { + _blocks = new ListManagedBlock[ 0 ]; + _bat = null; + } + + /** + * provide blocks to manage + * + * @param blocks blocks to be managed + */ + + protected void setBlocks(final ListManagedBlock [] blocks) + { + _blocks = blocks; + } + + /* ********** START implementation of BlockList ********** */ + + /** + * remove the specified block from the list + * + * @param index the index of the specified block; if the index is + * out of range, that's ok + */ + + public void zap(final int index) + { + if ((index >= 0) && (index < _blocks.length)) + { + _blocks[ index ] = null; + } + } + + /** + * remove and return the specified block from the list + * + * @param index the index of the specified block + * + * @return the specified block + * + * @exception IOException if the index is out of range or has + * already been removed + */ + + public ListManagedBlock remove(final int index) + throws IOException + { + ListManagedBlock result = null; + + try + { + result = _blocks[ index ]; + if (result == null) + { + throw new IOException("block[ " + index + + " ] already removed"); + } + _blocks[ index ] = null; + } + catch (ArrayIndexOutOfBoundsException ignored) + { + throw new IOException("Cannot remove block[ " + index + + " ]; out of range"); + } + return result; + } + + /** + * get the blocks making up a particular stream in the list. The + * blocks are removed from the list. + * + * @param startBlock the index of the first block in the stream + * + * @return the stream as an array of correctly ordered blocks + * + * @exception IOException if blocks are missing + */ + + public ListManagedBlock [] fetchBlocks(final int startBlock) + throws IOException + { + if (_bat == null) + { + throw new IOException( + "Improperly initialized list: no block allocation table provided"); + } + return _bat.fetchBlocks(startBlock, this); + } + + /** + * set the associated BlockAllocationTable + * + * @param bat the associated BlockAllocationTable + * + * @exception IOException + */ + + public void setBAT(final BlockAllocationTableReader bat) + throws IOException + { + if (_bat != null) + { + throw new IOException( + "Attempt to replace existing BlockAllocationTable"); + } + _bat = bat; + } + + /* ********** END implementation of BlockList ********** */ +} // end package-scope class BlockListImpl + diff --git a/src/java/org/apache/poi/poifs/storage/BlockWritable.java b/src/java/org/apache/poi/poifs/storage/BlockWritable.java new file mode 100644 index 000000000..89ab9c6da --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/BlockWritable.java @@ -0,0 +1,83 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * An interface for persisting block storage of POIFS components. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public interface BlockWritable +{ + + /** + * Write the storage to an OutputStream + * + * @param stream the OutputStream to which the stored data should + * be written + * + * @exception IOException on problems writing to the specified + * stream + */ + + public void writeBlocks(final OutputStream stream) + throws IOException; +} // end public interface BlockWritable + diff --git a/src/java/org/apache/poi/poifs/storage/DocumentBlock.java b/src/java/org/apache/poi/poifs/storage/DocumentBlock.java new file mode 100644 index 000000000..9f5207cc6 --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/DocumentBlock.java @@ -0,0 +1,260 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import java.util.Arrays; + +import org.apache.poi.poifs.common.PoiFSConstants; +import org.apache.poi.util.IntegerField; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; + +/** + * A block of document data. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class DocumentBlock + extends BigBlock +{ + private static final byte _default_value = ( byte ) 0xFF; + private byte[] _data; + private int _bytes_read; + + /** + * create a document block from a raw data block + * + * @param block the raw data block + * + * @exception IOException + */ + + public DocumentBlock(final RawDataBlock block) + throws IOException + { + _data = block.getData(); + _bytes_read = _data.length; + } + + /** + * Create a single instance initialized with data. + * + * @param stream the InputStream delivering the data. + * + * @exception IOException + */ + + public DocumentBlock(final InputStream stream) + throws IOException + { + this(); + int count = stream.read(_data); + + _bytes_read = (count == -1) ? 0 + : count; + } + + /** + * Create a single instance initialized with default values + */ + + private DocumentBlock() + { + _data = new byte[ PoiFSConstants.BIG_BLOCK_SIZE ]; + Arrays.fill(_data, _default_value); + } + + /** + * Get the number of bytes read for this block + * + * @return bytes read into the block + */ + + public int size() + { + return _bytes_read; + } + + /** + * Was this a partially read block? + * + * @return true if the block was only partially filled with data + */ + + public boolean partiallyRead() + { + return _bytes_read != PoiFSConstants.BIG_BLOCK_SIZE; + } + + /** + * @return the fill byte used + */ + + public static byte getFillByte() + { + return _default_value; + } + + /** + * convert a single long array into an array of DocumentBlock + * instances + * + * @param array the byte array to be converted + * @param size the intended size of the array (which may be smaller) + * + * @return an array of DocumentBlock instances, filled from the + * input array + */ + + public static DocumentBlock [] convert(final byte [] array, + final int size) + { + DocumentBlock[] rval = + new DocumentBlock[ (size + PoiFSConstants.BIG_BLOCK_SIZE - 1) / PoiFSConstants.BIG_BLOCK_SIZE ]; + int offset = 0; + + for (int k = 0; k < rval.length; k++) + { + rval[ k ] = new DocumentBlock(); + if (offset < array.length) + { + int length = Math.min(PoiFSConstants.BIG_BLOCK_SIZE, + array.length - offset); + + System.arraycopy(array, offset, rval[ k ]._data, 0, length); + if (length != PoiFSConstants.BIG_BLOCK_SIZE) + { + Arrays.fill(rval[ k ]._data, length, + PoiFSConstants.BIG_BLOCK_SIZE, + _default_value); + } + } + else + { + Arrays.fill(rval[ k ]._data, _default_value); + } + offset += PoiFSConstants.BIG_BLOCK_SIZE; + } + return rval; + } + + /** + * read data from an array of DocumentBlocks + * + * @param blocks the blocks to read from + * @param buffer the buffer to write the data into + * @param offset the offset into the array of blocks to read from + */ + + public static void read(final DocumentBlock [] blocks, + final byte [] buffer, final int offset) + { + int firstBlockIndex = offset / PoiFSConstants.BIG_BLOCK_SIZE; + int firstBlockOffset = offset % PoiFSConstants.BIG_BLOCK_SIZE; + int lastBlockIndex = (offset + buffer.length - 1) + / PoiFSConstants.BIG_BLOCK_SIZE; + + if (firstBlockIndex == lastBlockIndex) + { + System.arraycopy(blocks[ firstBlockIndex ]._data, + firstBlockOffset, buffer, 0, buffer.length); + } + else + { + int buffer_offset = 0; + + System.arraycopy(blocks[ firstBlockIndex ]._data, + firstBlockOffset, buffer, buffer_offset, + PoiFSConstants.BIG_BLOCK_SIZE + - firstBlockOffset); + buffer_offset += PoiFSConstants.BIG_BLOCK_SIZE - firstBlockOffset; + for (int j = firstBlockIndex + 1; j < lastBlockIndex; j++) + { + System.arraycopy(blocks[ j ]._data, 0, buffer, buffer_offset, + PoiFSConstants.BIG_BLOCK_SIZE); + buffer_offset += PoiFSConstants.BIG_BLOCK_SIZE; + } + System.arraycopy(blocks[ lastBlockIndex ]._data, 0, buffer, + buffer_offset, buffer.length - buffer_offset); + } + } + + /* ********** START extension of BigBlock ********** */ + + /** + * Write the block's data to an OutputStream + * + * @param stream the OutputStream to which the stored data should + * be written + * + * @exception IOException on problems writing to the specified + * stream + */ + + void writeData(final OutputStream stream) + throws IOException + { + doWriteData(stream, _data); + } + + /* ********** END extension of BigBlock ********** */ +} // end public class DocumentBlock + diff --git a/src/java/org/apache/poi/poifs/storage/HeaderBlockConstants.java b/src/java/org/apache/poi/poifs/storage/HeaderBlockConstants.java new file mode 100644 index 000000000..0bb5b124b --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/HeaderBlockConstants.java @@ -0,0 +1,87 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import org.apache.poi.poifs.common.PoiFSConstants; +import org.apache.poi.util.IntegerField; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LongField; +import org.apache.poi.util.ShortField; + +/** + * Constants used in reading/writing the Header block + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public interface HeaderBlockConstants +{ + public static final long _signature = 0xE11AB1A1E011CFD0L; + public static final int _bat_array_offset = 0x4c; + public static final int _max_bats_in_header = + (PoiFSConstants.BIG_BLOCK_SIZE - _bat_array_offset) + / LittleEndianConsts.INT_SIZE; + + // useful offsets + public static final int _signature_offset = 0; + public static final int _bat_count_offset = 0x2C; + public static final int _property_start_offset = 0x30; + public static final int _sbat_start_offset = 0x3C; + public static final int _xbat_start_offset = 0x44; + public static final int _xbat_count_offset = 0x48; +} // end public interface HeaderBlockConstants + diff --git a/src/java/org/apache/poi/poifs/storage/HeaderBlockReader.java b/src/java/org/apache/poi/poifs/storage/HeaderBlockReader.java new file mode 100644 index 000000000..c33d86468 --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/HeaderBlockReader.java @@ -0,0 +1,199 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import java.io.*; + +import java.util.*; + +import org.apache.poi.poifs.common.PoiFSConstants; +import org.apache.poi.util.IntegerField; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LongField; +import org.apache.poi.util.ShortField; + +/** + * The block containing the archive header + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class HeaderBlockReader + implements HeaderBlockConstants +{ + + // number of big block allocation table blocks (int) + private IntegerField _bat_count; + + // start of the property set block (int index of the property set + // chain's first big block) + private IntegerField _property_start; + + // start of the small block allocation table (int index of small + // block allocation table's first big block) + private IntegerField _sbat_start; + + // big block index for extension to the big block allocation table + private IntegerField _xbat_start; + private IntegerField _xbat_count; + private byte[] _data; + + /** + * create a new HeaderBlockReader from an InputStream + * + * @param stream the source InputStream + * + * @exception IOException on errors or bad data + */ + + public HeaderBlockReader(final InputStream stream) + throws IOException + { + _data = new byte[ PoiFSConstants.BIG_BLOCK_SIZE ]; + int byte_count = stream.read(_data); + + if (byte_count != PoiFSConstants.BIG_BLOCK_SIZE) + { + String type = " byte" + ((byte_count == 1) ? ("") + : ("s")); + + throw new IOException("Unable to read entire header; " + + byte_count + type + " read; expected " + + PoiFSConstants.BIG_BLOCK_SIZE + " bytes"); + } + + // verify signature + LongField signature = new LongField(_signature_offset, _data); + + if (signature.get() != _signature) + { + throw new IOException("Invalid header signature; read " + + signature.get() + ", expected " + + _signature); + } + _bat_count = new IntegerField(_bat_count_offset, _data); + _property_start = new IntegerField(_property_start_offset, _data); + _sbat_start = new IntegerField(_sbat_start_offset, _data); + _xbat_start = new IntegerField(_xbat_start_offset, _data); + _xbat_count = new IntegerField(_xbat_count_offset, _data); + } + + /** + * get start of Property Table + * + * @return the index of the first block of the Property Table + */ + + public int getPropertyStart() + { + return _property_start.get(); + } + + /** + * @return start of small block allocation table + */ + + public int getSBATStart() + { + return _sbat_start.get(); + } + + /** + * @return number of BAT blocks + */ + + public int getBATCount() + { + return _bat_count.get(); + } + + /** + * @return BAT array + */ + + public int [] getBATArray() + { + int[] result = new int[ _max_bats_in_header ]; + int offset = _bat_array_offset; + + for (int j = 0; j < _max_bats_in_header; j++) + { + result[ j ] = LittleEndian.getInt(_data, offset); + offset += LittleEndianConsts.INT_SIZE; + } + return result; + } + + /** + * @return XBAT count + */ + + public int getXBATCount() + { + return _xbat_count.get(); + } + + /** + * @return XBAT index + */ + + public int getXBATIndex() + { + return _xbat_start.get(); + } +} // end public class HeaderBlockReader + diff --git a/src/java/org/apache/poi/poifs/storage/HeaderBlockWriter.java b/src/java/org/apache/poi/poifs/storage/HeaderBlockWriter.java new file mode 100644 index 000000000..1d4bed50a --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/HeaderBlockWriter.java @@ -0,0 +1,240 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import java.io.*; + +import java.util.*; + +import org.apache.poi.poifs.common.PoiFSConstants; +import org.apache.poi.util.IntegerField; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LongField; +import org.apache.poi.util.ShortField; + +/** + * The block containing the archive header + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class HeaderBlockWriter + extends BigBlock + implements HeaderBlockConstants +{ + private static final byte _default_value = ( byte ) 0xFF; + + // number of big block allocation table blocks (int) + private IntegerField _bat_count; + + // start of the property set block (int index of the property set + // chain's first big block) + private IntegerField _property_start; + + // start of the small block allocation table (int index of small + // block allocation table's first big block) + private IntegerField _sbat_start; + + // big block index for extension to the big block allocation table + private IntegerField _xbat_start; + private IntegerField _xbat_count; + private byte[] _data; + + /** + * Create a single instance initialized with default values + */ + + public HeaderBlockWriter() + { + _data = new byte[ PoiFSConstants.BIG_BLOCK_SIZE ]; + Arrays.fill(_data, _default_value); + new LongField(_signature_offset, _signature, _data); + new IntegerField(0x08, 0, _data); + new IntegerField(0x0c, 0, _data); + new IntegerField(0x10, 0, _data); + new IntegerField(0x14, 0, _data); + new ShortField(0x18, ( short ) 0x3b, _data); + new ShortField(0x1a, ( short ) 0x3, _data); + new ShortField(0x1c, ( short ) -2, _data); + new ShortField(0x1e, ( short ) 0x9, _data); + new IntegerField(0x20, 0x6, _data); + new IntegerField(0x24, 0, _data); + new IntegerField(0x28, 0, _data); + _bat_count = new IntegerField(_bat_count_offset, 0, _data); + _property_start = new IntegerField(_property_start_offset, + PoiFSConstants.END_OF_CHAIN, + _data); + new IntegerField(0x34, 0, _data); + new IntegerField(0x38, 0x1000, _data); + _sbat_start = new IntegerField(_sbat_start_offset, + PoiFSConstants.END_OF_CHAIN, _data); + new IntegerField(0x40, 1, _data); + _xbat_start = new IntegerField(_xbat_start_offset, + PoiFSConstants.END_OF_CHAIN, _data); + _xbat_count = new IntegerField(_xbat_count_offset, 0, _data); + } + + /** + * Set BAT block parameters. Assumes that all BAT blocks are + * contiguous. Will construct XBAT blocks if necessary and return + * the array of newly constructed XBAT blocks. + * + * @param blockCount count of BAT blocks + * @param startBlock index of first BAT block + * + * @return array of XBAT blocks; may be zero length, will not be + * null + */ + + public BATBlock [] setBATBlocks(final int blockCount, + final int startBlock) + { + BATBlock[] rvalue; + + _bat_count.set(blockCount, _data); + int limit = Math.min(blockCount, _max_bats_in_header); + int offset = _bat_array_offset; + + for (int j = 0; j < limit; j++) + { + new IntegerField(offset, startBlock + j, _data); + offset += LittleEndianConsts.INT_SIZE; + } + if (blockCount > _max_bats_in_header) + { + int excess_blocks = blockCount - _max_bats_in_header; + int[] excess_block_array = new int[ excess_blocks ]; + + for (int j = 0; j < excess_blocks; j++) + { + excess_block_array[ j ] = startBlock + j + + _max_bats_in_header; + } + rvalue = BATBlock.createXBATBlocks(excess_block_array, + startBlock + blockCount); + _xbat_start.set(startBlock + blockCount, _data); + } + else + { + rvalue = BATBlock.createXBATBlocks(new int[ 0 ], 0); + _xbat_start.set(PoiFSConstants.END_OF_CHAIN, _data); + } + _xbat_count.set(rvalue.length, _data); + return rvalue; + } + + /** + * Set start of Property Table + * + * @param startBlock the index of the first block of the Property + * Table + */ + + public void setPropertyStart(final int startBlock) + { + _property_start.set(startBlock, _data); + } + + /** + * Set start of small block allocation table + * + * @param startBlock the index of the first big block of the small + * block allocation table + */ + + public void setSBATStart(final int startBlock) + { + _sbat_start.set(startBlock, _data); + } + + /** + * For a given number of BAT blocks, calculate how many XBAT + * blocks will be needed + * + * @param blockCount number of BAT blocks + * + * @return number of XBAT blocks needed + */ + + static int calculateXBATStorageRequirements(final int blockCount) + { + return (blockCount > _max_bats_in_header) + ? BATBlock.calculateXBATStorageRequirements(blockCount + - _max_bats_in_header) + : 0; + } + + /* ********** START extension of BigBlock ********** */ + + /** + * Write the block's data to an OutputStream + * + * @param stream the OutputStream to which the stored data should + * be written + * + * @exception IOException on problems writing to the specified + * stream + */ + + void writeData(final OutputStream stream) + throws IOException + { + doWriteData(stream, _data); + } + + /* ********** END extension of BigBlock ********** */ +} // end public class HeaderBlockWriter + diff --git a/src/java/org/apache/poi/poifs/storage/ListManagedBlock.java b/src/java/org/apache/poi/poifs/storage/ListManagedBlock.java new file mode 100644 index 000000000..33bc7dfcd --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/ListManagedBlock.java @@ -0,0 +1,81 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import java.io.IOException; + +/** + * An interface for blocks managed by a list that works with a + * BlockAllocationTable to keep block sequences straight + * + * @author Marc Johnson (mjohnson at apache dot org + */ + +public interface ListManagedBlock +{ + + /** + * Get the data from the block + * + * @return the block's data as a byte array + * + * @exception IOException if there is no data + */ + + public byte [] getData() + throws IOException; +} // end public interface ListManagedBlock + diff --git a/src/java/org/apache/poi/poifs/storage/PropertyBlock.java b/src/java/org/apache/poi/poifs/storage/PropertyBlock.java new file mode 100644 index 000000000..36f15d91e --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/PropertyBlock.java @@ -0,0 +1,169 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import java.io.*; + +import java.util.*; + +import org.apache.poi.poifs.common.PoiFSConstants; +import org.apache.poi.poifs.property.Property; +import org.apache.poi.util.IntegerField; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; + +/** + * A block of Property instances + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class PropertyBlock + extends BigBlock +{ + private static final int _properties_per_block = + PoiFSConstants.BIG_BLOCK_SIZE / PoiFSConstants.PROPERTY_SIZE; + private Property[] _properties; + + /** + * Create a single instance initialized with default values + * + * @param properties the properties to be inserted + * @param offset the offset into the properties array + */ + + private PropertyBlock(final Property [] properties, final int offset) + { + _properties = new Property[ _properties_per_block ]; + for (int j = 0; j < _properties_per_block; j++) + { + _properties[ j ] = properties[ j + offset ]; + } + } + + /** + * Create an array of PropertyBlocks from an array of Property + * instances, creating empty Property instances to make up any + * shortfall + * + * @param properties the Property instances to be converted into + * PropertyBlocks, in a java List + * + * @return the array of newly created PropertyBlock instances + */ + + public static BlockWritable [] createPropertyBlockArray( + final List properties) + { + int block_count = + (properties.size() + _properties_per_block - 1) + / _properties_per_block; + Property[] to_be_written = + new Property[ block_count * _properties_per_block ]; + + System.arraycopy(properties.toArray(new Property[ 0 ]), 0, + to_be_written, 0, properties.size()); + for (int j = properties.size(); j < to_be_written.length; j++) + { + + // create an instance of an anonymous inner class that + // extends Property + to_be_written[ j ] = new Property() + { + protected void preWrite() + { + } + + public boolean isDirectory() + { + return false; + } + }; + } + BlockWritable[] rvalue = new BlockWritable[ block_count ]; + + for (int j = 0; j < block_count; j++) + { + rvalue[ j ] = new PropertyBlock(to_be_written, + j * _properties_per_block); + } + return rvalue; + } + + /* ********** START extension of BigBlock ********** */ + + /** + * Write the block's data to an OutputStream + * + * @param stream the OutputStream to which the stored data should + * be written + * + * @exception IOException on problems writing to the specified + * stream + */ + + void writeData(final OutputStream stream) + throws IOException + { + for (int j = 0; j < _properties_per_block; j++) + { + _properties[ j ].writeData(stream); + } + } + + /* ********** END extension of BigBlock ********** */ +} // end public class PropertyBlock + diff --git a/src/java/org/apache/poi/poifs/storage/RawDataBlock.java b/src/java/org/apache/poi/poifs/storage/RawDataBlock.java new file mode 100644 index 000000000..05a53ab7c --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/RawDataBlock.java @@ -0,0 +1,145 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import org.apache.poi.poifs.common.PoiFSConstants; + +import java.io.*; + +/** + * A big block created from an InputStream, holding the raw data + * + * @author Marc Johnson (mjohnson at apache dot org + */ + +public class RawDataBlock + implements ListManagedBlock +{ + private byte[] _data; + private boolean _eof; + + /** + * Constructor RawDataBlock + * + * @param stream the InputStream from which the data will be read + * + * @exception IOException on I/O errors, and if an insufficient + * amount of data is read + */ + + public RawDataBlock(final InputStream stream) + throws IOException + { + _data = new byte[ PoiFSConstants.BIG_BLOCK_SIZE ]; + int count = stream.read(_data); + + if (count == -1) + { + _eof = true; + } + else if (count != PoiFSConstants.BIG_BLOCK_SIZE) + { + String type = " byte" + ((count == 1) ? ("") + : ("s")); + + throw new IOException("Unable to read entire block; " + count + + type + " read; expected " + + PoiFSConstants.BIG_BLOCK_SIZE + " bytes"); + } + else + { + _eof = false; + } + } + + /** + * When we read the data, did we hit end of file? + * + * @return true if no data was read because we were at the end of + * the file, else false + * + * @exception IOException + */ + + public boolean eof() + throws IOException + { + return _eof; + } + + /* ********** START implementation of ListManagedBlock ********** */ + + /** + * Get the data from the block + * + * @return the block's data as a byte array + * + * @exception IOException if there is no data + */ + + public byte [] getData() + throws IOException + { + if (eof()) + { + throw new IOException("Cannot return empty data"); + } + return _data; + } + + /* ********** END implementation of ListManagedBlock ********** */ +} // end public class RawDataBlock + diff --git a/src/java/org/apache/poi/poifs/storage/RawDataBlockList.java b/src/java/org/apache/poi/poifs/storage/RawDataBlockList.java new file mode 100644 index 000000000..5db227099 --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/RawDataBlockList.java @@ -0,0 +1,99 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import java.io.*; + +import java.util.*; + +/** + * A list of RawDataBlocks instances, and methods to manage the list + * + * @author Marc Johnson (mjohnson at apache dot org + */ + +public class RawDataBlockList + extends BlockListImpl +{ + + /** + * Constructor RawDataBlockList + * + * @param stream the InputStream from which the data will be read + * + * @exception IOException on I/O errors, and if an incomplete + * block is read + */ + + public RawDataBlockList(final InputStream stream) + throws IOException + { + List blocks = new ArrayList(); + + while (true) + { + RawDataBlock block = new RawDataBlock(stream); + + if (block.eof()) + { + break; + } + blocks.add(block); + } + setBlocks(( RawDataBlock [] ) blocks.toArray(new RawDataBlock[ 0 ])); + } +} // end public class RawDataBlockList + diff --git a/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java b/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java new file mode 100644 index 000000000..43d6366ec --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java @@ -0,0 +1,101 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import org.apache.poi.poifs.property.RootProperty; + +import java.util.*; + +import java.io.*; + +/** + * This class implements reading the small document block list from an + * existing file + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class SmallBlockTableReader +{ + + /** + * fetch the small document block list from an existing file + * + * @param blockList the raw data from which the small block table + * will be extracted + * @param root the root property (which contains the start block + * and small block table size) + * @param sbatStart the start block of the SBAT + * + * @return the small document block list + * + * @exception IOException + */ + + public static BlockList getSmallDocumentBlocks( + final RawDataBlockList blockList, final RootProperty root, + final int sbatStart) + throws IOException + { + BlockList list = + new SmallDocumentBlockList(SmallDocumentBlock + .extract(blockList.fetchBlocks(root.getStartBlock()))); + + new BlockAllocationTableReader(blockList.fetchBlocks(sbatStart), + list); + return list; + } +} diff --git a/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java b/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java new file mode 100644 index 000000000..76b77b54b --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java @@ -0,0 +1,178 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import org.apache.poi.poifs.filesystem.BATManaged; +import org.apache.poi.poifs.filesystem.POIFSDocument; +import org.apache.poi.poifs.property.RootProperty; + +import java.util.*; + +import java.io.*; + +/** + * This class implements storage for writing the small blocks used by + * small documents. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class SmallBlockTableWriter + implements BlockWritable, BATManaged +{ + private BlockAllocationTableWriter _sbat; + private List _small_blocks; + private int _big_block_count; + private RootProperty _root; + + /** + * Creates new SmallBlockTable + * + * @param documents a List of POIFSDocument instances + * @param root the Filesystem's root property + */ + + public SmallBlockTableWriter(final List documents, + final RootProperty root) + { + _sbat = new BlockAllocationTableWriter(); + _small_blocks = new ArrayList(); + _root = root; + Iterator iter = documents.iterator(); + + while (iter.hasNext()) + { + POIFSDocument doc = ( POIFSDocument ) iter.next(); + BlockWritable[] blocks = doc.getSmallBlocks(); + + if (blocks.length != 0) + { + doc.setStartBlock(_sbat.allocateSpace(blocks.length)); + for (int j = 0; j < blocks.length; j++) + { + _small_blocks.add(blocks[ j ]); + } + } + } + _sbat.simpleCreateBlocks(); + _root.setSize(_small_blocks.size()); + _big_block_count = SmallDocumentBlock.fill(_small_blocks); + } + + /** + * Get the SBAT + * + * @return the Small Block Allocation Table + */ + + public BlockAllocationTableWriter getSBAT() + { + return _sbat; + } + + /* ********** START implementation of BATManaged ********** */ + + /** + * Return the number of BigBlock's this instance uses + * + * @return count of BigBlock instances + */ + + public int countBlocks() + { + return _big_block_count; + } + + /** + * Set the start block for this instance + * + * @param index index into the array of BigBlock instances making + * up the the filesystem + * + * @param start_block + */ + + public void setStartBlock(int start_block) + { + _root.setStartBlock(start_block); + } + + /* ********** END implementation of BATManaged ********** */ + /* ********** START implementation of BlockWritable ********** */ + + /** + * Write the storage to an OutputStream + * + * @param stream the OutputStream to which the stored data should + * be written + * + * @exception IOException on problems writing to the specified + * stream + */ + + public void writeBlocks(final OutputStream stream) + throws IOException + { + Iterator iter = _small_blocks.iterator(); + + while (iter.hasNext()) + { + (( BlockWritable ) iter.next()).writeBlocks(stream); + } + } + + /* ********** END implementation of BlockWritable ********** */ +} diff --git a/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java b/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java new file mode 100644 index 000000000..b5e27f906 --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java @@ -0,0 +1,322 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import java.io.*; + +import java.util.*; + +import org.apache.poi.poifs.common.PoiFSConstants; + +/** + * Storage for documents that are too small to use regular + * DocumentBlocks for their data + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class SmallDocumentBlock + implements BlockWritable, ListManagedBlock +{ + private byte[] _data; + private static final byte _default_fill = ( byte ) 0xff; + private static final int _block_size = 64; + private static final int _blocks_per_big_block = + PoiFSConstants.BIG_BLOCK_SIZE / _block_size; + + private SmallDocumentBlock(final byte [] data, final int index) + { + this(); + System.arraycopy(data, index * _block_size, _data, 0, _block_size); + } + + private SmallDocumentBlock() + { + _data = new byte[ _block_size ]; + } + + /** + * convert a single long array into an array of SmallDocumentBlock + * instances + * + * @param array the byte array to be converted + * @param size the intended size of the array (which may be smaller) + * + * @return an array of SmallDocumentBlock instances, filled from + * the array + */ + + public static SmallDocumentBlock [] convert(final byte [] array, + final int size) + { + SmallDocumentBlock[] rval = + new SmallDocumentBlock[ (size + _block_size - 1) / _block_size ]; + int offset = 0; + + for (int k = 0; k < rval.length; k++) + { + rval[ k ] = new SmallDocumentBlock(); + if (offset < array.length) + { + int length = Math.min(_block_size, array.length - offset); + + System.arraycopy(array, offset, rval[ k ]._data, 0, length); + if (length != _block_size) + { + Arrays.fill(rval[ k ]._data, length, _block_size, + _default_fill); + } + } + else + { + Arrays.fill(rval[ k ]._data, _default_fill); + } + offset += _block_size; + } + return rval; + } + + /** + * fill out a List of SmallDocumentBlocks so that it fully occupies + * a set of big blocks + * + * @param blocks the List to be filled out + * + * @return number of big blocks the list encompasses + */ + + public static int fill(final List blocks) + { + int count = blocks.size(); + int big_block_count = (count + _blocks_per_big_block - 1) + / _blocks_per_big_block; + int full_count = big_block_count * _blocks_per_big_block; + + for (; count < full_count; count++) + { + blocks.add(makeEmptySmallDocumentBlock()); + } + return big_block_count; + } + + /** + * Factory for creating SmallDocumentBlocks from DocumentBlocks + * + * @param store the original DocumentBlocks + * @param size the total document size + * + * @return an array of new SmallDocumentBlocks instances + * + * @exception IOException on errors reading from the DocumentBlocks + * @exception ArrayIndexOutOfBoundsException if, somehow, the store + * contains less data than size indicates + */ + + public static SmallDocumentBlock [] convert(final BlockWritable [] store, + final int size) + throws IOException, ArrayIndexOutOfBoundsException + { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + + for (int j = 0; j < store.length; j++) + { + store[ j ].writeBlocks(stream); + } + byte[] data = stream.toByteArray(); + SmallDocumentBlock[] rval = + new SmallDocumentBlock[ convertToBlockCount(size) ]; + + for (int index = 0; index < rval.length; index++) + { + rval[ index ] = new SmallDocumentBlock(data, index); + } + return rval; + } + + /** + * create a list of SmallDocumentBlock's from raw data + * + * @param blocks the raw data containing the SmallDocumentBlock + * data + * + * @return a List of SmallDocumentBlock's extracted from the input + * + * @exception IOException + */ + + public static List extract(ListManagedBlock [] blocks) + throws IOException + { + List sdbs = new ArrayList(); + + for (int j = 0; j < blocks.length; j++) + { + byte[] data = blocks[ j ].getData(); + + for (int k = 0; k < _blocks_per_big_block; k++) + { + sdbs.add(new SmallDocumentBlock(data, k)); + } + } + return sdbs; + } + + /** + * read data from an array of SmallDocumentBlocks + * + * @param blocks the blocks to read from + * @param buffer the buffer to write the data into + * @param offset the offset into the array of blocks to read from + */ + + public static void read(final BlockWritable [] blocks, + final byte [] buffer, final int offset) + { + int firstBlockIndex = offset / _block_size; + int firstBlockOffset = offset % _block_size; + int lastBlockIndex = (offset + buffer.length - 1) / _block_size; + + if (firstBlockIndex == lastBlockIndex) + { + System.arraycopy( + (( SmallDocumentBlock ) blocks[ firstBlockIndex ])._data, + firstBlockOffset, buffer, 0, buffer.length); + } + else + { + int buffer_offset = 0; + + System.arraycopy( + (( SmallDocumentBlock ) blocks[ firstBlockIndex ])._data, + firstBlockOffset, buffer, buffer_offset, + _block_size - firstBlockOffset); + buffer_offset += _block_size - firstBlockOffset; + for (int j = firstBlockIndex + 1; j < lastBlockIndex; j++) + { + System.arraycopy((( SmallDocumentBlock ) blocks[ j ])._data, + 0, buffer, buffer_offset, _block_size); + buffer_offset += _block_size; + } + System.arraycopy( + (( SmallDocumentBlock ) blocks[ lastBlockIndex ])._data, 0, + buffer, buffer_offset, buffer.length - buffer_offset); + } + } + + /** + * Calculate the storage size of a set of SmallDocumentBlocks + * + * @param size number of SmallDocumentBlocks + * + * @return total size + */ + + public static int calcSize(int size) + { + return size * _block_size; + } + + private static SmallDocumentBlock makeEmptySmallDocumentBlock() + { + SmallDocumentBlock block = new SmallDocumentBlock(); + + Arrays.fill(block._data, _default_fill); + return block; + } + + private static int convertToBlockCount(final int size) + { + return (size + _block_size - 1) / _block_size; + } + + /* ********** START implementation of BlockWritable ********** */ + + /** + * Write the storage to an OutputStream + * + * @param stream the OutputStream to which the stored data should + * be written + * + * @exception IOException on problems writing to the specified + * stream + */ + + public void writeBlocks(final OutputStream stream) + throws IOException + { + stream.write(_data); + } + + /* ********** END implementation of BlockWritable ********** */ + /* ********** START implementation of ListManagedBlock ********** */ + + /** + * Get the data from the block + * + * @return the block's data as a byte array + * + * @exception IOException if there is no data + */ + + public byte [] getData() + throws IOException + { + return _data; + } + + /* ********** END implementation of ListManagedBlock ********** */ +} // end public class SmallDocumentBlock + diff --git a/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java b/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java new file mode 100644 index 000000000..85e75f585 --- /dev/null +++ b/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java @@ -0,0 +1,82 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.poifs.storage; + +import java.util.*; + +/** + * A list of SmallDocumentBlocks instances, and methods to manage the list + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class SmallDocumentBlockList + extends BlockListImpl +{ + + /** + * Constructor SmallDocumentBlockList + * + * @param blocks a list of SmallDocumentBlock instances + */ + + public SmallDocumentBlockList(final List blocks) + { + setBlocks(( SmallDocumentBlock [] ) blocks + .toArray(new SmallDocumentBlock[ 0 ])); + } +} // end public class SmallDocumentBlockList + diff --git a/src/java/org/apache/poi/util/BinaryTree.java b/src/java/org/apache/poi/util/BinaryTree.java new file mode 100644 index 000000000..3b2356eb5 --- /dev/null +++ b/src/java/org/apache/poi/util/BinaryTree.java @@ -0,0 +1,2231 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +import java.lang.reflect.Array; + +import java.util.*; + +/** + * Red-Black tree-based implementation of Map. This class guarantees + * that the map will be in both ascending key order and ascending + * value order, sorted according to the natural order for the key's + * and value's classes.

+ * + * This Map is intended for applications that need to be able to look + * up a key-value pairing by either key or value, and need to do so + * with equal efficiency.

+ * + * While that goal could be accomplished by taking a pair of TreeMaps + * and redirecting requests to the appropriate TreeMap (e.g., + * containsKey would be directed to the TreeMap that maps values to + * keys, containsValue would be directed to the TreeMap that maps keys + * to values), there are problems with that implementation, + * particularly when trying to keep the two TreeMaps synchronized with + * each other. And if the data contained in the TreeMaps is large, the + * cost of redundant storage becomes significant.

+ * + * This solution keeps the data properly synchronized and minimizes + * the data storage. The red-black algorithm is based on TreeMap's, + * but has been modified to simultaneously map a tree node by key and + * by value. This doubles the cost of put operations (but so does + * using two TreeMaps), and nearly doubles the cost of remove + * operations (there is a savings in that the lookup of the node to be + * removed only has to be performed once). And since only one node + * contains the key and value, storage is significantly less than that + * required by two TreeMaps.

+ * + * There are some limitations placed on data kept in this Map. The + * biggest one is this:

+ * + * When performing a put operation, neither the key nor the value may + * already exist in the Map. In the java.util Map implementations + * (HashMap, TreeMap), you can perform a put with an already mapped + * key, and neither cares about duplicate values at all ... but this + * implementation's put method with throw an IllegalArgumentException + * if either the key or the value is already in the Map.

+ * + * Obviously, that same restriction (and consequence of failing to + * heed that restriction) applies to the putAll method.

+ * + * The Map.Entry instances returned by the appropriate methods will + * not allow setValue() and will throw an + * UnsupportedOperationException on attempts to call that method.

+ * + * New methods are added to take advantage of the fact that values are + * kept sorted independently of their keys:

+ * + * Object getKeyForValue(Object value) is the opposite of get; it + * takes a value and returns its key, if any.

+ * + * Object removeValue(Object value) finds and removes the specified + * value and returns the now un-used key.

+ * + * Set entrySetByValue() returns the Map.Entry's in a Set whose + * iterator will iterate over the Map.Entry's in ascending order by + * their corresponding values.

+ * + * Set keySetByValue() returns the keys in a Set whose iterator will + * iterate over the keys in ascending order by their corresponding + * values.

+ * + * Collection valuesByValue() returns the values in a Collection whose + * iterator will iterate over the values in ascending order.

+ * + * @author Marc Johnson (mjohnson at apache dot org) + */ + +// final for performance +public final class BinaryTree + extends AbstractMap +{ + private Node[] _root = new Node[] + { + null, null + }; + private int _size = 0; + private int _modifications = 0; + private Set[] _key_set = new Set[] + { + null, null + }; + private Set[] _entry_set = new Set[] + { + null, null + }; + private Collection[] _value_collection = new Collection[] + { + null, null + }; + private static final int _KEY = 0; + private static final int _VALUE = 1; + private static final int _INDEX_SUM = _KEY + _VALUE; + private static final int _MINIMUM_INDEX = 0; + private static final int _INDEX_COUNT = 2; + private static final String[] _data_name = new String[] + { + "key", "value" + }; + + /** + * Construct a new BinaryTree + */ + + public BinaryTree() + { + } + + /** + * Constructs a new BinaryTree from an existing Map, with keys and + * values sorted + * + * @param map the map whose mappings are to be placed in this map. + * + * @exception ClassCastException if the keys in the map are not + * Comparable, or are not mutually + * comparable; also if the values in + * the map are not Comparable, or + * are not mutually Comparable + * @exception NullPointerException if any key or value in the map + * is null + * @exception IllegalArgumentException if there are duplicate keys + * or duplicate values in the + * map + */ + + public BinaryTree(final Map map) + throws ClassCastException, NullPointerException, + IllegalArgumentException + { + putAll(map); + } + + /** + * Returns the key to which this map maps the specified value. + * Returns null if the map contains no mapping for this value. + * + * @param value value whose associated key is to be returned. + * + * @return the key to which this map maps the specified value, or + * null if the map contains no mapping for this value. + * + * @exception ClassCastException if the value is of an + * inappropriate type for this map. + * @exception NullPointerException if the value is null + */ + + public Object getKeyForValue(final Object value) + throws ClassCastException, NullPointerException + { + return doGet(( Comparable ) value, _VALUE); + } + + /** + * Removes the mapping for this value from this map if present + * + * @param value value whose mapping is to be removed from the map. + * + * @return previous key associated with specified value, or null + * if there was no mapping for value. + */ + + public Object removeValue(final Object value) + { + return doRemove(( Comparable ) value, _VALUE); + } + + /** + * Returns a set view of the mappings contained in this map. Each + * element in the returned set is a Map.Entry. The set is backed + * by the map, so changes to the map are reflected in the set, and + * vice-versa. If the map is modified while an iteration over the + * set is in progress, the results of the iteration are + * undefined. The set supports element removal, which removes the + * corresponding mapping from the map, via the Iterator.remove, + * Set.remove, removeAll, retainAll and clear operations. It does + * not support the add or addAll operations.

+ * + * The difference between this method and entrySet is that + * entrySet's iterator() method returns an iterator that iterates + * over the mappings in ascending order by key. This method's + * iterator method iterates over the mappings in ascending order + * by value. + * + * @return a set view of the mappings contained in this map. + */ + + public Set entrySetByValue() + { + if (_entry_set[ _VALUE ] == null) + { + _entry_set[ _VALUE ] = new AbstractSet() + { + public Iterator iterator() + { + return new BinaryTreeIterator(_VALUE) + { + protected Object doGetNext() + { + return _last_returned_node; + } + }; + } + + public boolean contains(Object o) + { + if (!(o instanceof Map.Entry)) + { + return false; + } + Map.Entry entry = ( Map.Entry ) o; + Object key = entry.getKey(); + Node node = lookup(( Comparable ) entry.getValue(), + _VALUE); + + return (node != null) && node.getData(_KEY).equals(key); + } + + public boolean remove(Object o) + { + if (!(o instanceof Map.Entry)) + { + return false; + } + Map.Entry entry = ( Map.Entry ) o; + Object key = entry.getKey(); + Node node = lookup(( Comparable ) entry.getValue(), + _VALUE); + + if ((node != null) && node.getData(_KEY).equals(key)) + { + doRedBlackDelete(node); + return true; + } + return false; + } + + public int size() + { + return BinaryTree.this.size(); + } + + public void clear() + { + BinaryTree.this.clear(); + } + }; + } + return _entry_set[ _VALUE ]; + } + + /** + * Returns a set view of the keys contained in this map. The set + * is backed by the map, so changes to the map are reflected in + * the set, and vice-versa. If the map is modified while an + * iteration over the set is in progress, the results of the + * iteration are undefined. The set supports element removal, + * which removes the corresponding mapping from the map, via the + * Iterator.remove, Set.remove, removeAll, retainAll, and clear + * operations. It does not support the add or addAll + * operations.

+ * + * The difference between this method and keySet is that keySet's + * iterator() method returns an iterator that iterates over the + * keys in ascending order by key. This method's iterator method + * iterates over the keys in ascending order by value. + * + * @return a set view of the keys contained in this map. + */ + + public Set keySetByValue() + { + if (_key_set[ _VALUE ] == null) + { + _key_set[ _VALUE ] = new AbstractSet() + { + public Iterator iterator() + { + return new BinaryTreeIterator(_VALUE) + { + protected Object doGetNext() + { + return _last_returned_node.getData(_KEY); + } + }; + } + + public int size() + { + return BinaryTree.this.size(); + } + + public boolean contains(Object o) + { + return containsKey(o); + } + + public boolean remove(Object o) + { + int old_size = _size; + + BinaryTree.this.remove(o); + return _size != old_size; + } + + public void clear() + { + BinaryTree.this.clear(); + } + }; + } + return _key_set[ _VALUE ]; + } + + /** + * Returns a collection view of the values contained in this + * map. The collection is backed by the map, so changes to the map + * are reflected in the collection, and vice-versa. If the map is + * modified while an iteration over the collection is in progress, + * the results of the iteration are undefined. The collection + * supports element removal, which removes the corresponding + * mapping from the map, via the Iterator.remove, + * Collection.remove, removeAll, retainAll and clear operations. + * It does not support the add or addAll operations.

+ * + * The difference between this method and values is that values's + * iterator() method returns an iterator that iterates over the + * values in ascending order by key. This method's iterator method + * iterates over the values in ascending order by key. + * + * @return a collection view of the values contained in this map. + */ + + public Collection valuesByValue() + { + if (_value_collection[ _VALUE ] == null) + { + _value_collection[ _VALUE ] = new AbstractCollection() + { + public Iterator iterator() + { + return new BinaryTreeIterator(_VALUE) + { + protected Object doGetNext() + { + return _last_returned_node.getData(_VALUE); + } + }; + } + + public int size() + { + return BinaryTree.this.size(); + } + + public boolean contains(Object o) + { + return containsValue(o); + } + + public boolean remove(Object o) + { + int old_size = _size; + + removeValue(o); + return _size != old_size; + } + + public boolean removeAll(Collection c) + { + boolean modified = false; + Iterator iter = c.iterator(); + + while (iter.hasNext()) + { + if (removeValue(iter.next()) != null) + { + modified = true; + } + } + return modified; + } + + public void clear() + { + BinaryTree.this.clear(); + } + }; + } + return _value_collection[ _VALUE ]; + } + + /** + * common remove logic (remove by key or remove by value) + * + * @param o the key, or value, that we're looking for + * @param index _KEY or _VALUE + * + * @return the key, if remove by value, or the value, if remove by + * key. null if the specified key or value could not be + * found + */ + + private Object doRemove(final Comparable o, final int index) + { + Node node = lookup(o, index); + Object rval = null; + + if (node != null) + { + rval = node.getData(oppositeIndex(index)); + doRedBlackDelete(node); + } + return rval; + } + + /** + * common get logic, used to get by key or get by value + * + * @param o the key or value that we're looking for + * @param index _KEY or _VALUE + * + * @return the key (if the value was mapped) or the value (if the + * key was mapped); null if we couldn't find the specified + * object + */ + + private Object doGet(final Comparable o, final int index) + { + checkNonNullComparable(o, index); + Node node = lookup(o, index); + + return ((node == null) ? null + : node.getData(oppositeIndex(index))); + } + + /** + * Get the opposite index of the specified index + * + * @param index _KEY or _VALUE + * + * @return _VALUE (if _KEY was specified), else _KEY + */ + + private int oppositeIndex(final int index) + { + + // old trick ... to find the opposite of a value, m or n, + // subtract the value from the sum of the two possible + // values. (m + n) - m = n; (m + n) - n = m + return _INDEX_SUM - index; + } + + /** + * do the actual lookup of a piece of data + * + * @param data the key or value to be looked up + * @param index _KEY or _VALUE + * + * @return the desired Node, or null if there is no mapping of the + * specified data + */ + + private Node lookup(final Comparable data, final int index) + { + Node rval = null; + Node node = _root[ index ]; + + while (node != null) + { + int cmp = compare(data, node.getData(index)); + + if (cmp == 0) + { + rval = node; + break; + } + else + { + node = (cmp < 0) ? node.getLeft(index) + : node.getRight(index); + } + } + return rval; + } + + /** + * Compare two objects + * + * @param o1 the first object + * @param o2 the second object + * + * @return negative value if o1 < o2; 0 if o1 == o2; positive + * value if o1 > o2 + */ + + private static int compare(final Comparable o1, final Comparable o2) + { + return (( Comparable ) o1).compareTo(o2); + } + + /** + * find the least node from a given node. very useful for starting + * a sorting iterator ... + * + * @param node the node from which we will start searching + * @param index _KEY or _VALUE + * + * @return the smallest node, from the specified node, in the + * specified mapping + */ + + private static Node leastNode(final Node node, final int index) + { + Node rval = node; + + if (rval != null) + { + while (rval.getLeft(index) != null) + { + rval = rval.getLeft(index); + } + } + return rval; + } + + /** + * get the next larger node from the specified node + * + * @param node the node to be searched from + * @param index _KEY or _VALUE + * + * @return the specified node + */ + + private Node nextGreater(final Node node, final int index) + { + Node rval = null; + + if (node == null) + { + rval = null; + } + else if (node.getRight(index) != null) + { + + // everything to the node's right is larger. The least of + // the right node's descendents is the next larger node + rval = leastNode(node.getRight(index), index); + } + else + { + + // traverse up our ancestry until we find an ancestor that + // is null or one whose left child is our ancestor. If we + // find a null, then this node IS the largest node in the + // tree, and there is no greater node. Otherwise, we are + // the largest node in the subtree on that ancestor's left + // ... and that ancestor is the next greatest node + Node parent = node.getParent(index); + Node child = node; + + while ((parent != null) && (child == parent.getRight(index))) + { + child = parent; + parent = parent.getParent(index); + } + rval = parent; + } + return rval; + } + + /** + * copy the color from one node to another, dealing with the fact + * that one or both nodes may, in fact, be null + * + * @param from the node whose color we're copying; may be null + * @param to the node whose color we're changing; may be null + * @param index _KEY or _VALUE + */ + + private static void copyColor(final Node from, final Node to, + final int index) + { + if (to != null) + { + if (from == null) + { + + // by default, make it black + to.setBlack(index); + } + else + { + to.copyColor(from, index); + } + } + } + + /** + * is the specified node red? if the node does not exist, no, it's + * black, thank you + * + * @param node the node (may be null) in question + * @param index _KEY or _VALUE + */ + + private static boolean isRed(final Node node, final int index) + { + return ((node == null) ? false + : node.isRed(index)); + } + + /** + * is the specified black red? if the node does not exist, sure, + * it's black, thank you + * + * @param node the node (may be null) in question + * @param index _KEY or _VALUE + */ + + private static boolean isBlack(final Node node, final int index) + { + return ((node == null) ? true + : node.isBlack(index)); + } + + /** + * force a node (if it exists) red + * + * @param node the node (may be null) in question + * @param index _KEY or _VALUE + */ + + private static void makeRed(final Node node, final int index) + { + if (node != null) + { + node.setRed(index); + } + } + + /** + * force a node (if it exists) black + * + * @param node the node (may be null) in question + * @param index _KEY or _VALUE + */ + + private static void makeBlack(final Node node, final int index) + { + if (node != null) + { + node.setBlack(index); + } + } + + /** + * get a node's grandparent. mind you, the node, its parent, or + * its grandparent may not exist. no problem + * + * @param node the node (may be null) in question + * @param index _KEY or _VALUE + */ + + private static Node getGrandParent(final Node node, final int index) + { + return getParent(getParent(node, index), index); + } + + /** + * get a node's parent. mind you, the node, or its parent, may not + * exist. no problem + * + * @param node the node (may be null) in question + * @param index _KEY or _VALUE + */ + + private static Node getParent(final Node node, final int index) + { + return ((node == null) ? null + : node.getParent(index)); + } + + /** + * get a node's right child. mind you, the node may not exist. no + * problem + * + * @param node the node (may be null) in question + * @param index _KEY or _VALUE + */ + + private static Node getRightChild(final Node node, final int index) + { + return (node == null) ? null + : node.getRight(index); + } + + /** + * get a node's left child. mind you, the node may not exist. no + * problem + * + * @param node the node (may be null) in question + * @param index _KEY or _VALUE + */ + + private static Node getLeftChild(final Node node, final int index) + { + return (node == null) ? null + : node.getLeft(index); + } + + /** + * is this node its parent's left child? mind you, the node, or + * its parent, may not exist. no problem. if the node doesn't + * exist ... it's its non-existent parent's left child. If the + * node does exist but has no parent ... no, we're not the + * non-existent parent's left child. Otherwise (both the specified + * node AND its parent exist), check. + * + * @param node the node (may be null) in question + * @param index _KEY or _VALUE + */ + + private static boolean isLeftChild(final Node node, final int index) + { + return (node == null) ? true + : ((node.getParent(index) == null) ? false + : (node + == node.getParent( + index).getLeft( + index))); + } + + /** + * is this node its parent's right child? mind you, the node, or + * its parent, may not exist. no problem. if the node doesn't + * exist ... it's its non-existent parent's right child. If the + * node does exist but has no parent ... no, we're not the + * non-existent parent's right child. Otherwise (both the + * specified node AND its parent exist), check. + * + * @param node the node (may be null) in question + * @param index _KEY or _VALUE + */ + + private static boolean isRightChild(final Node node, final int index) + { + return (node == null) ? true + : ((node.getParent(index) == null) ? false + : (node + == node.getParent( + index).getRight( + index))); + } + + /** + * do a rotate left. standard fare in the world of balanced trees + * + * @param node the node to be rotated + * @param index _KEY or _VALUE + */ + + private void rotateLeft(final Node node, final int index) + { + Node right_child = node.getRight(index); + + node.setRight(right_child.getLeft(index), index); + if (right_child.getLeft(index) != null) + { + right_child.getLeft(index).setParent(node, index); + } + right_child.setParent(node.getParent(index), index); + if (node.getParent(index) == null) + { + + // node was the root ... now its right child is the root + _root[ index ] = right_child; + } + else if (node.getParent(index).getLeft(index) == node) + { + node.getParent(index).setLeft(right_child, index); + } + else + { + node.getParent(index).setRight(right_child, index); + } + right_child.setLeft(node, index); + node.setParent(right_child, index); + } + + /** + * do a rotate right. standard fare in the world of balanced trees + * + * @param node the node to be rotated + * @param index _KEY or _VALUE + */ + + private void rotateRight(final Node node, final int index) + { + Node left_child = node.getLeft(index); + + node.setLeft(left_child.getRight(index), index); + if (left_child.getRight(index) != null) + { + left_child.getRight(index).setParent(node, index); + } + left_child.setParent(node.getParent(index), index); + if (node.getParent(index) == null) + { + + // node was the root ... now its left child is the root + _root[ index ] = left_child; + } + else if (node.getParent(index).getRight(index) == node) + { + node.getParent(index).setRight(left_child, index); + } + else + { + node.getParent(index).setLeft(left_child, index); + } + left_child.setRight(node, index); + node.setParent(left_child, index); + } + + /** + * complicated red-black insert stuff. Based on Sun's TreeMap + * implementation, though it's barely recognizeable any more + * + * @param inserted_node the node to be inserted + * @param index _KEY or _VALUE + */ + + private void doRedBlackInsert(final Node inserted_node, final int index) + { + Node current_node = inserted_node; + + makeRed(current_node, index); + while ((current_node != null) && (current_node != _root[ index ]) + && (isRed(current_node.getParent(index), index))) + { + if (isLeftChild(getParent(current_node, index), index)) + { + Node y = getRightChild(getGrandParent(current_node, index), + index); + + if (isRed(y, index)) + { + makeBlack(getParent(current_node, index), index); + makeBlack(y, index); + makeRed(getGrandParent(current_node, index), index); + current_node = getGrandParent(current_node, index); + } + else + { + if (isRightChild(current_node, index)) + { + current_node = getParent(current_node, index); + rotateLeft(current_node, index); + } + makeBlack(getParent(current_node, index), index); + makeRed(getGrandParent(current_node, index), index); + if (getGrandParent(current_node, index) != null) + { + rotateRight(getGrandParent(current_node, index), + index); + } + } + } + else + { + + // just like clause above, except swap left for right + Node y = getLeftChild(getGrandParent(current_node, index), + index); + + if (isRed(y, index)) + { + makeBlack(getParent(current_node, index), index); + makeBlack(y, index); + makeRed(getGrandParent(current_node, index), index); + current_node = getGrandParent(current_node, index); + } + else + { + if (isLeftChild(current_node, index)) + { + current_node = getParent(current_node, index); + rotateRight(current_node, index); + } + makeBlack(getParent(current_node, index), index); + makeRed(getGrandParent(current_node, index), index); + if (getGrandParent(current_node, index) != null) + { + rotateLeft(getGrandParent(current_node, index), + index); + } + } + } + } + makeBlack(_root[ index ], index); + } + + /** + * complicated red-black delete stuff. Based on Sun's TreeMap + * implementation, though it's barely recognizeable any more + * + * @param deleted_node the node to be deleted + */ + + private void doRedBlackDelete(final Node deleted_node) + { + for (int index = _MINIMUM_INDEX; index < _INDEX_COUNT; index++) + { + + // if deleted node has both left and children, swap with + // the next greater node + if ((deleted_node.getLeft(index) != null) + && (deleted_node.getRight(index) != null)) + { + swapPosition(nextGreater(deleted_node, index), deleted_node, + index); + } + Node replacement = ((deleted_node.getLeft(index) != null) + ? deleted_node.getLeft(index) + : deleted_node.getRight(index)); + + if (replacement != null) + { + replacement.setParent(deleted_node.getParent(index), index); + if (deleted_node.getParent(index) == null) + { + _root[ index ] = replacement; + } + else if (deleted_node + == deleted_node.getParent(index).getLeft(index)) + { + deleted_node.getParent(index).setLeft(replacement, index); + } + else + { + deleted_node.getParent(index).setRight(replacement, + index); + } + deleted_node.setLeft(null, index); + deleted_node.setRight(null, index); + deleted_node.setParent(null, index); + if (isBlack(deleted_node, index)) + { + doRedBlackDeleteFixup(replacement, index); + } + } + else + { + + // replacement is null + if (deleted_node.getParent(index) == null) + { + + // empty tree + _root[ index ] = null; + } + else + { + + // deleted node had no children + if (isBlack(deleted_node, index)) + { + doRedBlackDeleteFixup(deleted_node, index); + } + if (deleted_node.getParent(index) != null) + { + if (deleted_node + == deleted_node.getParent(index) + .getLeft(index)) + { + deleted_node.getParent(index).setLeft(null, + index); + } + else + { + deleted_node.getParent(index).setRight(null, + index); + } + deleted_node.setParent(null, index); + } + } + } + } + shrink(); + } + + /** + * complicated red-black delete stuff. Based on Sun's TreeMap + * implementation, though it's barely recognizeable any more. This + * rebalances the tree (somewhat, as red-black trees are not + * perfectly balanced -- perfect balancing takes longer) + * + * @param deleted_node the node being replaced + * @param index _KEY or _VALUE + */ + + private void doRedBlackDeleteFixup(final Node replacement_node, + final int index) + { + Node current_node = replacement_node; + + while ((current_node != _root[ index ]) + && (isBlack(current_node, index))) + { + if (isLeftChild(current_node, index)) + { + Node sibling_node = + getRightChild(getParent(current_node, index), index); + + if (isRed(sibling_node, index)) + { + makeBlack(sibling_node, index); + makeRed(getParent(current_node, index), index); + rotateLeft(getParent(current_node, index), index); + sibling_node = + getRightChild(getParent(current_node, index), index); + } + if (isBlack(getLeftChild(sibling_node, index), index) + && isBlack(getRightChild(sibling_node, index), index)) + { + makeRed(sibling_node, index); + current_node = getParent(current_node, index); + } + else + { + if (isBlack(getRightChild(sibling_node, index), index)) + { + makeBlack(getLeftChild(sibling_node, index), index); + makeRed(sibling_node, index); + rotateRight(sibling_node, index); + sibling_node = + getRightChild(getParent(current_node, index), + index); + } + copyColor(getParent(current_node, index), sibling_node, + index); + makeBlack(getParent(current_node, index), index); + makeBlack(getRightChild(sibling_node, index), index); + rotateLeft(getParent(current_node, index), index); + current_node = _root[ index ]; + } + } + else + { + Node sibling_node = + getLeftChild(getParent(current_node, index), index); + + if (isRed(sibling_node, index)) + { + makeBlack(sibling_node, index); + makeRed(getParent(current_node, index), index); + rotateRight(getParent(current_node, index), index); + sibling_node = + getLeftChild(getParent(current_node, index), index); + } + if (isBlack(getRightChild(sibling_node, index), index) + && isBlack(getLeftChild(sibling_node, index), index)) + { + makeRed(sibling_node, index); + current_node = getParent(current_node, index); + } + else + { + if (isBlack(getLeftChild(sibling_node, index), index)) + { + makeBlack(getRightChild(sibling_node, index), index); + makeRed(sibling_node, index); + rotateLeft(sibling_node, index); + sibling_node = + getLeftChild(getParent(current_node, index), + index); + } + copyColor(getParent(current_node, index), sibling_node, + index); + makeBlack(getParent(current_node, index), index); + makeBlack(getLeftChild(sibling_node, index), index); + rotateRight(getParent(current_node, index), index); + current_node = _root[ index ]; + } + } + } + makeBlack(current_node, index); + } + + /** + * swap two nodes (except for their content), taking care of + * special cases where one is the other's parent ... hey, it + * happens. + * + * @param x one node + * @param y another node + * @param index _KEY or _VALUE + */ + + private void swapPosition(final Node x, final Node y, final int index) + { + + // Save initial values. + Node x_old_parent = x.getParent(index); + Node x_old_left_child = x.getLeft(index); + Node x_old_right_child = x.getRight(index); + Node y_old_parent = y.getParent(index); + Node y_old_left_child = y.getLeft(index); + Node y_old_right_child = y.getRight(index); + boolean x_was_left_child = + (x.getParent(index) != null) + && (x == x.getParent(index).getLeft(index)); + boolean y_was_left_child = + (y.getParent(index) != null) + && (y == y.getParent(index).getLeft(index)); + + // Swap, handling special cases of one being the other's parent. + if (x == y_old_parent) + { // x was y's parent + x.setParent(y, index); + if (y_was_left_child) + { + y.setLeft(x, index); + y.setRight(x_old_right_child, index); + } + else + { + y.setRight(x, index); + y.setLeft(x_old_left_child, index); + } + } + else + { + x.setParent(y_old_parent, index); + if (y_old_parent != null) + { + if (y_was_left_child) + { + y_old_parent.setLeft(x, index); + } + else + { + y_old_parent.setRight(x, index); + } + } + y.setLeft(x_old_left_child, index); + y.setRight(x_old_right_child, index); + } + if (y == x_old_parent) + { // y was x's parent + y.setParent(x, index); + if (x_was_left_child) + { + x.setLeft(y, index); + x.setRight(y_old_right_child, index); + } + else + { + x.setRight(y, index); + x.setLeft(y_old_left_child, index); + } + } + else + { + y.setParent(x_old_parent, index); + if (x_old_parent != null) + { + if (x_was_left_child) + { + x_old_parent.setLeft(y, index); + } + else + { + x_old_parent.setRight(y, index); + } + } + x.setLeft(y_old_left_child, index); + x.setRight(y_old_right_child, index); + } + + // Fix children's parent pointers + if (x.getLeft(index) != null) + { + x.getLeft(index).setParent(x, index); + } + if (x.getRight(index) != null) + { + x.getRight(index).setParent(x, index); + } + if (y.getLeft(index) != null) + { + y.getLeft(index).setParent(y, index); + } + if (y.getRight(index) != null) + { + y.getRight(index).setParent(y, index); + } + x.swapColors(y, index); + + // Check if _root changed + if (_root[ index ] == x) + { + _root[ index ] = y; + } + else if (_root[ index ] == y) + { + _root[ index ] = x; + } + } + + /** + * check if an object is fit to be proper input ... has to be + * Comparable and non-null + * + * @param o the object being checked + * @param index _KEY or _VALUE (used to put the right word in the + * exception message) + * + * @exception NullPointerException if o is null + * @exception ClassCastException if o is not Comparable + */ + + private static void checkNonNullComparable(final Object o, + final int index) + { + if (o == null) + { + throw new NullPointerException(_data_name[ index ] + + " cannot be null"); + } + if (!(o instanceof Comparable)) + { + throw new ClassCastException(_data_name[ index ] + + " must be Comparable"); + } + } + + /** + * check a key for validity (non-null and implements Comparable) + * + * @param key the key to be checked + * + * @exception NullPointerException if key is null + * @exception ClassCastException if key is not Comparable + */ + + private static void checkKey(final Object key) + { + checkNonNullComparable(key, _KEY); + } + + /** + * check a value for validity (non-null and implements Comparable) + * + * @param value the value to be checked + * + * @exception NullPointerException if value is null + * @exception ClassCastException if value is not Comparable + */ + + private static void checkValue(final Object value) + { + checkNonNullComparable(value, _VALUE); + } + + /** + * check a key and a value for validity (non-null and implements + * Comparable) + * + * @param key the key to be checked + * @param value the value to be checked + * + * @exception NullPointerException if key or value is null + * @exception ClassCastException if key or value is not Comparable + */ + + private static void checkKeyAndValue(final Object key, final Object value) + { + checkKey(key); + checkValue(value); + } + + /** + * increment the modification count -- used to check for + * concurrent modification of the map through the map and through + * an Iterator from one of its Set or Collection views + */ + + private void modify() + { + _modifications++; + } + + /** + * bump up the size and note that the map has changed + */ + + private void grow() + { + modify(); + _size++; + } + + /** + * decrement the size and note that the map has changed + */ + + private void shrink() + { + modify(); + _size--; + } + + /** + * insert a node by its value + * + * @param newNode the node to be inserted + * + * @exception IllegalArgumentException if the node already exists + * in the value mapping + */ + + private void insertValue(final Node newNode) + throws IllegalArgumentException + { + Node node = _root[ _VALUE ]; + + while (true) + { + int cmp = compare(newNode.getData(_VALUE), node.getData(_VALUE)); + + if (cmp == 0) + { + throw new IllegalArgumentException( + "Cannot store a duplicate value (\"" + + newNode.getData(_VALUE) + "\") in this Map"); + } + else if (cmp < 0) + { + if (node.getLeft(_VALUE) != null) + { + node = node.getLeft(_VALUE); + } + else + { + node.setLeft(newNode, _VALUE); + newNode.setParent(node, _VALUE); + doRedBlackInsert(newNode, _VALUE); + break; + } + } + else + { // cmp > 0 + if (node.getRight(_VALUE) != null) + { + node = node.getRight(_VALUE); + } + else + { + node.setRight(newNode, _VALUE); + newNode.setParent(node, _VALUE); + doRedBlackInsert(newNode, _VALUE); + break; + } + } + } + } + + /* ********** START implementation of Map ********** */ + + /** + * Returns the number of key-value mappings in this map. If the + * map contains more than Integer.MAX_VALUE elements, returns + * Integer.MAX_VALUE. + * + * @return the number of key-value mappings in this map. + */ + + public int size() + { + return _size; + } + + /** + * Returns true if this map contains a mapping for the specified + * key. + * + * @param key key whose presence in this map is to be tested. + * + * @return true if this map contains a mapping for the specified + * key. + * + * @exception ClassCastException if the key is of an inappropriate + * type for this map. + * @exception NullPointerException if the key is null + */ + + public boolean containsKey(final Object key) + throws ClassCastException, NullPointerException + { + checkKey(key); + return lookup(( Comparable ) key, _KEY) != null; + } + + /** + * Returns true if this map maps one or more keys to the + * specified value. + * + * @param value value whose presence in this map is to be tested. + * + * @return true if this map maps one or more keys to the specified + * value. + */ + + public boolean containsValue(final Object value) + { + checkValue(value); + return lookup(( Comparable ) value, _VALUE) != null; + } + + /** + * Returns the value to which this map maps the specified + * key. Returns null if the map contains no mapping for this key. + * + * @param key key whose associated value is to be returned. + * + * @return the value to which this map maps the specified key, or + * null if the map contains no mapping for this key. + * + * @exception ClassCastException if the key is of an inappropriate + * type for this map. + * @exception NullPointerException if the key is null + */ + + public Object get(final Object key) + throws ClassCastException, NullPointerException + { + return doGet(( Comparable ) key, _KEY); + } + + /** + * Associates the specified value with the specified key in this + * map. + * + * @param key key with which the specified value is to be + * associated. + * @param value value to be associated with the specified key. + * + * @return null + * + * @exception ClassCastException if the class of the specified key + * or value prevents it from being + * stored in this map. + * @exception NullPointerException if the specified key or value + * is null + * @exception IllegalArgumentException if the key duplicates an + * existing key, or if the + * value duplicates an + * existing value + */ + + public Object put(final Object key, final Object value) + throws ClassCastException, NullPointerException, + IllegalArgumentException + { + checkKeyAndValue(key, value); + Node node = _root[ _KEY ]; + + if (node == null) + { + Node root = new Node(( Comparable ) key, ( Comparable ) value); + + _root[ _KEY ] = root; + _root[ _VALUE ] = root; + grow(); + } + else + { + while (true) + { + int cmp = compare(( Comparable ) key, node.getData(_KEY)); + + if (cmp == 0) + { + throw new IllegalArgumentException( + "Cannot store a duplicate key (\"" + key + + "\") in this Map"); + } + else if (cmp < 0) + { + if (node.getLeft(_KEY) != null) + { + node = node.getLeft(_KEY); + } + else + { + Node newNode = new Node(( Comparable ) key, + ( Comparable ) value); + + insertValue(newNode); + node.setLeft(newNode, _KEY); + newNode.setParent(node, _KEY); + doRedBlackInsert(newNode, _KEY); + grow(); + break; + } + } + else + { // cmp > 0 + if (node.getRight(_KEY) != null) + { + node = node.getRight(_KEY); + } + else + { + Node newNode = new Node(( Comparable ) key, + ( Comparable ) value); + + insertValue(newNode); + node.setRight(newNode, _KEY); + newNode.setParent(node, _KEY); + doRedBlackInsert(newNode, _KEY); + grow(); + break; + } + } + } + } + return null; + } + + /** + * Removes the mapping for this key from this map if present + * + * @param key key whose mapping is to be removed from the map. + * + * @return previous value associated with specified key, or null + * if there was no mapping for key. + */ + + public Object remove(final Object key) + { + return doRemove(( Comparable ) key, _KEY); + } + + /** + * Removes all mappings from this map + */ + + public void clear() + { + modify(); + _size = 0; + _root[ _KEY ] = null; + _root[ _VALUE ] = null; + } + + /** + * Returns a set view of the keys contained in this map. The set + * is backed by the map, so changes to the map are reflected in + * the set, and vice-versa. If the map is modified while an + * iteration over the set is in progress, the results of the + * iteration are undefined. The set supports element removal, + * which removes the corresponding mapping from the map, via the + * Iterator.remove, Set.remove, removeAll, retainAll, and clear + * operations. It does not support the add or addAll operations. + * + * @return a set view of the keys contained in this map. + */ + + public Set keySet() + { + if (_key_set[ _KEY ] == null) + { + _key_set[ _KEY ] = new AbstractSet() + { + public Iterator iterator() + { + return new BinaryTreeIterator(_KEY) + { + protected Object doGetNext() + { + return _last_returned_node.getData(_KEY); + } + }; + } + + public int size() + { + return BinaryTree.this.size(); + } + + public boolean contains(Object o) + { + return containsKey(o); + } + + public boolean remove(Object o) + { + int old_size = _size; + + BinaryTree.this.remove(o); + return _size != old_size; + } + + public void clear() + { + BinaryTree.this.clear(); + } + }; + } + return _key_set[ _KEY ]; + } + + /** + * Returns a collection view of the values contained in this + * map. The collection is backed by the map, so changes to the map + * are reflected in the collection, and vice-versa. If the map is + * modified while an iteration over the collection is in progress, + * the results of the iteration are undefined. The collection + * supports element removal, which removes the corresponding + * mapping from the map, via the Iterator.remove, + * Collection.remove, removeAll, retainAll and clear operations. + * It does not support the add or addAll operations. + * + * @return a collection view of the values contained in this map. + */ + + public Collection values() + { + if (_value_collection[ _KEY ] == null) + { + _value_collection[ _KEY ] = new AbstractCollection() + { + public Iterator iterator() + { + return new BinaryTreeIterator(_KEY) + { + protected Object doGetNext() + { + return _last_returned_node.getData(_VALUE); + } + }; + } + + public int size() + { + return BinaryTree.this.size(); + } + + public boolean contains(Object o) + { + return containsValue(o); + } + + public boolean remove(Object o) + { + int old_size = _size; + + removeValue(o); + return _size != old_size; + } + + public boolean removeAll(Collection c) + { + boolean modified = false; + Iterator iter = c.iterator(); + + while (iter.hasNext()) + { + if (removeValue(iter.next()) != null) + { + modified = true; + } + } + return modified; + } + + public void clear() + { + BinaryTree.this.clear(); + } + }; + } + return _value_collection[ _KEY ]; + } + + /** + * Returns a set view of the mappings contained in this map. Each + * element in the returned set is a Map.Entry. The set is backed + * by the map, so changes to the map are reflected in the set, and + * vice-versa. If the map is modified while an iteration over the + * set is in progress, the results of the iteration are + * undefined. The set supports element removal, which removes the + * corresponding mapping from the map, via the Iterator.remove, + * Set.remove, removeAll, retainAll and clear operations. It does + * not support the add or addAll operations. + * + * @return a set view of the mappings contained in this map. + */ + + public Set entrySet() + { + if (_entry_set[ _KEY ] == null) + { + _entry_set[ _KEY ] = new AbstractSet() + { + public Iterator iterator() + { + return new BinaryTreeIterator(_KEY) + { + protected Object doGetNext() + { + return _last_returned_node; + } + }; + } + + public boolean contains(Object o) + { + if (!(o instanceof Map.Entry)) + { + return false; + } + Map.Entry entry = ( Map.Entry ) o; + Object value = entry.getValue(); + Node node = lookup(( Comparable ) entry.getKey(), + _KEY); + + return (node != null) + && node.getData(_VALUE).equals(value); + } + + public boolean remove(Object o) + { + if (!(o instanceof Map.Entry)) + { + return false; + } + Map.Entry entry = ( Map.Entry ) o; + Object value = entry.getValue(); + Node node = lookup(( Comparable ) entry.getKey(), + _KEY); + + if ((node != null) && node.getData(_VALUE).equals(value)) + { + doRedBlackDelete(node); + return true; + } + return false; + } + + public int size() + { + return BinaryTree.this.size(); + } + + public void clear() + { + BinaryTree.this.clear(); + } + }; + } + return _entry_set[ _KEY ]; + } + + /* ********** END implementation of Map ********** */ + private abstract class BinaryTreeIterator + implements Iterator + { + private int _expected_modifications; + protected Node _last_returned_node; + private Node _next_node; + private int _type; + + /** + * Constructor + * + * @param type + */ + + BinaryTreeIterator(final int type) + { + _type = type; + _expected_modifications = BinaryTree.this._modifications; + _last_returned_node = null; + _next_node = leastNode(_root[ _type ], _type); + } + + /** + * @return 'next', whatever that means for a given kind of + * BinaryTreeIterator + */ + + protected abstract Object doGetNext(); + + /* ********** START implementation of Iterator ********** */ + + /** + * @return true if the iterator has more elements. + */ + + public final boolean hasNext() + { + return _next_node != null; + } + + /** + * @return the next element in the iteration. + * + * @exception NoSuchElementException if iteration has no more + * elements. + * @exception ConcurrentModificationException if the + * BinaryTree is + * modified behind + * the iterator's + * back + */ + + public final Object next() + throws NoSuchElementException, ConcurrentModificationException + { + if (_next_node == null) + { + throw new NoSuchElementException(); + } + if (_modifications != _expected_modifications) + { + throw new ConcurrentModificationException(); + } + _last_returned_node = _next_node; + _next_node = nextGreater(_next_node, _type); + return doGetNext(); + } + + /** + * Removes from the underlying collection the last element + * returned by the iterator. This method can be called only + * once per call to next. The behavior of an iterator is + * unspecified if the underlying collection is modified while + * the iteration is in progress in any way other than by + * calling this method. + * + * @exception IllegalStateException if the next method has not + * yet been called, or the + * remove method has already + * been called after the last + * call to the next method. + * @exception ConcurrentModificationException if the + * BinaryTree is + * modified behind + * the iterator's + * back + */ + + public final void remove() + throws IllegalStateException, ConcurrentModificationException + { + if (_last_returned_node == null) + { + throw new IllegalStateException(); + } + if (_modifications != _expected_modifications) + { + throw new ConcurrentModificationException(); + } + doRedBlackDelete(_last_returned_node); + _expected_modifications++; + _last_returned_node = null; + } + + /* ********** END implementation of Iterator ********** */ + } // end private abstract class BinaryTreeIterator + + // final for performance + private static final class Node + implements Map.Entry + { + private Comparable[] _data; + private Node[] _left; + private Node[] _right; + private Node[] _parent; + private boolean[] _black; + private int _hashcode; + private boolean _calculated_hashcode; + + /** + * Make a new cell with given key and value, and with null + * links, and black (true) colors. + * + * @param key + * @param value + */ + + Node(final Comparable key, final Comparable value) + { + _data = new Comparable[] + { + key, value + }; + _left = new Node[] + { + null, null + }; + _right = new Node[] + { + null, null + }; + _parent = new Node[] + { + null, null + }; + _black = new boolean[] + { + true, true + }; + _calculated_hashcode = false; + } + + /** + * get the specified data + * + * @param index _KEY or _VALUE + * + * @return the key or value + */ + + private Comparable getData(final int index) + { + return _data[ index ]; + } + + /** + * Set this node's left node + * + * @param node the new left node + * @param index _KEY or _VALUE + */ + + private void setLeft(final Node node, final int index) + { + _left[ index ] = node; + } + + /** + * get the left node + * + * @param index _KEY or _VALUE + * + * @return the left node -- may be null + */ + + private Node getLeft(final int index) + { + return _left[ index ]; + } + + /** + * Set this node's right node + * + * @param node the new right node + * @param index _KEY or _VALUE + */ + + private void setRight(final Node node, final int index) + { + _right[ index ] = node; + } + + /** + * get the right node + * + * @param index _KEY or _VALUE + * + * @return the right node -- may be null + */ + + private Node getRight(final int index) + { + return _right[ index ]; + } + + /** + * Set this node's parent node + * + * @param node the new parent node + * @param index _KEY or _VALUE + */ + + private void setParent(final Node node, final int index) + { + _parent[ index ] = node; + } + + /** + * get the parent node + * + * @param index _KEY or _VALUE + * + * @return the parent node -- may be null + */ + + private Node getParent(final int index) + { + return _parent[ index ]; + } + + /** + * exchange colors with another node + * + * @param node the node to swap with + * @param index _KEY or _VALUE + */ + + private void swapColors(final Node node, final int index) + { + + // Swap colors -- old hacker's trick + _black[ index ] ^= node._black[ index ]; + node._black[ index ] ^= _black[ index ]; + _black[ index ] ^= node._black[ index ]; + } + + /** + * is this node black? + * + * @param index _KEY or _VALUE + * + * @return true if black (which is represented as a true boolean) + */ + + private boolean isBlack(final int index) + { + return _black[ index ]; + } + + /** + * is this node red? + * + * @param index _KEY or _VALUE + * + * @return true if non-black + */ + + private boolean isRed(final int index) + { + return !_black[ index ]; + } + + /** + * make this node black + * + * @param index _KEY or _VALUE + */ + + private void setBlack(final int index) + { + _black[ index ] = true; + } + + /** + * make this node red + * + * @param index _KEY or _VALUE + */ + + private void setRed(final int index) + { + _black[ index ] = false; + } + + /** + * make this node the same color as another + * + * @param node the node whose color we're adopting + * @param index _KEY or _VALUE + */ + + private void copyColor(final Node node, final int index) + { + _black[ index ] = node._black[ index ]; + } + + /* ********** START implementation of Map.Entry ********** */ + + /** + * @return the key corresponding to this entry. + */ + + public Object getKey() + { + return _data[ _KEY ]; + } + + /** + * @return the value corresponding to this entry. + */ + + public Object getValue() + { + return _data[ _VALUE ]; + } + + /** + * Optional operation that is not permitted in this + * implementation + * + * @param ignored + * + * @return does not return + * + * @exception UnsupportedOperationException + */ + + public Object setValue(Object ignored) + throws UnsupportedOperationException + { + throw new UnsupportedOperationException( + "Map.Entry.setValue is not supported"); + } + + /** + * Compares the specified object with this entry for equality. + * Returns true if the given object is also a map entry and + * the two entries represent the same mapping. + * + * @param o object to be compared for equality with this map + * entry. + * @return true if the specified object is equal to this map + * entry. + */ + + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof Map.Entry)) + { + return false; + } + Map.Entry e = ( Map.Entry ) o; + + return _data[ _KEY ].equals(e.getKey()) + && _data[ _VALUE ].equals(e.getValue()); + } + + /** + * @return the hash code value for this map entry. + */ + + public int hashCode() + { + if (!_calculated_hashcode) + { + _hashcode = _data[ _KEY ].hashCode() + ^ _data[ _VALUE ].hashCode(); + _calculated_hashcode = true; + } + return _hashcode; + } + + /* ********** END implementation of Map.Entry ********** */ + } +} // end public class BinaryTree + diff --git a/src/java/org/apache/poi/util/BitField.java b/src/java/org/apache/poi/util/BitField.java new file mode 100644 index 000000000..8a95d038a --- /dev/null +++ b/src/java/org/apache/poi/util/BitField.java @@ -0,0 +1,362 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +/** + * Manage operations dealing with bit-mapped fields. + * + * @author Marc Johnson (mjohnson at apache dot org) + * @author Andrew C. Oliver (acoliver at apache dot org) + */ + +public class BitField +{ + private final int _mask; + private final int _shift_count; + + /** + * Create a BitField instance + * + * @param mask the mask specifying which bits apply to this + * BitField. Bits that are set in this mask are the + * bits that this BitField operates on + */ + + public BitField(final int mask) + { + _mask = mask; + int count = 0; + int bit_pattern = mask; + + if (bit_pattern != 0) + { + while ((bit_pattern & 1) == 0) + { + count++; + bit_pattern >>= 1; + } + } + _shift_count = count; + } + + /** + * Obtain the value for the specified BitField, appropriately + * shifted right. Many users of a BitField will want to treat the + * specified bits as an int value, and will not want to be aware + * that the value is stored as a BitField (and so shifted left so + * many bits) + * + * @param holder the int data containing the bits we're interested + * in + * + * @return the selected bits, shifted right appropriately + */ + + public int getValue(final int holder) + { + return getRawValue(holder) >> _shift_count; + } + + /** + * Obtain the value for the specified BitField, appropriately + * shifted right, as a short. Many users of a BitField will want + * to treat the specified bits as an int value, and will not want + * to be aware that the value is stored as a BitField (and so + * shifted left so many bits) + * + * @param holder the short data containing the bits we're + * interested in + * + * @return the selected bits, shifted right appropriately + */ + + public short getShortValue(final short holder) + { + return ( short ) getValue(holder); + } + + /** + * Obtain the value for the specified BitField, unshifted + * + * @param holder the int data containing the bits we're interested + * in + * + * @return the selected bits + */ + + public int getRawValue(final int holder) + { + return (holder & _mask); + } + + /** + * Obtain the value for the specified BitField, unshifted + * + * @param holder the short data containing the bits we're + * interested in + * + * @return the selected bits + */ + + public short getShortRawValue(final short holder) + { + return ( short ) getRawValue(holder); + } + + /** + * Is the field set or not? This is most commonly used for a + * single-bit field, which is often used to represent a boolean + * value; the results of using it for a multi-bit field is to + * determine whether *any* of its bits are set + * + * @param holder the int data containing the bits we're interested + * in + * + * @return true if any of the bits are set, else false + */ + + public boolean isSet(final int holder) + { + return (holder & _mask) != 0; + } + + /** + * Are all of the bits set or not? This is a stricter test than + * isSet, in that all of the bits in a multi-bit set must be set + * for this method to return true + * + * @param holder the int data containing the bits we're interested + * in + * + * @return true if all of the bits are set, else false + */ + + public boolean isAllSet(final int holder) + { + return (holder & _mask) == _mask; + } + + /** + * Replace the bits with new values. + * + * @param holder the int data containint the bits we're interested + * in + * @param value the new value for the specified bits + * + * @return the value of holder with the bits from the value + * parameter replacing the old bits + */ + + public int setValue(final int holder, final int value) + { + return (holder & ~_mask) | ((value << _shift_count) & _mask); + } + + /** + * Replace the bits with new values. + * + * @param holder the short data containing the bits we're + * interested in + * @param value the new value for the specified bits + * + * @return the value of holder with the bits from the value + * parameter replacing the old bits + */ + + public short setShortValue(final short holder, final short value) + { + return ( short ) setValue(holder, value); + } + + /** + * Clear the bits. + * + * @param holder the int data containing the bits we're interested + * in + * + * @return the value of holder with the specified bits cleared + * (set to 0) + */ + + public int clear(final int holder) + { + return holder & ~_mask; + } + + /** + * Clear the bits. + * + * @param holder the short data containing the bits we're + * interested in + * + * @return the value of holder with the specified bits cleared + * (set to 0) + */ + + public short clearShort(final short holder) + { + return ( short ) clear(holder); + } + + /** + * Clear the bits. + * + * @param holder the byte data containing the bits we're + * interested in + * + * @return the value of holder with the specified bits cleared + * (set to 0) + */ + + public byte clearByte(final byte holder) + { + return ( byte ) clear(holder); + } + + /** + * Set the bits. + * + * @param holder the int data containing the bits we're interested + * in + * + * @return the value of holder with the specified bits set to 1 + */ + + public int set(final int holder) + { + return holder | _mask; + } + + /** + * Set the bits. + * + * @param holder the short data containing the bits we're + * interested in + * + * @return the value of holder with the specified bits set to 1 + */ + + public short setShort(final short holder) + { + return ( short ) set(holder); + } + + /** + * Set the bits. + * + * @param holder the byte data containing the bits we're + * interested in + * + * @return the value of holder with the specified bits set to 1 + */ + + public byte setByte(final byte holder) + { + return ( byte ) set(holder); + } + + /** + * Set a boolean BitField + * + * @param holder the int data containing the bits we're interested + * in + * @param flag indicating whether to set or clear the bits + * + * @return the value of holder with the specified bits set or + * cleared + */ + + public int setBoolean(final int holder, final boolean flag) + { + return flag ? set(holder) + : clear(holder); + } + + /** + * Set a boolean BitField + * + * @param holder the short data containing the bits we're + * interested in + * @param flag indicating whether to set or clear the bits + * + * @return the value of holder with the specified bits set or + * cleared + */ + + public short setShortBoolean(final short holder, final boolean flag) + { + return flag ? setShort(holder) + : clearShort(holder); + } + + /** + * Set a boolean BitField + * + * @param holder the byte data containing the bits we're + * interested in + * @param flag indicating whether to set or clear the bits + * + * @return the value of holder with the specified bits set or + * cleared + */ + + public byte setByteBoolean(final byte holder, final boolean flag) + { + return flag ? setByte(holder) + : clearByte(holder); + } +} // end public class BitField + diff --git a/src/java/org/apache/poi/util/ByteField.java b/src/java/org/apache/poi/util/ByteField.java new file mode 100644 index 000000000..3389572d1 --- /dev/null +++ b/src/java/org/apache/poi/util/ByteField.java @@ -0,0 +1,257 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +import org.apache.poi.util.LittleEndian.BufferUnderrunException; + +import java.io.*; + +/** + * representation of a byte (8-bit) field at a fixed location within a + * byte array + * + * @author Marc Johnson (mjohnson at apache dot org + */ + +public class ByteField + implements FixedField +{ + private static final byte _default_value = 0; + private byte _value; + private final int _offset; + + /** + * construct the ByteField with its offset into its containing + * byte array and a default value of 0 + * + * @param offset of the field within its byte array + * + * @exception ArrayIndexOutOfBoundsException if offset is negative + */ + + public ByteField(final int offset) + throws ArrayIndexOutOfBoundsException + { + this(offset, _default_value); + } + + /** + * construct the ByteField with its offset into its containing + * byte array and initialize its value + * + * @param offset of the field within its byte array + * @param value the initial value + * + * @exception ArrayIndexOutOfBoundsException if offset is negative + */ + + public ByteField(final int offset, final byte value) + throws ArrayIndexOutOfBoundsException + { + if (offset < 0) + { + throw new ArrayIndexOutOfBoundsException( + "offset cannot be negative"); + } + _offset = offset; + set(value); + } + + /** + * Construct the ByteField with its offset into its containing + * byte array and initialize its value from its byte array + * + * @param offset of the field within its byte array + * @param data the byte array to read the value from + * + * @exception ArrayIndexOutOfBoundsException if the offset is not + * within the range of 0..(data.length - 1) + */ + + public ByteField(final int offset, final byte [] data) + throws ArrayIndexOutOfBoundsException + { + this(offset); + readFromBytes(data); + } + + /** + * construct the ByteField with its offset into its containing + * byte array, initialize its value, and write its value to its + * byte array + * + * @param offset of the field within its byte array + * @param value the initial value + * @param data the byte array to write the value to + * + * @exception ArrayIndexOutOfBoundsException if the offset is not + * within the range of 0..(data.length - 1) + */ + + public ByteField(final int offset, final byte value, final byte [] data) + throws ArrayIndexOutOfBoundsException + { + this(offset, value); + writeToBytes(data); + } + + /** + * get the ByteField's current value + * + * @return current value + */ + + public byte get() + { + return _value; + } + + /** + * set the ByteField's current value + * + * @param value to be set + */ + + public void set(final byte value) + { + _value = value; + } + + /** + * set the ByteField's current value and write it to a byte array + * + * @param value to be set + * @param data the byte array to write the value to + * + * @exception ArrayIndexOutOfBoundsException if the offset is out + * of the byte array's range + */ + + public void set(final byte value, final byte [] data) + throws ArrayIndexOutOfBoundsException + { + set(value); + writeToBytes(data); + } + + /* ********** START implementation of FixedField ********** */ + + /** + * set the value from its offset into an array of bytes + * + * @param data the byte array from which the value is to be read + * + * @exception ArrayIndexOutOfBoundsException if the offset is out + * of range of the bte array + */ + + public void readFromBytes(final byte [] data) + throws ArrayIndexOutOfBoundsException + { + _value = data[ _offset ]; + } + + /** + * set the value from an InputStream + * + * @param stream the InputStream from which the value is to be + * read + * + * @exception BufferUnderrunException if there is not enough data + * available from the InputStream + * @exception IOException if an IOException is thrown from reading + * the InputStream + */ + + public void readFromStream(final InputStream stream) + throws IOException, BufferUnderrunException + { + _value = + (LittleEndian.readFromStream(stream, + LittleEndianConsts.BYTE_SIZE))[ 0 ]; + } + + /** + * write the value out to an array of bytes at the appropriate + * offset + * + * @param data the array of bytes to which the value is to be + * written + * + * @exception ArrayIndexOutOfBoundsException if the offset is out + * of the byte array's range + */ + + public void writeToBytes(final byte [] data) + throws ArrayIndexOutOfBoundsException + { + data[ _offset ] = _value; + } + + /** + * return the value as a String + * + * @return the value as a String + */ + + public String toString() + { + return String.valueOf(_value); + } + + /* ********** END implementation of FixedField ********** */ +} // end public class ByteField + diff --git a/src/java/org/apache/poi/util/FixedField.java b/src/java/org/apache/poi/util/FixedField.java new file mode 100644 index 000000000..298a0f1bc --- /dev/null +++ b/src/java/org/apache/poi/util/FixedField.java @@ -0,0 +1,120 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +import org.apache.poi.util.LittleEndian.BufferUnderrunException; + +import java.io.*; + +/** + * behavior of a field at a fixed location within a byte array + * + * @author Marc Johnson (mjohnson at apache dot org + */ + +public interface FixedField +{ + + /** + * set the value from its offset into an array of bytes + * + * @param data the byte array from which the value is to be read + * + * @exception ArrayIndexOutOfBoundsException if the offset is out + * of the array's valid index range + */ + + public void readFromBytes(byte [] data) + throws ArrayIndexOutOfBoundsException; + + /** + * set the value from an InputStream + * + * @param stream the InputStream from which the value is to be + * read + * + * @exception BufferUnderrunException if there is not enough data + * available from the InputStream + * @exception IOException if an IOException is thrown from reading + * the InputStream + */ + + public void readFromStream(InputStream stream) + throws IOException, BufferUnderrunException; + + /** + * write the value out to an array of bytes at the appropriate + * offset + * + * @param data the array of bytes to which the value is to be + * written + * + * @exception ArrayIndexOutOfBoundsException if the offset is out + * of the array's valid index range + */ + + public void writeToBytes(byte [] data) + throws ArrayIndexOutOfBoundsException; + + /** + * return the value as a String + * + * @return the value as a String + */ + + public String toString(); +} // end public interface FixedField + diff --git a/src/java/org/apache/poi/util/HexDump.java b/src/java/org/apache/poi/util/HexDump.java new file mode 100644 index 000000000..d2d54e819 --- /dev/null +++ b/src/java/org/apache/poi/util/HexDump.java @@ -0,0 +1,184 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +import java.io.*; + +/** + * dump data in hexadecimal format; derived from a HexDump utility I + * wrote in June 2001 + * + * @author Marc Johnson + */ + +public class HexDump +{ + + // all static methods, so no need for a public constructor + private HexDump() + { + } + + /** + * 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 static void dump(final byte [] data, final long offset, + final OutputStream stream, final int index) + throws IOException, ArrayIndexOutOfBoundsException, + IllegalArgumentException + { + if ((index < 0) || (index >= data.length)) + { + throw new ArrayIndexOutOfBoundsException( + "illegal index: " + index + " into array of length " + + data.length); + } + if (stream == null) + { + throw new IllegalArgumentException("cannot write to nullstream"); + } + long display_offset = offset + index; + StringBuffer buffer = new StringBuffer(74); + + for (int j = index; j < data.length; j += 16) + { + int chars_read = data.length - j; + + if (chars_read > 16) + { + chars_read = 16; + } + buffer.append(dump(display_offset)).append(' '); + for (int k = 0; k < 16; k++) + { + if (k < chars_read) + { + buffer.append(dump(data[ k + j ])); + } + else + { + buffer.append(" "); + } + buffer.append(' '); + } + for (int k = 0; k < chars_read; k++) + { + if ((data[ k + j ] >= ' ') && (data[ k + j ] < 127)) + { + buffer.append(( char ) data[ k + j ]); + } + else + { + buffer.append('.'); + } + } + buffer.append(EOL); + stream.write(buffer.toString().getBytes()); + stream.flush(); + buffer.setLength(0); + display_offset += chars_read; + } + } + + public static final String EOL = + System.getProperty("line.separator"); + private static final StringBuffer _lbuffer = new StringBuffer(8); + private static final StringBuffer _cbuffer = new StringBuffer(2); + private static final char _hexcodes[] = + { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', + 'E', 'F' + }; + private static final int _shifts[] = + { + 28, 24, 20, 16, 12, 8, 4, 0 + }; + + private static StringBuffer dump(final long value) + { + _lbuffer.setLength(0); + for (int j = 0; j < 8; j++) + { + _lbuffer + .append(_hexcodes[ (( int ) (value >> _shifts[ j ])) & 15 ]); + } + return _lbuffer; + } + + private static StringBuffer dump(final byte value) + { + _cbuffer.setLength(0); + for (int j = 0; j < 2; j++) + { + _cbuffer.append(_hexcodes[ (value >> _shifts[ j + 6 ]) & 15 ]); + } + return _cbuffer; + } +} diff --git a/src/java/org/apache/poi/util/IntList.java b/src/java/org/apache/poi/util/IntList.java new file mode 100644 index 000000000..79e7a6bbb --- /dev/null +++ b/src/java/org/apache/poi/util/IntList.java @@ -0,0 +1,678 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +import java.util.*; + +/** + * A List of int's; as full an implementation of the java.util.List + * interface as possible, with an eye toward minimal creation of + * objects + * + * the mimicry of List is as follows: + *

    + *
  • if possible, operations designated 'optional' in the List + * interface are attempted + *
  • wherever the List interface refers to an Object, substitute + * int + *
  • wherever the List interface refers to a Collection or List, + * substitute IntList + *
+ * + * the mimicry is not perfect, however: + *
    + *
  • operations involving Iterators or ListIterators are not + * supported + *
  • remove(Object) becomes removeValue to distinguish it from + * remove(int index) + *
  • subList is not supported + *
+ * + * @author Marc Johnson + */ + +public class IntList +{ + private int[] _array; + private int _limit; + private static final int _default_size = 128; + + /** + * create an IntList of default size + */ + + public IntList() + { + this(_default_size); + } + + /** + * create a copy of an existing IntList + * + * @param list the existing IntList + */ + + public IntList(final IntList list) + { + this(list._array.length); + System.arraycopy(list._array, 0, _array, 0, _array.length); + _limit = list._limit; + } + + /** + * create an IntList with a predefined initial size + * + * @param initialCapacity the size for the internal array + */ + + public IntList(final int initialCapacity) + { + _array = new int[ initialCapacity ]; + _limit = 0; + } + + /** + * add the specfied value at the specified index + * + * @param index the index where the new value is to be added + * @param value the new value + * + * @exception IndexOutOfBoundsException if the index is out of + * range (index < 0 || index > size()). + */ + + public void add(final int index, final int value) + { + if (index > _limit) + { + throw new IndexOutOfBoundsException(); + } + else if (index == _limit) + { + add(value); + } + else + { + + // index < limit -- insert into the middle + if (_limit == _array.length) + { + growArray(_limit * 2); + } + System.arraycopy(_array, index, _array, index + 1, + _limit - index); + _array[ index ] = value; + _limit++; + } + } + + /** + * Appends the specified element to the end of this list + * + * @param value element to be appended to this list. + * + * @return true (as per the general contract of the Collection.add + * method). + */ + + public boolean add(final int value) + { + if (_limit == _array.length) + { + growArray(_limit * 2); + } + _array[ _limit++ ] = value; + return true; + } + + /** + * Appends all of the elements in the specified collection to the + * end of this list, in the order that they are returned by the + * specified collection's iterator. The behavior of this + * operation is unspecified if the specified collection is + * modified while the operation is in progress. (Note that this + * will occur if the specified collection is this list, and it's + * nonempty.) + * + * @param c collection whose elements are to be added to this + * list. + * + * @return true if this list changed as a result of the call. + */ + + public boolean addAll(final IntList c) + { + if (c._limit != 0) + { + if ((_limit + c._limit) > _array.length) + { + growArray(_limit + c._limit); + } + System.arraycopy(c._array, 0, _array, _limit, c._limit); + _limit += c._limit; + } + return true; + } + + /** + * Inserts all of the elements in the specified collection into + * this list at the specified position. Shifts the element + * currently at that position (if any) and any subsequent elements + * to the right (increases their indices). The new elements will + * appear in this list in the order that they are returned by the + * specified collection's iterator. The behavior of this + * operation is unspecified if the specified collection is + * modified while the operation is in progress. (Note that this + * will occur if the specified collection is this list, and it's + * nonempty.) + * + * @param index index at which to insert first element from the + * specified collection. + * @param c elements to be inserted into this list. + * + * @return true if this list changed as a result of the call. + * + * @exception IndexOutOfBoundsException if the index is out of + * range (index < 0 || index > size()) + */ + + public boolean addAll(final int index, final IntList c) + { + if (index > _limit) + { + throw new IndexOutOfBoundsException(); + } + if (c._limit != 0) + { + if ((_limit + c._limit) > _array.length) + { + growArray(_limit + c._limit); + } + + // make a hole + System.arraycopy(_array, index, _array, index + c._limit, + _limit - index); + + // fill it in + System.arraycopy(c._array, 0, _array, index, c._limit); + _limit += c._limit; + } + return true; + } + + /** + * Removes all of the elements from this list. This list will be + * empty after this call returns (unless it throws an exception). + */ + + public void clear() + { + _limit = 0; + } + + /** + * Returns true if this list contains the specified element. More + * formally, returns true if and only if this list contains at + * least one element e such that o == e + * + * @param o element whose presence in this list is to be tested. + * + * @return true if this list contains the specified element. + */ + + public boolean contains(final int o) + { + boolean rval = false; + + for (int j = 0; !rval && (j < _limit); j++) + { + if (_array[ j ] == o) + { + rval = true; + } + } + return rval; + } + + /** + * Returns true if this list contains all of the elements of the + * specified collection. + * + * @param c collection to be checked for containment in this list. + * + * @return true if this list contains all of the elements of the + * specified collection. + */ + + public boolean containsAll(final IntList c) + { + boolean rval = true; + + if (this != c) + { + for (int j = 0; rval && (j < c._limit); j++) + { + if (!contains(c._array[ j ])) + { + rval = false; + } + } + } + return rval; + } + + /** + * Compares the specified object with this list for equality. + * Returns true if and only if the specified object is also a + * list, both lists have the same size, and all corresponding + * pairs of elements in the two lists are equal. (Two elements e1 + * and e2 are equal if e1 == e2.) In other words, two lists are + * defined to be equal if they contain the same elements in the + * same order. This definition ensures that the equals method + * works properly across different implementations of the List + * interface. + * + * @param o the object to be compared for equality with this list. + * + * @return true if the specified object is equal to this list. + */ + + public boolean equals(final Object o) + { + boolean rval = this == o; + + if (!rval && (o != null) && (o.getClass() == this.getClass())) + { + IntList other = ( IntList ) o; + + if (other._limit == _limit) + { + + // assume match + rval = true; + for (int j = 0; rval && (j < _limit); j++) + { + rval = _array[ j ] == other._array[ j ]; + } + } + } + return rval; + } + + /** + * Returns the element at the specified position in this list. + * + * @param index index of element to return. + * + * @return the element at the specified position in this list. + * + * @exception IndexOutOfBoundsException if the index is out of + * range (index < 0 || index >= size()). + */ + + public int get(final int index) + { + if (index >= _limit) + { + throw new IndexOutOfBoundsException(); + } + return _array[ index ]; + } + + /** + * Returns the hash code value for this list. The hash code of a + * list is defined to be the result of the following calculation: + * + * + * hashCode = 1; + * Iterator i = list.iterator(); + * while (i.hasNext()) { + * Object obj = i.next(); + * hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode()); + * } + * + * + * This ensures that list1.equals(list2) implies that + * list1.hashCode()==list2.hashCode() for any two lists, list1 and + * list2, as required by the general contract of Object.hashCode. + * + * @return the hash code value for this list. + */ + + public int hashCode() + { + int hash = 0; + + for (int j = 0; j < _limit; j++) + { + hash = (31 * hash) + _array[ j ]; + } + return hash; + } + + /** + * Returns the index in this list of the first occurrence of the + * specified element, or -1 if this list does not contain this + * element. More formally, returns the lowest index i such that + * (o == get(i)), or -1 if there is no such index. + * + * @param o element to search for. + * + * @return the index in this list of the first occurrence of the + * specified element, or -1 if this list does not contain + * this element. + */ + + public int indexOf(final int o) + { + int rval = 0; + + for (; rval < _limit; rval++) + { + if (o == _array[ rval ]) + { + break; + } + } + if (rval == _limit) + { + rval = -1; // didn't find it + } + return rval; + } + + /** + * Returns true if this list contains no elements. + * + * @return true if this list contains no elements. + */ + + public boolean isEmpty() + { + return _limit == 0; + } + + /** + * Returns the index in this list of the last occurrence of the + * specified element, or -1 if this list does not contain this + * element. More formally, returns the highest index i such that + * (o == get(i)), or -1 if there is no such index. + * + * @param o element to search for. + * + * @return the index in this list of the last occurrence of the + * specified element, or -1 if this list does not contain + * this element. + */ + + public int lastIndexOf(final int o) + { + int rval = _limit - 1; + + for (; rval >= 0; rval--) + { + if (o == _array[ rval ]) + { + break; + } + } + return rval; + } + + /** + * Removes the element at the specified position in this list. + * Shifts any subsequent elements to the left (subtracts one from + * their indices). Returns the element that was removed from the + * list. + * + * @param index the index of the element to removed. + * + * @return the element previously at the specified position. + * + * @exception IndexOutOfBoundsException if the index is out of + * range (index < 0 || index >= size()). + */ + + public int remove(final int index) + { + if (index >= _limit) + { + throw new IndexOutOfBoundsException(); + } + int rval = _array[ index ]; + + System.arraycopy(_array, index + 1, _array, index, _limit - index); + _limit--; + return rval; + } + + /** + * Removes the first occurrence in this list of the specified + * element (optional operation). If this list does not contain + * the element, it is unchanged. More formally, removes the + * element with the lowest index i such that (o.equals(get(i))) + * (if such an element exists). + * + * @param o element to be removed from this list, if present. + * + * @return true if this list contained the specified element. + */ + + public boolean removeValue(final int o) + { + boolean rval = false; + + for (int j = 0; !rval && (j < _limit); j++) + { + if (o == _array[ j ]) + { + System.arraycopy(_array, j + 1, _array, j, _limit - j); + _limit--; + rval = true; + } + } + return rval; + } + + /** + * Removes from this list all the elements that are contained in + * the specified collection + * + * @param c collection that defines which elements will be removed + * from this list. + * + * @return true if this list changed as a result of the call. + */ + + public boolean removeAll(final IntList c) + { + boolean rval = false; + + for (int j = 0; j < c._limit; j++) + { + if (removeValue(c._array[ j ])) + { + rval = true; + } + } + return rval; + } + + /** + * Retains only the elements in this list that are contained in + * the specified collection. In other words, removes from this + * list all the elements that are not contained in the specified + * collection. + * + * @param c collection that defines which elements this set will + * retain. + * + * @return true if this list changed as a result of the call. + */ + + public boolean retainAll(final IntList c) + { + boolean rval = false; + + for (int j = 0; j < _limit; ) + { + if (!c.contains(_array[ j ])) + { + remove(j); + rval = true; + } + else + { + j++; + } + } + return rval; + } + + /** + * Replaces the element at the specified position in this list + * with the specified element + * + * @param index index of element to replace. + * @param element element to be stored at the specified position. + * + * @return the element previously at the specified position. + * + * @exception IndexOutOfBoundsException if the index is out of + * range (index < 0 || index >= size()). + */ + + public int set(final int index, final int element) + { + if (index >= _limit) + { + throw new IndexOutOfBoundsException(); + } + int rval = _array[ index ]; + + _array[ index ] = element; + return rval; + } + + /** + * Returns the number of elements in this list. If this list + * contains more than Integer.MAX_VALUE elements, returns + * Integer.MAX_VALUE. + * + * @return the number of elements in this IntList + */ + + public int size() + { + return _limit; + } + + /** + * Returns an array containing all of the elements in this list in + * proper sequence. Obeys the general contract of the + * Collection.toArray method. + * + * @return an array containing all of the elements in this list in + * proper sequence. + */ + + public int [] toArray() + { + int[] rval = new int[ _limit ]; + + System.arraycopy(_array, 0, rval, 0, _limit); + return rval; + } + + /** + * Returns an array containing all of the elements in this list in + * proper sequence. Obeys the general contract of the + * Collection.toArray(Object[]) method. + * + * @param a the array into which the elements of this list are to + * be stored, if it is big enough; otherwise, a new array + * is allocated for this purpose. + * + * @return an array containing the elements of this list. + */ + + public int [] toArray(final int [] a) + { + int[] rval; + + if (a.length == _limit) + { + System.arraycopy(_array, 0, a, 0, _limit); + rval = a; + } + else + { + rval = toArray(); + } + return rval; + } + + private void growArray(final int new_size) + { + int size = (new_size == _array.length) ? new_size + 1 + : new_size; + int[] new_array = new int[ size ]; + + System.arraycopy(_array, 0, new_array, 0, _limit); + _array = new_array; + } +} // end public class IntList + diff --git a/src/java/org/apache/poi/util/IntegerField.java b/src/java/org/apache/poi/util/IntegerField.java new file mode 100644 index 000000000..22b6a3aff --- /dev/null +++ b/src/java/org/apache/poi/util/IntegerField.java @@ -0,0 +1,256 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +import org.apache.poi.util.LittleEndian.BufferUnderrunException; + +import java.io.*; + +/** + * representation of an integer (32-bit) field at a fixed location + * within a byte array + * + * @author Marc Johnson (mjohnson at apache dot org + */ + +public class IntegerField + implements FixedField +{ + private int _value; + private final int _offset; + + /** + * construct the IntegerField with its offset into its containing + * byte array + * + * @param offset of the field within its byte array + * + * @exception ArrayIndexOutOfBoundsException if the offset is + * negative + */ + + public IntegerField(final int offset) + throws ArrayIndexOutOfBoundsException + { + if (offset < 0) + { + throw new ArrayIndexOutOfBoundsException("negative offset"); + } + _offset = offset; + } + + /** + * construct the IntegerField with its offset into its containing + * byte array and initialize its value + * + * @param offset of the field within its byte array + * @param value the initial value + * + * @exception ArrayIndexOutOfBoundsException if the offset is + * negative + */ + + public IntegerField(final int offset, final int value) + throws ArrayIndexOutOfBoundsException + { + this(offset); + set(value); + } + + /** + * Construct the IntegerField with its offset into its containing + * byte array and initialize its value from its byte array + * + * @param offset of the field within its byte array + * @param data the byte array to read the value from + * + * @exception ArrayIndexOutOfBoundsException if the offset is not + * within the range of 0..(data.length - 1) + */ + + public IntegerField(final int offset, final byte [] data) + throws ArrayIndexOutOfBoundsException + { + this(offset); + readFromBytes(data); + } + + /** + * construct the IntegerField with its offset into its containing + * byte array, initialize its value, and write the value to a byte + * array + * + * @param offset of the field within its byte array + * @param value the initial value + * @param data the byte array to write the value to + * + * @exception ArrayIndexOutOfBoundsException if the offset is + * negative or too large + */ + + public IntegerField(final int offset, final int value, final byte [] data) + throws ArrayIndexOutOfBoundsException + { + this(offset); + set(value, data); + } + + /** + * get the IntegerField's current value + * + * @return current value + */ + + public int get() + { + return _value; + } + + /** + * set the IntegerField's current value + * + * @param value to be set + */ + + public void set(final int value) + { + _value = value; + } + + /** + * set the IntegerField's current value and write it to a byte + * array + * + * @param value to be set + * @param data the byte array to write the value to + * + * @exception ArrayIndexOutOfBoundsException if the offset is too + * large + */ + + public void set(final int value, final byte [] data) + throws ArrayIndexOutOfBoundsException + { + _value = value; + writeToBytes(data); + } + + /* ********** START implementation of FixedField ********** */ + + /** + * set the value from its offset into an array of bytes + * + * @param data the byte array from which the value is to be read + * + * @exception ArrayIndexOutOfBoundsException if the offset is too + * large + */ + + public void readFromBytes(final byte [] data) + throws ArrayIndexOutOfBoundsException + { + _value = LittleEndian.getInt(data, _offset); + } + + /** + * set the value from an InputStream + * + * @param stream the InputStream from which the value is to be + * read + * + * @exception BufferUnderrunException if there is not enough data + * available from the InputStream + * @exception IOException if an IOException is thrown from reading + * the InputStream + */ + + public void readFromStream(final InputStream stream) + throws IOException, BufferUnderrunException + { + _value = LittleEndian.readInt(stream); + } + + /** + * write the value out to an array of bytes at the appropriate + * offset + * + * @param data the array of bytes to which the value is to be + * written + * + * @exception ArrayIndexOutOfBoundsException if the offset is too + * large + */ + + public void writeToBytes(final byte [] data) + throws ArrayIndexOutOfBoundsException + { + LittleEndian.putInt(data, _offset, _value); + } + + /** + * return the value as a String + * + * @return the value as a String + */ + + public String toString() + { + return String.valueOf(_value); + } + + /* ********** END implementation of FixedField ********** */ +} // end public class IntegerField + diff --git a/src/java/org/apache/poi/util/LittleEndian.java b/src/java/org/apache/poi/util/LittleEndian.java new file mode 100644 index 000000000..259872172 --- /dev/null +++ b/src/java/org/apache/poi/util/LittleEndian.java @@ -0,0 +1,501 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +import java.io.*; + +import java.util.*; + +/** + * a utility class for handling little-endian numbers, which the 80x86 + * world is replete with. The methods are all static, and input/output + * is from/to byte arrays, or from InputStreams. + * + * @author Marc Johnson (mjohnson at apache dot org) + * @author Andrew Oliver (acoliver at apache dot org) + * + */ + +public class LittleEndian + implements LittleEndianConsts +{ + + // all methods are static, so an accessible constructor makes no + // sense + private LittleEndian() + { + } + + /** + * get a short value from a byte array + * + * @param data the byte array + * @param offset a starting offset into the byte array + * + * @return the short (16-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static short getShort(final byte [] data, final int offset) + { + return ( short ) getNumber(data, offset, SHORT_SIZE); + } + + /** + * get a short value from the beginning of a byte array + * + * @param data the byte array + * + * @return the short (16-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static short getShort(final byte [] data) + { + return getShort(data, 0); + } + + /** + * get an int value from a byte array + * + * @param data the byte array + * @param offset a starting offset into the byte array + * + * @return the int (32-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static int getInt(final byte [] data, final int offset) + { + return ( int ) getNumber(data, offset, INT_SIZE); + } + + /** + * get an int value from the beginning of a byte array + * + * @param data the byte array + * + * @return the int (32-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static int getInt(final byte [] data) + { + return getInt(data, 0); + } + + /** + * get a long value from a byte array + * + * @param data the byte array + * @param offset a starting offset into the byte array + * + * @return the long (64-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static long getLong(final byte [] data, final int offset) + { + return getNumber(data, offset, LONG_SIZE); + } + + /** + * get a long value from the beginning of a byte array + * + * @param data the byte array + * + * @return the long (64-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static long getLong(final byte [] data) + { + return getLong(data, 0); + } + + /** + * get a double value from a byte array, reads it in little endian format + * then converts the resulting revolting IEEE 754 (curse them) floating + * point number to a happy java double + * + * @param data the byte array + * @param offset a starting offset into the byte array + * + * @return the double (64-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static double getDouble(final byte [] data, final int offset) + { + return Double.longBitsToDouble(getNumber(data, offset, DOUBLE_SIZE)); + } + + /** + * get a double value from the beginning of a byte array + * + * @param data the byte array + * + * @return the double (64-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static double getDouble(final byte [] data) + { + return getDouble(data, 0); + } + + /** + * put a 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 putShort(final byte [] data, final int offset, + final short value) + { + putNumber(data, offset, value, SHORT_SIZE); + } + + /** + * put a short value into beginning of a byte array + * + * @param data the byte array + * @param value the short (16-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static void putShort(final byte [] data, final short value) + { + putShort(data, 0, value); + } + + /** + * put an int value into a byte array + * + * @param data the byte array + * @param offset a starting offset into the byte array + * @param value the int (32-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static void putInt(final byte [] data, final int offset, + final int value) + { + putNumber(data, offset, value, INT_SIZE); + } + + /** + * put an int value into beginning of a byte array + * + * @param data the byte array + * @param value the int (32-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static void putInt(final byte [] data, final int value) + { + putInt(data, 0, value); + } + + /** + * put a long value into a byte array + * + * @param data the byte array + * @param offset a starting offset into the byte array + * @param value the long (64-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static void putLong(final byte [] data, final int offset, + final long value) + { + putNumber(data, offset, value, LONG_SIZE); + } + + /** + * put a long value into beginning of a byte array + * + * @param data the byte array + * @param value the long (64-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static void putLong(final byte [] data, final long value) + { + putLong(data, 0, value); + } + + /** + * put a double value into a byte array + * + * @param data the byte array + * @param offset a starting offset into the byte array + * @param value the double (64-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static void putDouble(final byte [] data, final int offset, + final double value) + { + putNumber(data, offset, Double.doubleToLongBits(value), DOUBLE_SIZE); + } + + /** + * put a double value into beginning of a byte array + * + * @param data the byte array + * @param value the double (64-bit) value + * + * @exception ArrayIndexOutOfBoundsException may be thrown + */ + + public static void putDouble(final byte [] data, final double value) + { + putDouble(data, 0, value); + } + + /** + * Exception to handle buffer underruns + * + * @author Marc Johnson (mjohnson at apache dot org) + */ + + public static class BufferUnderrunException + extends IOException + { + + /** + * simple constructor + */ + + BufferUnderrunException() + { + super("buffer underrun"); + } + } + + /** + * get a short value from an InputStream + * + * @param stream the InputStream from which the short is to be + * read + * + * @return the short (16-bit) value + * + * @exception IOException will be propagated back to the caller + * @exception BufferUnderrunException if the stream cannot provide + * enough bytes + */ + + public static short readShort(final InputStream stream) + throws IOException, BufferUnderrunException + { + return getShort(readFromStream(stream, SHORT_SIZE)); + } + + /** + * get an int value from an InputStream + * + * @param stream the InputStream from which the int is to be read + * + * @return the int (32-bit) value + * + * @exception IOException will be propagated back to the caller + * @exception BufferUnderrunException if the stream cannot provide + * enough bytes + */ + + public static int readInt(final InputStream stream) + throws IOException, BufferUnderrunException + { + return getInt(readFromStream(stream, INT_SIZE)); + } + + /** + * get a long value from an InputStream + * + * @param stream the InputStream from which the long is to be read + * + * @return the long (64-bit) value + * + * @exception IOException will be propagated back to the caller + * @exception BufferUnderrunException if the stream cannot provide + * enough bytes + */ + + public static long readLong(final InputStream stream) + throws IOException, BufferUnderrunException + { + return getLong(readFromStream(stream, LONG_SIZE)); + } + + private static final byte[] _short_buffer = new byte[ SHORT_SIZE ]; + private static final byte[] _int_buffer = new byte[ INT_SIZE ]; + private static final byte[] _long_buffer = new byte[ LONG_SIZE ]; + + /** + * Read the appropriate number of bytes from the stream and return + * them to the caller. + *

+ * It should be noted that, in an attempt to improve system + * performance and to prevent a transient explosion of discarded + * byte arrays to be garbage collected, static byte arrays are + * employed for the standard cases of reading a short, an int, or + * a long. + *

+ * THIS INTRODUCES A RISK FOR THREADED OPERATIONS! + *

+ * However, for the purposes of the POI project, this risk is + * deemed negligible. It is, however, so noted. + * + * @param stream the InputStream we're reading from + * @param size the number of bytes to read; in 99.99% of cases, + * this will be SHORT_SIZE, INT_SIZE, or LONG_SIZE -- + * but it doesn't have to be. + * + * @return the byte array containing the required number of + * bytes. The array will contain all zero's on end of + * stream + * + * @exception IOException will be propagated back to the caller + * @exception BufferUnderrunException if the stream cannot provide + * enough bytes + */ + + public static byte [] readFromStream(final InputStream stream, + final int size) + throws IOException, BufferUnderrunException + { + byte[] buffer = null; + + switch (size) + { + + case SHORT_SIZE : + buffer = _short_buffer; + break; + + case INT_SIZE : + buffer = _int_buffer; + break; + + case LONG_SIZE : + buffer = _long_buffer; + break; + + default : + buffer = new byte[ size ]; + break; + } + int count = stream.read(buffer); + + if (count == -1) + { + + // return a zero-filled buffer + Arrays.fill(buffer, ( byte ) 0); + } + else if (count != size) + { + throw new BufferUnderrunException(); + } + return buffer; + } + + private static long getNumber(final byte [] data, final int offset, + final int size) + { + long result = 0; + + for (int j = offset + size - 1; j >= offset; j--) + { + result <<= 8; + result |= 0xff & data[ j ]; + } + return result; + } + + private static void putNumber(final byte [] data, final int offset, + final long value, final int size) + { + int limit = size + offset; + long v = value; + + for (int j = offset; j < limit; j++) + { + data[ j ] = ( byte ) (v & 0xFF); + v >>= 8; + } + } +} diff --git a/src/java/org/apache/poi/util/LittleEndianConsts.java b/src/java/org/apache/poi/util/LittleEndianConsts.java new file mode 100644 index 000000000..44721d6cf --- /dev/null +++ b/src/java/org/apache/poi/util/LittleEndianConsts.java @@ -0,0 +1,75 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +/** + * a repository for constants shared by classes within this package + * + * @author Marc Johnson + * @author Andrew C. Oliver (acoliver at apache dot org) + */ + +public interface LittleEndianConsts +{ + + // sizes of various numbers in this environment + public static final int BYTE_SIZE = 1; + public static final int SHORT_SIZE = 2; + public static final int INT_SIZE = 4; + public static final int LONG_SIZE = 8; + public static final int DOUBLE_SIZE = 8; +} // end public interface LittleEndianConsts + diff --git a/src/java/org/apache/poi/util/LongField.java b/src/java/org/apache/poi/util/LongField.java new file mode 100644 index 000000000..4f11c6300 --- /dev/null +++ b/src/java/org/apache/poi/util/LongField.java @@ -0,0 +1,253 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +import org.apache.poi.util.LittleEndian.BufferUnderrunException; + +import java.io.*; + +/** + * representation of a long (16-bit) field at a fixed location within + * a byte array + * + * @author Marc Johnson (mjohnson at apache dot org + */ + +public class LongField + implements FixedField +{ + private long _value; + private final int _offset; + + /** + * construct the LongField with its offset into its containing + * byte array + * + * @param offset of the field within its byte array + * + * @exception ArrayIndexOutOfBoundsException if offset is negative + */ + + public LongField(final int offset) + throws ArrayIndexOutOfBoundsException + { + if (offset < 0) + { + throw new ArrayIndexOutOfBoundsException("Illegal offset: " + + offset); + } + _offset = offset; + } + + /** + * construct the LongField with its offset into its containing + * byte array and initialize its value + * + * @param offset of the field within its byte array + * @param value the initial value + * + * @exception ArrayIndexOutOfBoundsException if offset is negative + */ + + public LongField(final int offset, final long value) + throws ArrayIndexOutOfBoundsException + { + this(offset); + set(value); + } + + /** + * Construct the LongField with its offset into its containing + * byte array and initialize its value from its byte array + * + * @param offset of the field within its byte array + * @param data the byte array to read the value from + * + * @exception ArrayIndexOutOfBoundsException if the offset is not + * within the range of 0..(data.length - 1) + */ + + public LongField(final int offset, final byte [] data) + throws ArrayIndexOutOfBoundsException + { + this(offset); + readFromBytes(data); + } + + /** + * construct the LongField with its offset into its containing + * byte array, initialize its value, and write the value to a byte + * array + * + * @param offset of the field within its byte array + * @param value the initial value + * @param data the byte array to write the value to + * + * @exception ArrayIndexOutOfBoundsException if offset is negative + */ + + public LongField(final int offset, final long value, final byte [] data) + throws ArrayIndexOutOfBoundsException + { + this(offset); + set(value, data); + } + + /** + * get the LongField's current value + * + * @return current value + */ + + public long get() + { + return _value; + } + + /** + * set the LongField's current value + * + * @param value to be set + */ + + public void set(final long value) + { + _value = value; + } + + /** + * set the LongField's current value and write it to a byte array + * + * @param value to be set + * @param data the byte array to write the value to + * + * @exception ArrayIndexOutOfBoundsException if the offset is out + * of range + */ + + public void set(final long value, final byte [] data) + throws ArrayIndexOutOfBoundsException + { + _value = value; + writeToBytes(data); + } + + /* ********** START implementation of FixedField ********** */ + + /** + * set the value from its offset into an array of bytes + * + * @param data the byte array from which the value is to be read + * + * @exception ArrayIndexOutOfBoundsException if the offset is out + * of range + */ + + public void readFromBytes(final byte [] data) + throws ArrayIndexOutOfBoundsException + { + _value = LittleEndian.getLong(data, _offset); + } + + /** + * set the value from an InputStream + * + * @param stream the InputStream from which the value is to be + * read + * + * @exception BufferUnderrunException if there is not enough data + * available from the InputStream + * @exception IOException if an IOException is thrown from reading + * the InputStream + */ + + public void readFromStream(final InputStream stream) + throws IOException, BufferUnderrunException + { + _value = LittleEndian.readLong(stream); + } + + /** + * write the value out to an array of bytes at the appropriate + * offset + * + * @param data the array of bytes to which the value is to be + * written + * + * @exception ArrayIndexOutOfBoundsException if the offset is out + * of range + */ + + public void writeToBytes(final byte [] data) + throws ArrayIndexOutOfBoundsException + { + LittleEndian.putLong(data, _offset, _value); + } + + /** + * return the value as a String + * + * @return the value as a String + */ + + public String toString() + { + return String.valueOf(_value); + } + + /* ********** END implementation of FixedField ********** */ +} // end public class LongField + diff --git a/src/java/org/apache/poi/util/POILogFactory.java b/src/java/org/apache/poi/util/POILogFactory.java new file mode 100644 index 000000000..628ff8306 --- /dev/null +++ b/src/java/org/apache/poi/util/POILogFactory.java @@ -0,0 +1,143 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +import java.io.FileInputStream; +import java.io.IOException; + +import java.util.*; + +import org.apache.log4j.Category; +import org.apache.log4j.ConsoleAppender; +import org.apache.log4j.Hierarchy; +import org.apache.log4j.PropertyConfigurator; +import org.apache.log4j.SimpleLayout; +import org.apache.log4j.spi.RootCategory; + +/** + * Provides logging without clients having to mess with + * configuration/initialization. + * + * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Marc Johnson (mjohnson at apache dot org) + */ + +public class POILogFactory +{ + private Hierarchy _creator; + + // map of POILogger instances, with classes as keys + private Map _loggers; + private static final String _fs = System.getProperty("file.separator"); + + /** + * construct a POILogFactory. + * + * @param logFile the name of the file that contains the + * properties governing the logs; should not be + * null or empty + * @param logPathProperty the name of the system property that + * defines the path of logFile; can not be + * null or empty + */ + + public POILogFactory(final String logFile, final String logPathProperty) + { + String logfile = logFile; + String logpath = System.getProperty(logPathProperty); + + if ((logpath != null) && (logpath.trim().length() != 0)) + { + logfile = logpath + _fs + logfile; + } + _creator = + new Hierarchy(new RootCategory(Category.getRoot().getPriority())); + try + { + new FileInputStream(logfile).close(); + new PropertyConfigurator().doConfigure(logfile, _creator); + } + catch (IOException e) + { + _creator.getRoot() + .addAppender(new ConsoleAppender(new SimpleLayout(), + ConsoleAppender.SYSTEM_OUT)); + _creator.disableDebug(); + } + _loggers = new HashMap(); + } + + /** + * Get a logger, based on a class name + * + * @param theclass the class whose name defines the log + * + * @return a POILogger for the specified class + */ + + public POILogger getLogger(final Class theclass) + { + POILogger logger = ( POILogger ) _loggers.get(theclass); + + if (logger == null) + { + logger = new POILogger(_creator.getInstance(theclass.getName())); + _loggers.put(theclass, 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 new file mode 100644 index 000000000..c1a0fca99 --- /dev/null +++ b/src/java/org/apache/poi/util/POILogger.java @@ -0,0 +1,731 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +import org.apache.log4j.Category; +import org.apache.log4j.Priority; + +import java.util.*; + +/** + * A logger class that strives to make it as easy as possible for + * developers to write log calls, while simultaneously making those + * calls as cheap as possible by performing lazy evaluation of the log + * message.

+ * + * @author Marc Johnson (mjohnson at apache dot org) + * @author Glen Stampoultzis (gstamp at iprimus dot com dot au) + */ + +public class POILogger +{ + private Category log = null; + public static final int DEBUG = Priority.DEBUG_INT; + public static final int INFO = Priority.INFO_INT; + public static final int WARN = Priority.WARN_INT; + public static final int ERROR = Priority.ERROR_INT; + public static final int FATAL = Priority.FATAL_INT; + + /** + * 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 Category log) + { + this.log = log; + } + + /** + * Log a message + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 The object to log. This is converted to a string. + */ + + public void log(final int logLevel, final Object obj1) + { + log.log(Priority.toPriority(logLevel), obj1); + } + + /** + * Log a message. Lazily appends Object parameters together. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 first object to place in the message + * @param obj2 second object to place in the message + */ + + public void log(final int logLevel, final Object obj1, final Object obj2) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + log.log(priority, new StringBuffer(32).append(obj1).append(obj2)); + } + } + + /** + * Log a message. Lazily appends Object parameters together. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 first Object to place in the message + * @param obj2 second Object to place in the message + * @param obj3 third Object to place in the message + */ + + public void log(final int logLevel, final Object obj1, final Object obj2, + final Object obj3) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + log.log(priority, + new StringBuffer(48).append(obj1).append(obj2) + .append(obj3)); + } + } + + /** + * Log a message. Lazily appends Object parameters together. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 first Object to place in the message + * @param obj2 second Object to place in the message + * @param obj3 third Object to place in the message + * @param obj4 fourth Object to place in the message + */ + + public void log(final int logLevel, final Object obj1, final Object obj2, + final Object obj3, final Object obj4) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + log.log(priority, + new StringBuffer(64).append(obj1).append(obj2) + .append(obj3).append(obj4)); + } + } + + /** + * Log a message. Lazily appends Object parameters together. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 first Object to place in the message + * @param obj2 second Object to place in the message + * @param obj3 third Object to place in the message + * @param obj4 fourth Object to place in the message + * @param obj5 fifth Object to place in the message + */ + + public void log(final int logLevel, final Object obj1, final Object obj2, + final Object obj3, final Object obj4, final Object obj5) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + log.log(priority, + new StringBuffer(80).append(obj1).append(obj2) + .append(obj3).append(obj4).append(obj5)); + } + } + + /** + * Log a message. Lazily appends Object parameters together. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 first Object to place in the message + * @param obj2 second Object to place in the message + * @param obj3 third Object to place in the message + * @param obj4 fourth Object to place in the message + * @param obj5 fifth Object to place in the message + * @param obj6 sixth Object to place in the message + */ + + public void log(final int logLevel, final Object obj1, final Object obj2, + final Object obj3, final Object obj4, final Object obj5, + final Object obj6) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + log.log(Priority.toPriority(logLevel), + new StringBuffer(96).append(obj1).append(obj2) + .append(obj3).append(obj4).append(obj5).append(obj6)); + } + } + + /** + * Log a message. Lazily appends Object parameters together. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 first Object to place in the message + * @param obj2 second Object to place in the message + * @param obj3 third Object to place in the message + * @param obj4 fourth Object to place in the message + * @param obj5 fifth Object to place in the message + * @param obj6 sixth Object to place in the message + * @param obj7 seventh Object to place in the message + */ + + public void log(final int logLevel, final Object obj1, final Object obj2, + final Object obj3, final Object obj4, final Object obj5, + final Object obj6, final Object obj7) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + log.log(priority, + new StringBuffer(112).append(obj1).append(obj2) + .append(obj3).append(obj4).append(obj5).append(obj6) + .append(obj7)); + } + } + + /** + * Log a message. Lazily appends Object parameters together. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 first Object to place in the message + * @param obj2 second Object to place in the message + * @param obj3 third Object to place in the message + * @param obj4 fourth Object to place in the message + * @param obj5 fifth Object to place in the message + * @param obj6 sixth Object to place in the message + * @param obj7 seventh Object to place in the message + * @param obj8 eighth Object to place in the message + */ + + public void log(final int logLevel, final Object obj1, final Object obj2, + final Object obj3, final Object obj4, final Object obj5, + final Object obj6, final Object obj7, final Object obj8) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + log.log(priority, + new StringBuffer(128).append(obj1).append(obj2) + .append(obj3).append(obj4).append(obj5).append(obj6) + .append(obj7).append(obj8)); + } + } + + /** + * Log a message + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 The object to log. This is converted to a string. + * @param exception An exception to be logged + */ + + public void log(final int logLevel, final Object obj1, + final Throwable exception) + { + log.log(Priority.toPriority(logLevel), obj1, exception); + } + + /** + * Log a message. Lazily appends Object parameters together. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 first Object to place in the message + * @param obj2 second Object to place in the message + * @param exception An exception to be logged + */ + + public void log(final int logLevel, final Object obj1, final Object obj2, + final Throwable exception) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + log.log(priority, new StringBuffer(32).append(obj1).append(obj2), + exception); + } + } + + /** + * Log a message. Lazily appends Object parameters together. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 first Object to place in the message + * @param obj2 second Object to place in the message + * @param obj3 third object to place in the message + * @param exception An error message to be logged + */ + + public void log(final int logLevel, final Object obj1, final Object obj2, + final Object obj3, final Throwable exception) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + log.log(priority, new StringBuffer(48).append(obj1).append(obj2) + .append(obj3), exception); + } + } + + /** + * Log a message. Lazily appends Object parameters together. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 first Object to place in the message + * @param obj2 second Object to place in the message + * @param obj3 third object to place in the message + * @param obj4 fourth object to place in the message + * @param exception An exception to be logged + */ + + public void log(final int logLevel, final Object obj1, final Object obj2, + final Object obj3, final Object obj4, + final Throwable exception) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + log.log(priority, new StringBuffer(64).append(obj1).append(obj2) + .append(obj3).append(obj4), exception); + } + } + + /** + * Log a message. Lazily appends Object parameters together. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 first Object to place in the message + * @param obj2 second Object to place in the message + * @param obj3 third object to place in the message + * @param obj4 fourth object to place in the message + * @param obj5 fifth object to place in the message + * @param exception An exception to be logged + */ + + public void log(final int logLevel, final Object obj1, final Object obj2, + final Object obj3, final Object obj4, final Object obj5, + final Throwable exception) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + log.log(priority, new StringBuffer(80).append(obj1).append(obj2) + .append(obj3).append(obj4).append(obj5), exception); + } + } + + /** + * Log a message. Lazily appends Object parameters together. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 first Object to place in the message + * @param obj2 second Object to place in the message + * @param obj3 third object to place in the message + * @param obj4 fourth object to place in the message + * @param obj5 fifth object to place in the message + * @param obj6 sixth object to place in the message + * @param exception An exception to be logged + */ + + public void log(final int logLevel, final Object obj1, final Object obj2, + final Object obj3, final Object obj4, final Object obj5, + final Object obj6, final Throwable exception) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + log.log(Priority.toPriority(logLevel), new StringBuffer(96) + .append(obj1).append(obj2).append(obj3).append(obj4) + .append(obj5).append(obj6), exception); + } + } + + /** + * Log a message. Lazily appends Object parameters together. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 first Object to place in the message + * @param obj2 second Object to place in the message + * @param obj3 third object to place in the message + * @param obj4 fourth object to place in the message + * @param obj5 fifth object to place in the message + * @param obj6 sixth object to place in the message + * @param obj7 seventh object to place in the message + * @param exception An exception to be logged + */ + + public void log(final int logLevel, final Object obj1, final Object obj2, + final Object obj3, final Object obj4, final Object obj5, + final Object obj6, final Object obj7, + final Throwable exception) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + log.log(priority, new StringBuffer(112).append(obj1).append(obj2) + .append(obj3).append(obj4).append(obj5).append(obj6) + .append(obj7), exception); + } + } + + /** + * Log a message. Lazily appends Object parameters together. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param obj1 first Object to place in the message + * @param obj2 second Object to place in the message + * @param obj3 third object to place in the message + * @param obj4 fourth object to place in the message + * @param obj5 fifth object to place in the message + * @param obj6 sixth object to place in the message + * @param obj7 seventh object to place in the message + * @param obj8 eighth object to place in the message + * @param exception An exception to be logged + */ + + public void log(final int logLevel, final Object obj1, final Object obj2, + final Object obj3, final Object obj4, final Object obj5, + final Object obj6, final Object obj7, final Object obj8, + final Throwable exception) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + log.log(priority, new StringBuffer(128).append(obj1).append(obj2) + .append(obj3).append(obj4).append(obj5).append(obj6) + .append(obj7).append(obj8), exception); + } + } + + /** + * Logs a formated message. The message itself may contain % + * characters as place holders. This routine will attempt to match + * the placeholder by looking at the type of parameter passed to + * obj1.

+ * + * If the parameter is an array, it traverses the array first and + * matches parameters sequentially against the array items. + * Otherwise the parameters after message are matched + * in order.

+ * + * If the place holder matches against a number it is printed as a + * whole number. This can be overridden by specifying a precision + * in the form %n.m where n is the padding for the whole part and + * m is the number of decimal places to display. n can be excluded + * if desired. n and m may not be more than 9.

+ * + * If the last parameter (after flattening) is a Throwable it is + * logged specially. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param message The message to log. + * @param obj1 The first object to match against. + */ + + public void logFormatted(final int logLevel, final String message, + final Object obj1) + { + commonLogFormatted(logLevel, message, new Object[] + { + obj1 + }); + } + + /** + * Logs a formated message. The message itself may contain % + * characters as place holders. This routine will attempt to match + * the placeholder by looking at the type of parameter passed to + * obj1.

+ * + * If the parameter is an array, it traverses the array first and + * matches parameters sequentially against the array items. + * Otherwise the parameters after message are matched + * in order.

+ * + * If the place holder matches against a number it is printed as a + * whole number. This can be overridden by specifying a precision + * in the form %n.m where n is the padding for the whole part and + * m is the number of decimal places to display. n can be excluded + * if desired. n and m may not be more than 9.

+ * + * If the last parameter (after flattening) is a Throwable it is + * logged specially. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param message The message to log. + * @param obj1 The first object to match against. + * @param obj2 The second object to match against. + */ + + public void logFormatted(final int logLevel, final String message, + final Object obj1, final Object obj2) + { + commonLogFormatted(logLevel, message, new Object[] + { + obj1, obj2 + }); + } + + /** + * Logs a formated message. The message itself may contain % + * characters as place holders. This routine will attempt to match + * the placeholder by looking at the type of parameter passed to + * obj1.

+ * + * If the parameter is an array, it traverses the array first and + * matches parameters sequentially against the array items. + * Otherwise the parameters after message are matched + * in order.

+ * + * If the place holder matches against a number it is printed as a + * whole number. This can be overridden by specifying a precision + * in the form %n.m where n is the padding for the whole part and + * m is the number of decimal places to display. n can be excluded + * if desired. n and m may not be more than 9.

+ * + * If the last parameter (after flattening) is a Throwable it is + * logged specially. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param message The message to log. + * @param obj1 The first object to match against. + * @param obj2 The second object to match against. + * @param obj3 The third object to match against. + */ + + public void logFormatted(final int logLevel, final String message, + final Object obj1, final Object obj2, + final Object obj3) + { + commonLogFormatted(logLevel, message, new Object[] + { + obj1, obj2, obj3 + }); + } + + /** + * Logs a formated message. The message itself may contain % + * characters as place holders. This routine will attempt to match + * the placeholder by looking at the type of parameter passed to + * obj1.

+ * + * If the parameter is an array, it traverses the array first and + * matches parameters sequentially against the array items. + * Otherwise the parameters after message are matched + * in order.

+ * + * If the place holder matches against a number it is printed as a + * whole number. This can be overridden by specifying a precision + * in the form %n.m where n is the padding for the whole part and + * m is the number of decimal places to display. n can be excluded + * if desired. n and m may not be more than 9.

+ * + * If the last parameter (after flattening) is a Throwable it is + * logged specially. + * + * @param logLevel One of DEBUG, INFO, WARN, ERROR, FATAL + * @param message The message to log. + * @param obj1 The first object to match against. + * @param obj2 The second object to match against. + * @param obj3 The third object to match against. + * @param obj4 The forth object to match against. + */ + + public void logFormatted(final int logLevel, final String message, + final Object obj1, final Object obj2, + final Object obj3, final Object obj4) + { + commonLogFormatted(logLevel, message, new Object[] + { + obj1, obj2, obj3, obj4 + }); + } + + private void commonLogFormatted(final int logLevel, final String message, + final Object [] unflatParams) + { + Priority priority = Priority.toPriority(logLevel); + + if (log.isEnabledFor(priority)) + { + Object[] params = flattenArrays(unflatParams); + + if (params[ params.length - 1 ] instanceof Throwable) + { + log(logLevel, StringUtil.format(message, params), + ( Throwable ) params[ params.length - 1 ]); + } + else + { + log(logLevel, StringUtil.format(message, params)); + } + } + } + + /** + * Flattens any contained objects. Only tranverses one level deep. + */ + + private Object [] flattenArrays(final Object [] objects) + { + List results = new ArrayList(); + + for (int i = 0; i < objects.length; i++) + { + results.addAll(objectToObjectArray(objects[ i ])); + } + return ( Object [] ) results.toArray(new Object[ results.size() ]); + } + + private List objectToObjectArray(Object object) + { + List results = new ArrayList(); + + if (object instanceof byte []) + { + byte[] array = ( byte [] ) object; + + for (int j = 0; j < array.length; j++) + { + results.add(new Byte(array[ j ])); + } + } + if (object instanceof char []) + { + char[] array = ( char [] ) object; + + for (int j = 0; j < array.length; j++) + { + results.add(new Character(array[ j ])); + } + } + else if (object instanceof short []) + { + short[] array = ( short [] ) object; + + for (int j = 0; j < array.length; j++) + { + results.add(new Short(array[ j ])); + } + } + else if (object instanceof int []) + { + int[] array = ( int [] ) object; + + for (int j = 0; j < array.length; j++) + { + results.add(new Integer(array[ j ])); + } + } + else if (object instanceof long []) + { + long[] array = ( long [] ) object; + + for (int j = 0; j < array.length; j++) + { + results.add(new Long(array[ j ])); + } + } + else if (object instanceof float []) + { + float[] array = ( float [] ) object; + + for (int j = 0; j < array.length; j++) + { + results.add(new Float(array[ j ])); + } + } + else if (object instanceof double []) + { + double[] array = ( double [] ) object; + + for (int j = 0; j < array.length; j++) + { + results.add(new Double(array[ j ])); + } + } + else if (object instanceof Object []) + { + Object[] array = ( Object [] ) object; + + for (int j = 0; j < array.length; j++) + { + results.add(array[ j ]); + } + } + else + { + results.add(object); + } + return results; + } +} // end package scope class POILogger + diff --git a/src/java/org/apache/poi/util/ShortField.java b/src/java/org/apache/poi/util/ShortField.java new file mode 100644 index 000000000..dc4d59c1f --- /dev/null +++ b/src/java/org/apache/poi/util/ShortField.java @@ -0,0 +1,253 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +import org.apache.poi.util.LittleEndian.BufferUnderrunException; + +import java.io.*; + +/** + * representation of a short (16-bit) field at a fixed location within + * a byte array + * + * @author Marc Johnson (mjohnson at apache dot org + */ + +public class ShortField + implements FixedField +{ + private short _value; + private final int _offset; + + /** + * construct the ShortField with its offset into its containing + * byte array + * + * @param offset of the field within its byte array + * + * @exception ArrayIndexOutOfBoundsException if offset is negative + */ + + public ShortField(final int offset) + throws ArrayIndexOutOfBoundsException + { + if (offset < 0) + { + throw new ArrayIndexOutOfBoundsException("Illegal offset: " + + offset); + } + _offset = offset; + } + + /** + * construct the ShortField with its offset into its containing + * byte array and initialize its value + * + * @param offset of the field within its byte array + * @param value the initial value + * + * @exception ArrayIndexOutOfBoundsException if offset is negative + */ + + public ShortField(final int offset, final short value) + throws ArrayIndexOutOfBoundsException + { + this(offset); + set(value); + } + + /** + * Construct the ShortField with its offset into its containing + * byte array and initialize its value from its byte array + * + * @param offset of the field within its byte array + * @param data the byte array to read the value from + * + * @exception ArrayIndexOutOfBoundsException if the offset is not + * within the range of 0..(data.length - 1) + */ + + public ShortField(final int offset, final byte [] data) + throws ArrayIndexOutOfBoundsException + { + this(offset); + readFromBytes(data); + } + + /** + * construct the ShortField with its offset into its containing + * byte array, initialize its value, and write its value to its + * byte array + * + * @param offset of the field within its byte array + * @param value the initial value + * @param data the byte array to write the value to + * + * @exception ArrayIndexOutOfBoundsException if offset is negative + */ + + public ShortField(final int offset, final short value, final byte [] data) + throws ArrayIndexOutOfBoundsException + { + this(offset); + set(value, data); + } + + /** + * get the ShortField's current value + * + * @return current value + */ + + public short get() + { + return _value; + } + + /** + * set the ShortField's current value + * + * @param value to be set + */ + + public void set(final short value) + { + _value = value; + } + + /** + * set the ShortField's current value and write it to a byte array + * + * @param value to be set + * @param data the byte array to write the value to + * + * @exception ArrayIndexOutOfBoundsException if the offset is out + * of range + */ + + public void set(final short value, final byte [] data) + throws ArrayIndexOutOfBoundsException + { + _value = value; + writeToBytes(data); + } + + /* ********** START implementation of FixedField ********** */ + + /** + * set the value from its offset into an array of bytes + * + * @param data the byte array from which the value is to be read + * + * @exception ArrayIndexOutOfBoundsException if the offset is out + * of range + */ + + public void readFromBytes(final byte [] data) + throws ArrayIndexOutOfBoundsException + { + _value = LittleEndian.getShort(data, _offset); + } + + /** + * set the value from an InputStream + * + * @param stream the InputStream from which the value is to be + * read + * + * @exception BufferUnderrunException if there is not enough data + * available from the InputStream + * @exception IOException if an IOException is thrown from reading + * the InputStream + */ + + public void readFromStream(final InputStream stream) + throws IOException, BufferUnderrunException + { + _value = LittleEndian.readShort(stream); + } + + /** + * write the value out to an array of bytes at the appropriate + * offset + * + * @param data the array of bytes to which the value is to be + * written + * + * @exception ArrayIndexOutOfBoundsException if the offset is out + * of range + */ + + public void writeToBytes(final byte [] data) + throws ArrayIndexOutOfBoundsException + { + LittleEndian.putShort(data, _offset, _value); + } + + /** + * return the value as a String + * + * @return the value as a String + */ + + public String toString() + { + return String.valueOf(_value); + } + + /* ********** END implementation of FixedField ********** */ +} // end public class ShortField + diff --git a/src/java/org/apache/poi/util/ShortList.java b/src/java/org/apache/poi/util/ShortList.java new file mode 100644 index 000000000..ec786d388 --- /dev/null +++ b/src/java/org/apache/poi/util/ShortList.java @@ -0,0 +1,678 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +import java.util.*; + +/** + * A List of short's; as full an implementation of the java.util.List + * interface as possible, with an eye toward minimal creation of + * objects + * + * the mimicry of List is as follows: + *

    + *
  • if possible, operations designated 'optional' in the List + * interface are attempted + *
  • wherever the List interface refers to an Object, substitute + * short + *
  • wherever the List interface refers to a Collection or List, + * substitute ShortList + *
+ * + * the mimicry is not perfect, however: + *
    + *
  • operations involving Iterators or ListIterators are not + * supported + *
  • remove(Object) becomes removeValue to distinguish it from + * remove(short index) + *
  • subList is not supported + *
+ * + * @author Marc Johnson + */ + +public class ShortList +{ + private short[] _array; + private int _limit; + private static final int _default_size = 128; + + /** + * create an ShortList of default size + */ + + public ShortList() + { + this(_default_size); + } + + /** + * create a copy of an existing ShortList + * + * @param list the existing ShortList + */ + + public ShortList(final ShortList list) + { + this(list._array.length); + System.arraycopy(list._array, 0, _array, 0, _array.length); + _limit = list._limit; + } + + /** + * create an ShortList with a predefined initial size + * + * @param initialCapacity the size for the internal array + */ + + public ShortList(final int initialCapacity) + { + _array = new short[ initialCapacity ]; + _limit = 0; + } + + /** + * add the specfied value at the specified index + * + * @param index the index where the new value is to be added + * @param value the new value + * + * @exception IndexOutOfBoundsException if the index is out of + * range (index < 0 || index > size()). + */ + + public void add(final int index, final short value) + { + if (index > _limit) + { + throw new IndexOutOfBoundsException(); + } + else if (index == _limit) + { + add(value); + } + else + { + + // index < limit -- insert into the middle + if (_limit == _array.length) + { + growArray(_limit * 2); + } + System.arraycopy(_array, index, _array, index + 1, + _limit - index); + _array[ index ] = value; + _limit++; + } + } + + /** + * Appends the specified element to the end of this list + * + * @param value element to be appended to this list. + * + * @return true (as per the general contract of the Collection.add + * method). + */ + + public boolean add(final short value) + { + if (_limit == _array.length) + { + growArray(_limit * 2); + } + _array[ _limit++ ] = value; + return true; + } + + /** + * Appends all of the elements in the specified collection to the + * end of this list, in the order that they are returned by the + * specified collection's iterator. The behavior of this + * operation is unspecified if the specified collection is + * modified while the operation is in progress. (Note that this + * will occur if the specified collection is this list, and it's + * nonempty.) + * + * @param c collection whose elements are to be added to this + * list. + * + * @return true if this list changed as a result of the call. + */ + + public boolean addAll(final ShortList c) + { + if (c._limit != 0) + { + if ((_limit + c._limit) > _array.length) + { + growArray(_limit + c._limit); + } + System.arraycopy(c._array, 0, _array, _limit, c._limit); + _limit += c._limit; + } + return true; + } + + /** + * Inserts all of the elements in the specified collection into + * this list at the specified position. Shifts the element + * currently at that position (if any) and any subsequent elements + * to the right (increases their indices). The new elements will + * appear in this list in the order that they are returned by the + * specified collection's iterator. The behavior of this + * operation is unspecified if the specified collection is + * modified while the operation is in progress. (Note that this + * will occur if the specified collection is this list, and it's + * nonempty.) + * + * @param index index at which to insert first element from the + * specified collection. + * @param c elements to be inserted into this list. + * + * @return true if this list changed as a result of the call. + * + * @exception IndexOutOfBoundsException if the index is out of + * range (index < 0 || index > size()) + */ + + public boolean addAll(final int index, final ShortList c) + { + if (index > _limit) + { + throw new IndexOutOfBoundsException(); + } + if (c._limit != 0) + { + if ((_limit + c._limit) > _array.length) + { + growArray(_limit + c._limit); + } + + // make a hole + System.arraycopy(_array, index, _array, index + c._limit, + _limit - index); + + // fill it in + System.arraycopy(c._array, 0, _array, index, c._limit); + _limit += c._limit; + } + return true; + } + + /** + * Removes all of the elements from this list. This list will be + * empty after this call returns (unless it throws an exception). + */ + + public void clear() + { + _limit = 0; + } + + /** + * Returns true if this list contains the specified element. More + * formally, returns true if and only if this list contains at + * least one element e such that o == e + * + * @param o element whose presence in this list is to be tested. + * + * @return true if this list contains the specified element. + */ + + public boolean contains(final short o) + { + boolean rval = false; + + for (int j = 0; !rval && (j < _limit); j++) + { + if (_array[ j ] == o) + { + rval = true; + } + } + return rval; + } + + /** + * Returns true if this list contains all of the elements of the + * specified collection. + * + * @param c collection to be checked for containment in this list. + * + * @return true if this list contains all of the elements of the + * specified collection. + */ + + public boolean containsAll(final ShortList c) + { + boolean rval = true; + + if (this != c) + { + for (int j = 0; rval && (j < c._limit); j++) + { + if (!contains(c._array[ j ])) + { + rval = false; + } + } + } + return rval; + } + + /** + * Compares the specified object with this list for equality. + * Returns true if and only if the specified object is also a + * list, both lists have the same size, and all corresponding + * pairs of elements in the two lists are equal. (Two elements e1 + * and e2 are equal if e1 == e2.) In other words, two lists are + * defined to be equal if they contain the same elements in the + * same order. This definition ensures that the equals method + * works properly across different implementations of the List + * interface. + * + * @param o the object to be compared for equality with this list. + * + * @return true if the specified object is equal to this list. + */ + + public boolean equals(final Object o) + { + boolean rval = this == o; + + if (!rval && (o != null) && (o.getClass() == this.getClass())) + { + ShortList other = ( ShortList ) o; + + if (other._limit == _limit) + { + + // assume match + rval = true; + for (int j = 0; rval && (j < _limit); j++) + { + rval = _array[ j ] == other._array[ j ]; + } + } + } + return rval; + } + + /** + * Returns the element at the specified position in this list. + * + * @param index index of element to return. + * + * @return the element at the specified position in this list. + * + * @exception IndexOutOfBoundsException if the index is out of + * range (index < 0 || index >= size()). + */ + + public short get(final int index) + { + if (index >= _limit) + { + throw new IndexOutOfBoundsException(); + } + return _array[ index ]; + } + + /** + * Returns the hash code value for this list. The hash code of a + * list is defined to be the result of the following calculation: + * + * + * hashCode = 1; + * Iterator i = list.iterator(); + * while (i.hasNext()) { + * Object obj = i.next(); + * hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode()); + * } + * + * + * This ensures that list1.equals(list2) implies that + * list1.hashCode()==list2.hashCode() for any two lists, list1 and + * list2, as required by the general contract of Object.hashCode. + * + * @return the hash code value for this list. + */ + + public int hashCode() + { + int hash = 0; + + for (int j = 0; j < _limit; j++) + { + hash = (31 * hash) + _array[ j ]; + } + return hash; + } + + /** + * Returns the index in this list of the first occurrence of the + * specified element, or -1 if this list does not contain this + * element. More formally, returns the lowest index i such that + * (o == get(i)), or -1 if there is no such index. + * + * @param o element to search for. + * + * @return the index in this list of the first occurrence of the + * specified element, or -1 if this list does not contain + * this element. + */ + + public int indexOf(final short o) + { + int rval = 0; + + for (; rval < _limit; rval++) + { + if (o == _array[ rval ]) + { + break; + } + } + if (rval == _limit) + { + rval = -1; // didn't find it + } + return rval; + } + + /** + * Returns true if this list contains no elements. + * + * @return true if this list contains no elements. + */ + + public boolean isEmpty() + { + return _limit == 0; + } + + /** + * Returns the index in this list of the last occurrence of the + * specified element, or -1 if this list does not contain this + * element. More formally, returns the highest index i such that + * (o == get(i)), or -1 if there is no such index. + * + * @param o element to search for. + * + * @return the index in this list of the last occurrence of the + * specified element, or -1 if this list does not contain + * this element. + */ + + public int lastIndexOf(final short o) + { + int rval = _limit - 1; + + for (; rval >= 0; rval--) + { + if (o == _array[ rval ]) + { + break; + } + } + return rval; + } + + /** + * Removes the element at the specified position in this list. + * Shifts any subsequent elements to the left (subtracts one from + * their indices). Returns the element that was removed from the + * list. + * + * @param index the index of the element to removed. + * + * @return the element previously at the specified position. + * + * @exception IndexOutOfBoundsException if the index is out of + * range (index < 0 || index >= size()). + */ + + public short remove(final int index) + { + if (index >= _limit) + { + throw new IndexOutOfBoundsException(); + } + short rval = _array[ index ]; + + System.arraycopy(_array, index + 1, _array, index, _limit - index); + _limit--; + return rval; + } + + /** + * Removes the first occurrence in this list of the specified + * element (optional operation). If this list does not contain + * the element, it is unchanged. More formally, removes the + * element with the lowest index i such that (o.equals(get(i))) + * (if such an element exists). + * + * @param o element to be removed from this list, if present. + * + * @return true if this list contained the specified element. + */ + + public boolean removeValue(final short o) + { + boolean rval = false; + + for (int j = 0; !rval && (j < _limit); j++) + { + if (o == _array[ j ]) + { + System.arraycopy(_array, j + 1, _array, j, _limit - j); + _limit--; + rval = true; + } + } + return rval; + } + + /** + * Removes from this list all the elements that are contained in + * the specified collection + * + * @param c collection that defines which elements will be removed + * from this list. + * + * @return true if this list changed as a result of the call. + */ + + public boolean removeAll(final ShortList c) + { + boolean rval = false; + + for (int j = 0; j < c._limit; j++) + { + if (removeValue(c._array[ j ])) + { + rval = true; + } + } + return rval; + } + + /** + * Retains only the elements in this list that are contained in + * the specified collection. In other words, removes from this + * list all the elements that are not contained in the specified + * collection. + * + * @param c collection that defines which elements this set will + * retain. + * + * @return true if this list changed as a result of the call. + */ + + public boolean retainAll(final ShortList c) + { + boolean rval = false; + + for (int j = 0; j < _limit; ) + { + if (!c.contains(_array[ j ])) + { + remove(j); + rval = true; + } + else + { + j++; + } + } + return rval; + } + + /** + * Replaces the element at the specified position in this list + * with the specified element + * + * @param index index of element to replace. + * @param element element to be stored at the specified position. + * + * @return the element previously at the specified position. + * + * @exception IndexOutOfBoundsException if the index is out of + * range (index < 0 || index >= size()). + */ + + public short set(final int index, final short element) + { + if (index >= _limit) + { + throw new IndexOutOfBoundsException(); + } + short rval = _array[ index ]; + + _array[ index ] = element; + return rval; + } + + /** + * Returns the number of elements in this list. If this list + * contains more than Integer.MAX_VALUE elements, returns + * Integer.MAX_VALUE. + * + * @return the number of elements in this ShortList + */ + + public int size() + { + return _limit; + } + + /** + * Returns an array containing all of the elements in this list in + * proper sequence. Obeys the general contract of the + * Collection.toArray method. + * + * @return an array containing all of the elements in this list in + * proper sequence. + */ + + public short [] toArray() + { + short[] rval = new short[ _limit ]; + + System.arraycopy(_array, 0, rval, 0, _limit); + return rval; + } + + /** + * Returns an array containing all of the elements in this list in + * proper sequence. Obeys the general contract of the + * Collection.toArray(Object[]) method. + * + * @param a the array into which the elements of this list are to + * be stored, if it is big enough; otherwise, a new array + * is allocated for this purpose. + * + * @return an array containing the elements of this list. + */ + + public short [] toArray(final short [] a) + { + short[] rval; + + if (a.length == _limit) + { + System.arraycopy(_array, 0, a, 0, _limit); + rval = a; + } + else + { + rval = toArray(); + } + return rval; + } + + private void growArray(final int new_size) + { + int size = (new_size == _array.length) ? new_size + 1 + : new_size; + short[] new_array = new short[ size ]; + + System.arraycopy(_array, 0, new_array, 0, _limit); + _array = new_array; + } +} // end public class ShortList + diff --git a/src/java/org/apache/poi/util/StringUtil.java b/src/java/org/apache/poi/util/StringUtil.java new file mode 100644 index 000000000..e3bd09512 --- /dev/null +++ b/src/java/org/apache/poi/util/StringUtil.java @@ -0,0 +1,261 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.util; + +import java.io.UnsupportedEncodingException; + +import java.text.NumberFormat; +import java.text.FieldPosition; + +/** + * Title: String Utility + * Description: Collection of string handling utilities + * @author Andrew C. Oliver + * @version 1.0 + */ + +public class StringUtil +{ + private StringUtil() + { + } + + /** + * given a byte array of 16-bit unicode characters, compress to + * 8-bit and return a string + * + * @param string the byte array to be converted + * @param offset the initial offset into the byte array. it is + * assumed that string[ offset ] and string[ offset + * + 1 ] contain the first 16-bit unicode character + * @len the length of the final string + * + * @param len + * @return the converted string + * + * @exception ArrayIndexOutOfBoundsException if offset is out of + * bounds for the byte array (i.e., is negative or is + * greater than or equal to string.length) + * @exception IllegalArgumentException if len is too large (i.e., + * there is not enough data in string to create a + * String of that length) + */ + + public static String getFromUnicode(final byte [] string, + final int offset, final int len) + throws ArrayIndexOutOfBoundsException, IllegalArgumentException + { + if ((offset < 0) || (offset >= string.length)) + { + throw new ArrayIndexOutOfBoundsException("Illegal offset"); + } + if ((len < 0) || (((string.length - offset) / 2) < len)) + { + throw new IllegalArgumentException("Illegal length"); + } + byte[] bstring = new byte[ len ]; + int index = offset + 1; // start with low bits. + + for (int k = 0; k < len; k++) + { + bstring[ k ] = string[ index ]; + index += 2; + } + return new String(bstring); + } + + /** + * given a byte array of 16-bit unicode characters, compress to + * 8-bit and return a string + * + * @param string the byte array to be converted + * + * @return the converted string + */ + + public static String getFromUnicode(final byte [] string) + { + return getFromUnicode(string, 0, string.length / 2); + } + + /** + * write compressed unicode + * + * @param input the String containing the data to be written + * @param output the byte array to which the data is to be written + * @param offset an offset into the byte arrat at which the data + * is start when written + */ + + public static void putCompressedUnicode(final String input, + final byte [] output, + final int offset) + { + int strlen = input.length(); + + for (int k = 0; k < strlen; k++) + { + output[ offset + k ] = ( byte ) input.charAt(k); + } + } + + /** + * Write uncompressed unicode + * + * @param input the String containing the unicode data to be + * written + * @param output the byte array to hold the uncompressed unicode + * @param offset the offset to start writing into the byte array + */ + + public static void putUncompressedUnicode(final String input, + final byte [] output, + final int offset) + { + int strlen = input.length(); + + for (int k = 0; k < strlen; k++) + { + char c = input.charAt(k); + + output[ offset + (2 * k) ] = ( byte ) c; + output[ offset + (2 * k) + 1 ] = ( byte ) (c >> 8); + } + } + + public static String format(String message, Object [] params) + { + int currentParamNumber = 0; + StringBuffer formattedMessage = new StringBuffer(); + + for (int i = 0; i < message.length(); i++) + { + if (message.charAt(i) == '%') + { + if (currentParamNumber >= params.length) + { + formattedMessage.append("?missing data?"); + } + else if ((params[ currentParamNumber ] instanceof Number) + && (i + 1 < message.length())) + { + i += matchOptionalFormatting( + ( Number ) params[ currentParamNumber++ ], + message.substring(i + 1), formattedMessage); + } + else + { + formattedMessage + .append(params[ currentParamNumber++ ].toString()); + } + } + else + { + if ((message.charAt(i) == '\\') && (i + 1 < message.length()) + && (message.charAt(i + 1) == '%')) + { + formattedMessage.append('%'); + i++; + } + else + { + formattedMessage.append(message.charAt(i)); + } + } + } + return formattedMessage.toString(); + } + + private static int matchOptionalFormatting(Number number, + String formatting, + StringBuffer outputTo) + { + NumberFormat numberFormat = NumberFormat.getInstance(); + + if ((0 < formatting.length()) + && Character.isDigit(formatting.charAt(0))) + { + numberFormat + .setMinimumIntegerDigits(Integer + .parseInt(formatting.charAt(0) + "")); + if ((2 < formatting.length()) && (formatting.charAt(1) == '.') + && Character.isDigit(formatting.charAt(2))) + { + numberFormat + .setMaximumFractionDigits(Integer + .parseInt(formatting.charAt(2) + "")); + numberFormat.format(number, outputTo, new FieldPosition(0)); + return 3; + } + numberFormat.format(number, outputTo, new FieldPosition(0)); + return 1; + } + else if ((0 < formatting.length()) && (formatting.charAt(0) == '.')) + { + if ((1 < formatting.length()) + && Character.isDigit(formatting.charAt(1))) + { + numberFormat + .setMaximumFractionDigits(Integer + .parseInt(formatting.charAt(1) + "")); + numberFormat.format(number, outputTo, new FieldPosition(0)); + return 2; + } + } + numberFormat.format(number, outputTo, new FieldPosition(0)); + return 1; + } +} diff --git a/src/models/BlockClassDiagram.pgml b/src/models/BlockClassDiagram.pgml new file mode 100755 index 000000000..72dd22a41 --- /dev/null +++ b/src/models/BlockClassDiagram.pgml @@ -0,0 +1,603 @@ + + + + + + + + + BigBlock + + #BIG_BLOCK_SIZE : int = 512 + +writeData(in stream:OutputStream) +#doWriteData(in stream:OutputStream, in data[]:byte) + + + + + + + HeaderBlock + + -_bat_count : IntegerField +-_property_start : IntegerField +-_sbat_start : IntegerField = -2 +-_xbat_start : IntegerField = -2 +-_xbat_count : IntegerField = 0 +-_data[ 512 ] : byte + +setBATBlocks(in blockCount:int, in startBlock:int) : BATBlock ++setPropertyStart(in startBlock:int) ++setXBATStart(in startBlock:int) ++Header() ++calculateXBATStorageRequirements(in blockCount:int) : int + + + + + + + PropertyBlock + + -_properties[ 4 ] : Property + +createPropertyBlockArray(in properties:List) : BlockWritable + + + + + + + BATBlock + + -_fields[ 128 ] : IntegerField +-_data[ 512 ] : byte + +createBATBlocks(in entries[]:int) : BATBlock ++calculateStorageRequirements(in entryCount:int) : int + + + + + + + DocumentBlock + + -_data[ 512 ] : byte +-_bytes_read : int + +DocumentBlock(in stream:InputStream) ++size() : int ++partiallyRead() : boolean + + + + + + + <<Interface>> + BlockWritable + +writeBlocks(in stream:OutputStream) + + + + sourcePortFig="Fig1.0" + destPortFig="Fig0.0" + sourceFigNode="Fig1" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig2.0" + destPortFig="Fig0.0" + sourceFigNode="Fig2" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig3.0" + destPortFig="Fig0.0" + sourceFigNode="Fig3" + destFigNode="Fig0" + + + + + + + + + + + + sourcePortFig="Fig4.0" + destPortFig="Fig0.0" + sourceFigNode="Fig4" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig5.0" + sourceFigNode="Fig0" + destFigNode="Fig5" + + + + + + + + + diff --git a/src/models/HSSFOperationalUseCases.pgml b/src/models/HSSFOperationalUseCases.pgml new file mode 100755 index 000000000..3706a32e0 --- /dev/null +++ b/src/models/HSSFOperationalUseCases.pgml @@ -0,0 +1,712 @@ + + + + + + + + + + + + + + + + + + + + + + + + + ClientApps + + + + + + + create HSSF File + + + + + + + write Workbook Entry + + + + + + + write sheet entry + + + + + + + new MUseCase + + + + + + + new MUseCase + + + + + + + new MUseCase + + + + + + + new MUseCase + + + + + + + new MUseCase + + + + + + + new MUseCase + + + + sourcePortFig="Fig0.0" + destPortFig="Fig1.0" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig1.0" + destPortFig="Fig2.0" + sourceFigNode="Fig1" + destFigNode="Fig2" + + + + + + + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig3.0" + sourceFigNode="Fig0" + destFigNode="Fig3" + + + + + + + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig4.0" + sourceFigNode="Fig0" + destFigNode="Fig4" + + + + + + + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig5.0" + sourceFigNode="Fig0" + destFigNode="Fig5" + + + + + + + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig6.0" + sourceFigNode="Fig0" + destFigNode="Fig6" + + + + + + + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig7.0" + sourceFigNode="Fig0" + destFigNode="Fig7" + + + + + + + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig9.0" + sourceFigNode="Fig0" + destFigNode="Fig9" + + + + + + + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig8.0" + sourceFigNode="Fig0" + destFigNode="Fig8" + + + + + + + + + diff --git a/src/models/HSSFSerializerClassDiagram.pgml b/src/models/HSSFSerializerClassDiagram.pgml new file mode 100755 index 000000000..44ea48875 --- /dev/null +++ b/src/models/HSSFSerializerClassDiagram.pgml @@ -0,0 +1,651 @@ + + + + + + + + + POIFSSerializer + + -_output_stream : OutputStream = null +-_locator : Locator = null +-_open_elements : Stack = new Stack() +-_filesystem : Filesystem = new Filesystem() + +startPrefixMapping(in ignoredPrefix:String, in ignoredUri:String) ++endPrefixMapping(in ignoredPrefix:String) ++processingInstruction(in ignoredTarget:String, in ignoredData:String) ++skippedEntity(in ignoredName:String) ++startDTD(in ignoredName:String, in ignoredPublicId:String, in ignoredSystemId:String) ++endDTD() ++startEntity(in ignoredName:String) ++endEntity(in ignoredName:String) ++startCDATA() ++endCDATA() ++comment(in ignoredCh[]:char, in ignoredStart:int, in ignoredLength:int) ++shouldSetContentLength() : boolean ++setOutputStream(in out:OutputStream) ++setDocumentLocator(in locator:Locator) ++startDocument() ++endDocument() ++startElement(in namespaceURI:String, in localName:String, in qName:String, in atts:Attributes) ++endElement(in namespaceURI:String, in localName:String, in qName:String) ++characters(in ch[]:char, in start:int, in length:int) ++ignorableWhitespace(in ch[]:char, in start:int, in length:int) +#getElementProcessorFactory() : ElementProcessorFactory +#doLocalPreEndDocument() +#doLocalPostEndDocument() +#getFilesystem() : Filesystem +#SAXExceptionFactory(in message:String, in e:Exception) : SAXException +#SAXExceptionFactory(in message:String) : SAXException + + + + + + + Attribute + + -_name : String +-_value : String + +getName() : String ++getValue() : String ++getValueAsInt() : int ++getValueAsShort() : short ++getValueAsLong() : long ++getValueAsBoolean() : boolean ++Attribute(in name:String, in value:String) + + + + + + + <<Interface>> + ElementProcessor + +initialize(in attributes[]:Attribute, in parent:ElementProcessor, in filesystem:Filesystem) ++acceptCharacters(in data[]:char) ++acceptWhitespaceCharacters(in data[]:char) ++endProcessing() + + + + + + + ElementProcessorFactory + + -_element_processor_map : Map + +createElementProcessor(in name:String) : ElementProcessor +#addElementProcessorProgenitor(in name:String, in progenitor:Object) +#lookupElementProcessorProgenitor(in name:String) : Object +#doCreateElementProcessor(in progenitor:Object) : ElementProcessor +#constructElementProcessor(in progenitor:Constructor) : ElementProcessor +#createNewElementProcessorInstance(in progenitor:Class) : ElementProcessor + + + + + + + HSSFSerializer + + -_element_processor_factory : HSSFElementProcessorFactory + +getMimeType() : String + + + + + + + HSSFElementProcessorFactory + + + + + + + + + + ElementProcessorFactory.CannotCreateElementProcessorException + + + + + + + sourcePortFig="Fig4.0" + destPortFig="Fig0.0" + sourceFigNode="Fig4" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig5.0" + destPortFig="Fig3.0" + sourceFigNode="Fig5" + destFigNode="Fig3" + + + + + + + + + + + sourcePortFig="Fig4.0" + destPortFig="Fig5.0" + sourceFigNode="Fig4" + destFigNode="Fig5" + + + + + + + + + diff --git a/src/models/HSSFSerializerUseCases.pgml b/src/models/HSSFSerializerUseCases.pgml new file mode 100755 index 000000000..fc5c267d1 --- /dev/null +++ b/src/models/HSSFSerializerUseCases.pgml @@ -0,0 +1,1031 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Cocoon + + + + + + + Sends Sax Events + + + + + + + Sends an Ignored Event + + + + + + + Sends and Interrogative Event + + + + + + + Sends Setup Event + + + + + + + Sends Start Document Event + + + + + + + Sends End Document Event + + + + + + + Sends Start Element Event + + + + + + + Sends End Element Event + + + + + + + Sends Raw Data Event + + + + sourcePortFig="Fig9.0" + destPortFig="Fig1.0" + sourceFigNode="Fig9" + destFigNode="Fig1" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig7.0" + destPortFig="Fig1.0" + sourceFigNode="Fig7" + destFigNode="Fig1" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig8.0" + destPortFig="Fig1.0" + sourceFigNode="Fig8" + destFigNode="Fig1" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig6.0" + destPortFig="Fig1.0" + sourceFigNode="Fig6" + destFigNode="Fig1" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig5.0" + destPortFig="Fig1.0" + sourceFigNode="Fig5" + destFigNode="Fig1" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig4.0" + destPortFig="Fig1.0" + sourceFigNode="Fig4" + destFigNode="Fig1" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig3.0" + destPortFig="Fig1.0" + sourceFigNode="Fig3" + destFigNode="Fig1" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig2.0" + destPortFig="Fig1.0" + sourceFigNode="Fig2" + destFigNode="Fig1" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig1.0" + destPortFig="Fig0.0" + sourceFigNode="Fig1" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig3.0" + destPortFig="Fig0.0" + sourceFigNode="Fig3" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig7.0" + destPortFig="Fig0.0" + sourceFigNode="Fig7" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig5.0" + destPortFig="Fig0.0" + sourceFigNode="Fig5" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig6.0" + destPortFig="Fig0.0" + sourceFigNode="Fig6" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig8.0" + destPortFig="Fig0.0" + sourceFigNode="Fig8" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig2.0" + destPortFig="Fig0.0" + sourceFigNode="Fig2" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig9.0" + destPortFig="Fig0.0" + sourceFigNode="Fig9" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig4.0" + destPortFig="Fig0.0" + sourceFigNode="Fig4" + destFigNode="Fig0" + + + + + + + + + diff --git a/src/models/HSSFUseCases.pgml b/src/models/HSSFUseCases.pgml new file mode 100755 index 000000000..db90c09b0 --- /dev/null +++ b/src/models/HSSFUseCases.pgml @@ -0,0 +1,707 @@ + + + + + + + + + + + + + + + + + + + + + + + + + ClientApps + + + + + + + create HSSF File + + + + + + + read existing HSSF File + + + + + + + write HSSF File + + + + + + + read Workbook Entry + + + + + + + write Workbook Entry + + + + + + + write sheet entry + + + + + + + read Sheet Entry + + + + sourcePortFig="Fig0.0" + destPortFig="Fig1.0" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig2.0" + sourceFigNode="Fig0" + destFigNode="Fig2" + + + + + + + + + + + sourcePortFig="Fig4.0" + destPortFig="Fig2.0" + sourceFigNode="Fig4" + destFigNode="Fig2" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig3.0" + sourceFigNode="Fig0" + destFigNode="Fig3" + + + + + + + + + + + sourcePortFig="Fig5.0" + destPortFig="Fig3.0" + sourceFigNode="Fig5" + destFigNode="Fig3" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig3.0" + destPortFig="Fig2.0" + sourceFigNode="Fig3" + destFigNode="Fig2" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig6.0" + destPortFig="Fig3.0" + sourceFigNode="Fig6" + destFigNode="Fig3" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig7.0" + destPortFig="Fig2.0" + sourceFigNode="Fig7" + destFigNode="Fig2" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig3.0" + destPortFig="Fig1.0" + sourceFigNode="Fig3" + destFigNode="Fig1" + + + + + + + <<extends>> + + + diff --git a/src/models/POIFSAddDocument.pgml b/src/models/POIFSAddDocument.pgml new file mode 100755 index 000000000..f28a8bd4c --- /dev/null +++ b/src/models/POIFSAddDocument.pgml @@ -0,0 +1,1024 @@ + + + + + + + + + Filesystem : + + + + + + + + + + + + + + + + + + + + + + Document : + + + + + + + + + + + + + + + + + + + + + DocumentProperty : + + + + + + + + + + + + + + + + + + DocumentBlock : + + + + + + + + + + + + + + + + + + PropertyTable : + + + + + + + + + + + + + + + + + + + RootProperty : + + + + + + + + + + + + + + + + : create + + + + + : create (1 .. n) + + + + + : create + + + + + : getDocumentProperty + + + + + : addProperty + + + + + : getRoot + + + + + : addChild + + + + sourcePortFig="Fig0.7" + destPortFig="Fig1.7" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig1.8" + destPortFig="Fig3.7" + sourceFigNode="Fig1" + destFigNode="Fig3" + + + + + + + + + + + sourcePortFig="Fig1.9" + destPortFig="Fig2.7" + sourceFigNode="Fig1" + destFigNode="Fig2" + + + + + + + + + + + sourcePortFig="Fig0.8" + destPortFig="Fig1.10" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig0.9" + destPortFig="Fig4.7" + sourceFigNode="Fig0" + destFigNode="Fig4" + + + + + + + + + + + sourcePortFig="Fig0.10" + destPortFig="Fig4.8" + sourceFigNode="Fig0" + destFigNode="Fig4" + + + + + + + + + + + sourcePortFig="Fig0.11" + destPortFig="Fig5.7" + sourceFigNode="Fig0" + destFigNode="Fig5" + + + + + + + + + diff --git a/src/models/POIFSClassDiagram.pgml b/src/models/POIFSClassDiagram.pgml new file mode 100755 index 000000000..96faf60ae --- /dev/null +++ b/src/models/POIFSClassDiagram.pgml @@ -0,0 +1,1107 @@ + + + + + + + + + Filesystem + + -_property_table : PropertyTable +-_header_block : HeaderBlock +-_documents : List + +createDocument(in stream:InputStream, in name:String) ++writeFilesystem(in stream:OutputStream) ++Filesystem() + + + + + + + Document + + -_property : DocumentProperty +-_blocks[] : DocumentBlock + #getDocumentProperty() : DocumentProperty +#Document(in name:String, in stream:InputStream) + + + + + + + DocumentBlock + + -_data[ 512 ] : byte +-_bytes_read : int + +DocumentBlock(in stream:InputStream) ++size() : int ++partiallyRead() : boolean + + + + + + + HeaderBlock + + -_bat_count : IntegerField +-_property_start : IntegerField +-_sbat_start : IntegerField = -2 +-_xbat_start : IntegerField = -2 +-_xbat_count : IntegerField = 0 +-_data[ 512 ] : byte + +setBATBlocks(in blockCount:int, in startBlock:int) : BATBlock ++setPropertyStart(in startBlock:int) ++setXBATStart(in startBlock:int) ++Header() ++calculateXBATStorageRequirements(in blockCount:int) : int + + + + + + + PropertyTable + + -_properties : List +-_blocks[ ] : BlockWritable +-_start_block : int + +getRoot() : Directory ++addProperty(in property:Property) ++preWrite() ++PropertyTable() ++getStartBlock() : int + + + + + + + DocumentProperty + + + +DocumentProperty(in name:String, in size:int) + + + + + + + <<Interface>> + BATManaged + +countBlocks() : int ++setStartBlock(in index:int) + + + + + + + <<Interface>> + BlockWritable + +writeBlocks(in stream:OutputStream) + + + + + + + BlockAllocationTable + + -_entries : IntList +-_blocks[] : BATBlock + #createBlocks() +#allocateSpace(in blockCount:int) : int +#BlockAllocationTable() +#countBlocks() : int + + + + + + + BATBlock + + -_fields[ 128 ] : IntegerField +-_data[ 512 ] : byte + +createBATBlocks(in entries[]:int) : BATBlock ++calculateStorageRequirements(in entryCount:int) : int + + + + sourcePortFig="Fig0.0" + destPortFig="Fig1.0" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + 0..* + + + + + sourcePortFig="Fig1.0" + destPortFig="Fig2.0" + sourceFigNode="Fig1" + destFigNode="Fig2" + + + + + + + 1..* + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig3.0" + sourceFigNode="Fig0" + destFigNode="Fig3" + + + + + + + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig4.0" + sourceFigNode="Fig0" + destFigNode="Fig4" + + + + + + + + + + + sourcePortFig="Fig1.0" + destPortFig="Fig5.0" + sourceFigNode="Fig1" + destFigNode="Fig5" + + + + + + + + + + + sourcePortFig="Fig4.0" + destPortFig="Fig6.0" + sourceFigNode="Fig4" + destFigNode="Fig6" + + + + + + + + + + + sourcePortFig="Fig1.0" + destPortFig="Fig6.0" + sourceFigNode="Fig1" + destFigNode="Fig6" + + + + + + + + + + + sourcePortFig="Fig1.0" + destPortFig="Fig7.0" + sourceFigNode="Fig1" + destFigNode="Fig7" + + + + + + + + + + + + sourcePortFig="Fig4.0" + destPortFig="Fig7.0" + sourceFigNode="Fig4" + destFigNode="Fig7" + + + + + + + + + + + sourcePortFig="Fig8.0" + destPortFig="Fig7.0" + sourceFigNode="Fig8" + destFigNode="Fig7" + + + + + + + + + + + sourcePortFig="Fig8.0" + destPortFig="Fig9.0" + sourceFigNode="Fig8" + destFigNode="Fig9" + + + + + + + 1..* + + + diff --git a/src/models/POIFSInitialization.pgml b/src/models/POIFSInitialization.pgml new file mode 100755 index 000000000..e43bd43e6 --- /dev/null +++ b/src/models/POIFSInitialization.pgml @@ -0,0 +1,572 @@ + + + + + + enclosingFig="Fig0" + + + + Filesystem : + + + + + + + + + + + + + + + + enclosingFig="Fig1" + + + + HeaderBlock : + + + + + + + + + + + + + + + enclosingFig="Fig2" + + + + PropertyTable : + + + + + + + + + + + + + + + + enclosingFig="Fig3" + + + + RootProperty : + + + + + + + + + + + + + + + + : create + + + + + : create + + + + + : create + + + + sourcePortFig="Fig0.7" + destPortFig="Fig2.7" + sourceFigNode="Fig0" + destFigNode="Fig2" + + + + + + + + + + + sourcePortFig="Fig2.8" + destPortFig="Fig3.7" + sourceFigNode="Fig2" + destFigNode="Fig3" + + + + + + + + + + + sourcePortFig="Fig0.8" + destPortFig="Fig1.7" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + diff --git a/src/models/POIFSLifeCycle.pgml b/src/models/POIFSLifeCycle.pgml new file mode 100755 index 000000000..136eba00c --- /dev/null +++ b/src/models/POIFSLifeCycle.pgml @@ -0,0 +1,392 @@ + + + + + + + + + (Client Application) : + + + + + + + + + + + + + + + + + + + + Filesystem : + + + + + + + + + + + + + + + + + + : create + + + + + : createDocument + + + + + : writeFileSystem + + + + sourcePortFig="Fig0.7" + destPortFig="Fig1.7" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig0.8" + destPortFig="Fig1.8" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig0.9" + destPortFig="Fig1.9" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + diff --git a/src/models/POIFSPropertyTablePreWrite.pgml b/src/models/POIFSPropertyTablePreWrite.pgml new file mode 100755 index 000000000..db5f3bd53 --- /dev/null +++ b/src/models/POIFSPropertyTablePreWrite.pgml @@ -0,0 +1,796 @@ + + + + + + + + + PropertyTable : + + + + + + + + + + + + + + + + + + + + Property : + + + + + + + + + + + + + + + + + + + PropertyBlock : + + + + + + + + + + + + + + + + + + + + PropertyBlock : + + + + + + + + + + + + + + + + + + Property : + + + + + + + + + + + + + + + + : setIndex (for each Property) + + + + + : createPropertyBlockArray + + + + + : create (enough so we have a multiple of 4 properties) + + + + + : create (1 for every 4 properties) + + + + + : preWrite (for each Property) + + + + sourcePortFig="Fig0.7" + destPortFig="Fig1.7" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig0.8" + destPortFig="Fig2.7" + sourceFigNode="Fig0" + destFigNode="Fig2" + + + + + + + + + + + sourcePortFig="Fig2.8" + destPortFig="Fig4.7" + sourceFigNode="Fig2" + destFigNode="Fig4" + + + + + + + + + + + sourcePortFig="Fig2.9" + destPortFig="Fig3.7" + sourceFigNode="Fig2" + destFigNode="Fig3" + + + + + + + + + + + sourcePortFig="Fig0.9" + destPortFig="Fig1.8" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + diff --git a/src/models/POIFSRootPropertyPreWrite.pgml b/src/models/POIFSRootPropertyPreWrite.pgml new file mode 100755 index 000000000..45068d7db --- /dev/null +++ b/src/models/POIFSRootPropertyPreWrite.pgml @@ -0,0 +1,398 @@ + + + + + + enclosingFig="Fig0" + + + + RootProperty : + + + + + + + + + + + + + + + + + + enclosingFig="Fig1" + + + + Property : + + + + + + + + + + + + + + + + + : setNextFile + + + + + : set _child_property + + + + + : setPreviousFile + + + + sourcePortFig="Fig0.7" + destPortFig="Fig1.7" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig0.8" + destPortFig="Fig0.9" + sourceFigNode="Fig0" + destFigNode="Fig0" + + + + + + + + + + + + + sourcePortFig="Fig0.10" + destPortFig="Fig1.8" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + diff --git a/src/models/POIFSWriteFilesystem.pgml b/src/models/POIFSWriteFilesystem.pgml new file mode 100755 index 000000000..06c6f1621 --- /dev/null +++ b/src/models/POIFSWriteFilesystem.pgml @@ -0,0 +1,1240 @@ + + + + + + enclosingFig="Fig0" + + + + Filesystem : + + + + + + + + + + + + + + + + + + + + + + + + enclosingFig="Fig1" + + + + PropertyTable : + + + + + + + + + + + + + + + enclosingFig="Fig2" + + + + BATManaged : + + + + + + + + + + + + + + + + enclosingFig="Fig3" + + + + BlockAllocationTable : + + + + + + + + + + + + + + + + + enclosingFig="Fig4" + + + + HeaderBlock : + + + + + + + + + + + + + + + + + enclosingFig="Fig5" + + + + BlockWritable : + + + + + + + + + + + + + + + + : preWrite + + + + + : countBlocks + + + + + : allocateSpace + + + + + : setStartBlock + + + + + : createBlocks + + + + + : setBatBlocks + + + + + : setPropertyStart + + + + + : writeBlocks + + + + + : create + + + + + : setXBATStart + + + + sourcePortFig="Fig0.7" + destPortFig="Fig1.7" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig0.8" + destPortFig="Fig2.7" + sourceFigNode="Fig0" + destFigNode="Fig2" + + + + + + + + + + + sourcePortFig="Fig0.9" + destPortFig="Fig3.7" + sourceFigNode="Fig0" + destFigNode="Fig3" + + + + + + + + + + + sourcePortFig="Fig0.10" + destPortFig="Fig2.8" + sourceFigNode="Fig0" + destFigNode="Fig2" + + + + + + + + + + + sourcePortFig="Fig0.11" + destPortFig="Fig3.8" + sourceFigNode="Fig0" + destFigNode="Fig3" + + + + + + + + + + + sourcePortFig="Fig0.12" + destPortFig="Fig4.7" + sourceFigNode="Fig0" + destFigNode="Fig4" + + + + + + + + + + + sourcePortFig="Fig0.13" + destPortFig="Fig4.8" + sourceFigNode="Fig0" + destFigNode="Fig4" + + + + + + + + + + + sourcePortFig="Fig0.14" + destPortFig="Fig5.7" + sourceFigNode="Fig0" + destFigNode="Fig5" + + + + + + + + + + + sourcePortFig="Fig0.15" + destPortFig="Fig3.9" + sourceFigNode="Fig0" + destFigNode="Fig3" + + + + + + + + + + + sourcePortFig="Fig0.16" + destPortFig="Fig4.9" + sourceFigNode="Fig0" + destFigNode="Fig4" + + + + + + + + + diff --git a/src/models/POIUseCases.pgml b/src/models/POIUseCases.pgml new file mode 100755 index 000000000..725ba22ee --- /dev/null +++ b/src/models/POIUseCases.pgml @@ -0,0 +1,988 @@ + + + + + + + + + + + + + + + + + + + + + + + + + ClientApps + + + + + + + read existing filesystem + + + + + + + write file system + + + + + + + create new filesystem + + + + + + + read file system directory + + + + + + + read existing file from file system + + + + + + + write new file to file system + + + + + + + delete file from file system + + + + + + + replace file in file system + + + + + + + read file + + + + + + + rename existing file in file system + + + + sourcePortFig="Fig0.0" + destPortFig="Fig1.0" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig2.0" + sourceFigNode="Fig0" + destFigNode="Fig2" + + + + + + + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig3.0" + sourceFigNode="Fig0" + destFigNode="Fig3" + + + + + + + + + + + sourcePortFig="Fig2.0" + destPortFig="Fig1.0" + sourceFigNode="Fig2" + destFigNode="Fig1" + + + + + + + <<includes>> + + + + + sourcePortFig="Fig4.0" + destPortFig="Fig1.0" + sourceFigNode="Fig4" + destFigNode="Fig1" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig5.0" + destPortFig="Fig1.0" + sourceFigNode="Fig5" + destFigNode="Fig1" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig6.0" + destPortFig="Fig2.0" + sourceFigNode="Fig6" + destFigNode="Fig2" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig7.0" + destPortFig="Fig2.0" + sourceFigNode="Fig7" + destFigNode="Fig2" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig8.0" + destPortFig="Fig2.0" + sourceFigNode="Fig8" + destFigNode="Fig2" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig2.0" + destPortFig="Fig3.0" + sourceFigNode="Fig2" + destFigNode="Fig3" + + + + + + + <<extends>> + + + + + sourcePortFig="Fig9.0" + destPortFig="Fig4.0" + sourceFigNode="Fig9" + destFigNode="Fig4" + + + + + + + uses + + + + + sourcePortFig="Fig9.0" + destPortFig="Fig5.0" + sourceFigNode="Fig9" + destFigNode="Fig5" + + + + + + + uses + + + + + sourcePortFig="Fig10.0" + destPortFig="Fig2.0" + sourceFigNode="Fig10" + destFigNode="Fig2" + + + + + + + <<extends>> + + + diff --git a/src/models/PropertyTableClassDiagram.pgml b/src/models/PropertyTableClassDiagram.pgml new file mode 100755 index 000000000..b788a8fd2 --- /dev/null +++ b/src/models/PropertyTableClassDiagram.pgml @@ -0,0 +1,800 @@ + + + + + + + + + Property + + -_name : String +-_name_size : ShortField +-_property_type : ByteField +-_storage_type : ByteField +-_previous_property : IntegerField +-_next_property : IntegerField +-_child_property : IntegerField +-_seconds_1 : IntegerField +-_days_1 : IntegerField +-_seconds_2 : IntegerField +-_days_2 : IntegerField +-_start_block : IntegerField +-_size : IntegerField +-_raw_data[ 128 ] : byte +-_index : int ++PROPERTY_SIZE : int = 128 +#_NO_INDEX : int = -1 +#_DIRECTORY_TYPE : byte = 1 +#_DOCUMENT_TYPE : byte = 2 +#_ROOT_TYPE : byte = 5 +#_BIG_BLOCK_STORAGE : byte = 1 +#_SMALL_BLOCK_STORAGE : byte = 0 +-_next_file : File +-_previous_file : File + #setIndex(in index:int) +#preWrite() +#getIndex() : int ++setStartBlock(in startBlock:int) +#Property() +#setName(in name:String) +#setPropertyType(in propertyType:byte) +#setStorageType(in storageType:byte) +#setChildProperty(in child:int) +#getChildProperty() : int +#setSize(in size:int) +#shouldUseSmallBlocks() : boolean + + + + + + + RootProperty + + -_children : List + + + + + + + + DocumentProperty + + + +DocumentProperty(in name:String, in size:int) + + + + + + + PropertyBlock + + -_properties[ 4 ] : Property + +createPropertyBlockArray(in properties:List) : BlockWritable + + + + + + + PropertyTable + + -_properties : List +-_blocks[ ] : BlockWritable +-_start_block : int + +getRoot() : Directory ++addProperty(in property:Property) ++preWrite() ++PropertyTable() ++getStartBlock() : int + + + + + + + <<Interface>> + File + +getNextFile() : File ++setNextFile(in file:File) ++getPreviousFile() : File ++setPreviousFile(in file:File) + + + + + + + <<Interface>> + Directory + +getChildren() : Iterator ++addChild(in property:Property) + + + + sourcePortFig="Fig1.0" + destPortFig="Fig0.0" + sourceFigNode="Fig1" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig2.0" + destPortFig="Fig0.0" + sourceFigNode="Fig2" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig3.0" + destPortFig="Fig0.0" + sourceFigNode="Fig3" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig4.0" + destPortFig="Fig3.0" + sourceFigNode="Fig4" + destFigNode="Fig3" + + + + + + + + 1..* + + + + + sourcePortFig="Fig4.0" + destPortFig="Fig0.0" + sourceFigNode="Fig4" + destFigNode="Fig0" + + + + + + + 1..* + + + + + sourcePortFig="Fig6.0" + destPortFig="Fig5.0" + sourceFigNode="Fig6" + destFigNode="Fig5" + + + + + + + + + + + sourcePortFig="Fig1.0" + destPortFig="Fig6.0" + sourceFigNode="Fig1" + destFigNode="Fig6" + + + + + + + + + + + sourcePortFig="Fig0.0" + destPortFig="Fig5.0" + sourceFigNode="Fig0" + destFigNode="Fig5" + + + + + + + + + diff --git a/src/models/analysismain.pgml b/src/models/analysismain.pgml new file mode 100755 index 000000000..3d548c2a8 --- /dev/null +++ b/src/models/analysismain.pgml @@ -0,0 +1,192 @@ + + + + + + + + POI + + + + + + + HSSF + + + + + + + HSSFSerializer + + + + + sourcePortFig="Fig2.0" + destPortFig="Fig1.0" + sourceFigNode="Fig2" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig1.0" + destPortFig="Fig0.0" + sourceFigNode="Fig1" + destFigNode="Fig0" + + + + + + + + + diff --git a/src/models/poi.argo b/src/models/poi.argo new file mode 100755 index 000000000..b31792b41 --- /dev/null +++ b/src/models/poi.argo @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {} + + diff --git a/src/models/poi.xmi b/src/models/poi.xmi new file mode 100755 index 000000000..48ae9c600 --- /dev/null +++ b/src/models/poi.xmi @@ -0,0 +1,19114 @@ + + + + + Novosoft UML Library + 0.4.19 + + + + + + project + + + + + + + analysisModel + + + + + + + + + + POI + + + + + + + + + + + + + read existing filesystem + + + + + + + + + + + + + + + create the filesystem + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + read all bytes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create a header block from first 512 bytes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create blocks from all blocks that are not header,bat or property blocks + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create bat blocks from bytes that are in bat + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create property table blocks from bytes starting at header.rootstartblock + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign BAT Blocks to the BAT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + derive property instances from the Property Table Blocks and add them to the property table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + InputStream + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + write file system + + + + + + + + + + + + + + + + + + + + createFileSystem + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + createHeaderBlock + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + createBlock [until all files have blocks] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create a record [until all files have records] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create bat block [if need more] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create a record [until all files have records] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + get the bat array info + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + get the extended bat array info + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + set the bat info + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + set the extended bat info + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create a block [if needed] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create a property + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + add the propert to the block + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + write all blocks to stream + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OutputStream + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + read file system directory + + + + + + + + + + + + + requests directory listing + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + enumerates properties + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + read existing file from file system + + + + + + + + + + + + + gets property from + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + gets property from + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + gets BAT Chain from + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + gets next bat chain element [until all are read] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + gets bytes [from each block in bat chain] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + constructs a byte array input stream with file bytes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + requests file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + returns input stream + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PropertyBlock + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ByteArrayInputStream + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + delete file from file system + + + + + + + + + + + + + replace file in file system + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + read file + + + + + + + + + + + + + + + + + + + uses + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + uses + + + + + + + + + + + + + + + + + + + + + + + + + + rename existing file in file system + + + + + + + + + + + + + + + + + + + + + + + + + POIFileSystem + + + + + + + + + + + + readFileSystem(InputStream in) + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + + + Block + + + + + + + + + + + + + + + + + createBlock(byte[] bytes, int offset, int length) + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + + + HeaderBlock + + + + + + + + + + + + + + + BATBlock + + + + + + + + + + + + + + + PropertyTableBlock + + + + + + + + + + + + + + + Property + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RootProperty + + + + + + + + + + + + + + + BAT + + + + + + + + + + + + createRecord + + + + + + + + + + + + + + + + return + + + + + + + + + + + bytes + + + + + + + + + + + + + + + + + + + + + + + getBlocks + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + blocks + + + + + + + + 0 + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + void + + + + + + + + + + + PropertyTable + + + + + + + + + + + + createRecord + + + + + + + + + + + + + + + + return + + + + + + + + + + + name + + + + + + + + + + + startBlock + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DirectoryProperty + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FileProperty + + + + + + + + + + + + + + + + + + + + + + + + + + + child + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + next + + + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + previous + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HSSF + + + + + + + + + + + + + + + + ClientApps + + + + + + + + + + create HSSF File + + + + + + + + + + + + + create new filesystem + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + read existing HSSF File + + + + + + + + + + + + + + + write HSSF File + + + + + + + + + + + + + + + + + + read Workbook Entry + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + write Workbook Entry + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + write sheet entry + + + + + + + + + + + + + + + + + + + + + + + + + write new file to file system + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + read Sheet Entry + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HSSFSerializer + + + + + + + + + + + + + Cocoon + + + + + + + + + + Sends Sax Events + + + + + + + + + + + + + + + + + + + + Sends an Ignored Event + + + + + + + + + + + + + Sends and Interrogative Event + + + + + + + + + + + + + Sends Setup Event + + + + + + + + + + + + + Sends Start Document Event + + + + + + + + + + + + + Sends End Document Event + + + + + + + + + + + + + Sends Start Element Event + + + + + + + + + + + + + Sends End Element Event + + + + + + + + + + + + + Sends Raw Data Event + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + designModel + + + + + + + + + + Property + + + + + + + + + + + + + + + + + + + _name + + + + + + + + + + + + _name_size + + + + + + + + + + + + _property_type + + + + + + + + + + + + _storage_type + + + + + + + + + + + + _previous_property + + + + + + + + + + + + _next_property + + + + + + + + + + + + _child_property + + + + + + + + + + + + _seconds_1 + + + + + + + + + + + + _days_1 + + + + + + + + + + + + _seconds_2 + + + + + + + + + + + + _days_2 + + + + + + + + + + + + _start_block + + + + + + + + + + + + _size + + + + + + + + + + + + _raw_data[ 128 ] + + + + + + + + + + + + _index + + + + + + + + + + + + setIndex + + + + + + + + + + + + + + + + index + + + + + + + + + + + + + + + + + + + + + + + preWrite + + + + + + + + + + + + + + + + + + + + + + + + + + getIndex + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + setStartBlock + + + + + + + + + + + + + + + + startBlock + + + + + + + + + + + + + + + + + + + + + + + PROPERTY_SIZE + + + + + + + java + 128 + + + + + + + + + + + _NO_INDEX + + + + + + + java + -1 + + + + + + + + + + + _DIRECTORY_TYPE + + + + + + + java + 1 + + + + + + + + + + + _DOCUMENT_TYPE + + + + + + + java + 2 + + + + + + + + + + + _ROOT_TYPE + + + + + + + java + 5 + + + + + + + + + + + _BIG_BLOCK_STORAGE + + + + + + + java + 1 + + + + + + + + + + + _SMALL_BLOCK_STORAGE + + + + + + + java + 0 + + + + + + + + + + + Property + + + + + + + + + + + + + + + + + + + + + + + + + + setName + + + + + + + + + + + + + + + + name + + + + + + + + + + + + + + + + + + + + + + + setPropertyType + + + + + + + + + + + + + + + + propertyType + + + + + + + + + + + + + + + + + + + + + + + setStorageType + + + + + + + + + + + + + + + + storageType + + + + + + + + + + + + + + + + + + + + + + + setChildProperty + + + + + + + + + + + + + + + + child + + + + + + + + + + + + + + + + + + + + + + + getChildProperty + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + setSize + + + + + + + + + + + + + + + + size + + + + + + + + + + + + + + + + + + + + + + + shouldUseSmallBlocks + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + _next_file + + + + + + + + + + + + _previous_file + + + + + + + + + + + + + + RootProperty + + + + + + + + + + + + + + + + + + _children + + + + + + + + + + + + + + DocumentProperty + + + + + + + + + + + + + + + DocumentProperty + + + + + + + + + + + + + + + + name + + + + + + + + + + + size + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PropertyBlock + + + + + + + + + + + + + + + + + + _properties[ 4 ] + + + + + + + + + + + + + createPropertyBlockArray + + + + + + + + + + + + + + + + return + + + + + + + + + + + properties + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PropertyTable + + + + + + + + + + + + + + + + _properties + + + + + + + + + + + + _blocks[ ] + + + + + + + + + + + + getRoot + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + addProperty + + + + + + + + + + + + + + + + property + + + + + + + + + + + + + + + + + + + + + + + preWrite + + + + + + + + + + + + + + + + + + + + + + + + + + PropertyTable + + + + + + + + + + + + + + + + + + + + + + + + + + getStartBlock + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + _start_block + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + File + + + + + + + + + + + + + + + + + getNextFile + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + setNextFile + + + + + + + + + + + + + + + + file + + + + + + + + + + + + + + + + + + + + + + + getPreviousFile + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + setPreviousFile + + + + + + + + + + + + + + + + file + + + + + + + + + + + + + + + + + + + + + + + + + realize + + + + + + + + + + Directory + + + + + + + + + + + + + + + + + getChildren + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + addChild + + + + + + + + + + + + + + + + property + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + realize + + + + + + + + + + + + + BigBlock + + + + + + + + + + + + + + + + + + + + + writeData + + + + + + + + + + + + + + + + stream + + + + + + + + + + + + + + + + + + + + + + + BIG_BLOCK_SIZE + + + + + + + java + 512 + + + + + + + + + + + doWriteData + + + + + + + + + + + + + + + + stream + + + + + + + + + + + data[] + + + + + + + + + + + + + + + + + + + + + + + + + HeaderBlock + + + + + + + + + + + + + + + _bat_count + + + + + + + + + + + + _property_start + + + + + + + + + + + + _sbat_start + + + + + + java + -2 + + + + + + + + + + + _xbat_start + + + + + + java + -2 + + + + + + + + + + + _xbat_count + + + + + + java + 0 + + + + + + + + + + + _data[ 512 ] + + + + + + + + + + + + setBATBlocks + + + + + + + + + + + + + + + + blockCount + + + + + + + + + + + startBlock + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + setPropertyStart + + + + + + + + + + + + + + + + startBlock + + + + + + + + + + + + + + + + + + + + + + + setXBATStart + + + + + + + + + + + + + + + + startBlock + + + + + + + + + + + + + + + + + + + + + + + Header + + + + + + + + + + + + + + + + + + + + + + + + + + calculateXBATStorageRequirements + + + + + + + + + + + + + + + + return + + + + + + + + + + + blockCount + + + + + + + + + + + + + + + + + + + + + + + + + BATBlock + + + + + + + + + + + + + + + _fields[ 128 ] + + + + + + + + + + + + _data[ 512 ] + + + + + + + + + + + + createBATBlocks + + + + + + + + + + + + + + + + return + + + + + + + + + + + entries[] + + + + + + + + + + + + + + + + + + + + + + + calculateStorageRequirements + + + + + + + + + + + + + + + + return + + + + + + + + + + + entryCount + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Filesystem + + + + + + + + + + + + createDocument + + + + + + + + + + + + + + + + stream + + + + + + + + + + + name + + + + + + + + + + + + + + + + + + + + + + + writeFilesystem + + + + + + + + + + + + + + + + stream + + + + + + + + + + + + + + + + + + + + + + + Filesystem + + + + + + + + + + + + + + + + + + + + + + + + + + _property_table + + + + + + + + + + + + _header_block + + + + + + + + + + + + _documents + + + + + + + + + + + + volatile + true + + + + + + + + + + Document + + + + + + + + + + + + + + + + getDocumentProperty + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + _property + + + + + + + + + + + + _blocks[] + + + + + + + + + + + + Document + + + + + + + + + + + + + + + + name + + + + + + + + + + + stream + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DocumentBlock + + + + + + + + + + + + + + + + _data[ 512 ] + + + + + + + + + + + + DocumentBlock + + + + + + + + + + + + + + + + stream + + + + + + + + + + + + + + + + + + + + + + + size + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + partiallyRead + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + _bytes_read + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BATManaged + + + + + + + + + + + + + + + countBlocks + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + setStartBlock + + + + + + + + + + + + + + + + index + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + realize + + + + + + + + + + + + + + + + + + + + + + + + + realize + + + + + + + + + + + + + realize + + + + + + + + + + + + + + + + + + + + + + realize + + + + + + + + + + + + + BlockWritable + + + + + + + + + + + + + + + + + writeBlocks + + + + + + + + + + + + + + + + stream + + + + + + + + + + + + + + + + + + + + + + + + + realize + + + + + + + + + + realize + + + + + + + + + + + + + + + + + + + + + + realize + + + + + + + + + + + + + + + + + + + + + + + + + realize + + + + + + + + + + + + + + + + + + + + + + + + + realize + + + + + + + + + + + + + BlockAllocationTable + + + + + + + + + + + + + + + createBlocks + + + + + + + + + + + + + + + + + + + + + + + + + + allocateSpace + + + + + + + + + + + + + + + + return + + + + + + + + + + + blockCount + + + + + + + + + + + + + + + + + + + + + + + _entries + + + + + + + + + + + + _blocks[] + + + + + + + + + + + + BlockAllocationTable + + + + + + + + + + + + + + + + + + + + + + + + + + countBlocks + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + realize + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + POIFSSerializer + + + + + + + + + + + + + + + startPrefixMapping + + + + + + + + + + + + + + + + ignoredPrefix + + + + + + + + + + + ignoredUri + + + + + + + + + + + + + + + + + + + + + + + endPrefixMapping + + + + + + + + + + + + + + + + ignoredPrefix + + + + + + + + + + + + + + + + + + + + + + + processingInstruction + + + + + + + + + + + + + + + + ignoredTarget + + + + + + + + + + + ignoredData + + + + + + + + + + + + + + + + + + + + + + + skippedEntity + + + + + + + + + + + + + + + + ignoredName + + + + + + + + + + + + + + + + + + + + + + + startDTD + + + + + + + + + + + + + + + + ignoredName + + + + + + + + + + + ignoredPublicId + + + + + + + + + + + ignoredSystemId + + + + + + + + + + + + + + + + + + + + + + + endDTD + + + + + + + + + + + + + + + + + + + + + + + + + + startEntity + + + + + + + + + + + + + + + + ignoredName + + + + + + + + + + + + + + + + + + + + + + + endEntity + + + + + + + + + + + + + + + + ignoredName + + + + + + + + + + + + + + + + + + + + + + + startCDATA + + + + + + + + + + + + + + + + + + + + + + + + + + endCDATA + + + + + + + + + + + + + + + + + + + + + + + + + + comment + + + + + + + + + + + + + + + + ignoredCh[] + + + + + + + + + + + ignoredStart + + + + + + + + + + + ignoredLength + + + + + + + + + + + + + + + + + + + + + + + shouldSetContentLength + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + setOutputStream + + + + + + + + + + + + + + + + out + + + + + + + + + + + + + + + + + + + + + + + _output_stream + + + + + + java + null + + + + + + + + + + + _locator + + + + + + java + null + + + + + + + + + + + setDocumentLocator + + + + + + + + + + + + + + + + locator + + + + + + + + + + + + + + + + + + + + + + + startDocument + + + + + + + + + + + + + + + + + + + + + + + + + + endDocument + + + + + + + + + + + + + + + + + + + + + + + + + + startElement + + + + + + + + + + + + + + + + namespaceURI + + + + + + + + + + + localName + + + + + + + + + + + qName + + + + + + + + + + + atts + + + + + + + + + + + + + + + + + + + + + + + endElement + + + + + + + + + + + + + + + + namespaceURI + + + + + + + + + + + localName + + + + + + + + + + + qName + + + + + + + + + + + + + + + + + + + + + + + characters + + + + + + + + + + + + + + + + ch[] + + + + + + + + + + + start + + + + + + + + + + + length + + + + + + + + + + + + + + + + + + + + + + + ignorableWhitespace + + + + + + + + + + + + + + + + ch[] + + + + + + + + + + + start + + + + + + + + + + + length + + + + + + + + + + + + + + + + + + + + + + + _open_elements + + + + + + java + new Stack() + + + + + + + + + + + _filesystem + + + + + + java + new Filesystem() + + + + + + + + + + + getElementProcessorFactory + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + doLocalPreEndDocument + + + + + + + + + + + + + + + + + + + + + + + + + + doLocalPostEndDocument + + + + + + + + + + + + + + + + + + + + + + + + + + getFilesystem + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + SAXExceptionFactory + + + + + + + + + + + + + + + + return + + + + + + + + + + + message + + + + + + + + + + + e + + + + + + + + + + + + + + + + + + + + + + + SAXExceptionFactory + + + + + + + + + + + + + + + + return + + + + + + + + + + + message + + + + + + + + + + + + + + + + + + + + + + + + + org.xml.sax + + + + + + + + + + Locator + + + + + + + + + + Attributes + + + + + + + + + + SAXException + + + + + + + + + + + + + Attribute + + + + + + + + + + + + _name + + + + + + + + + + + + + _value + + + + + + + + + + + + + getName + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + getValue + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + getValueAsInt + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + getValueAsShort + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + getValueAsLong + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + getValueAsBoolean + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + Attribute + + + + + + + + + + + + + + + + name + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + + + ElementProcessor + + + + + + + + + + + initialize + + + + + + + + + + + + + + + + attributes[] + + + + + + + + + + + parent + + + + + + + + + + + filesystem + + + + + + + + + + + + + + + + + + + + + + + acceptCharacters + + + + + + + + + + + + + + + + data[] + + + + + + + + + + + + + + + + + + + + + + + acceptWhitespaceCharacters + + + + + + + + + + + + + + + + data[] + + + + + + + + + + + + + + + + + + + + + + + endProcessing + + + + + + + + + + + + + + + + + + + + + + + + + + + + ElementProcessorFactory + + + + + + + + + + + + + + + _element_processor_map + + + + + + + + + + + + + createElementProcessor + + + + + + + + + + + + + + + + return + + + + + + + + + + + name + + + + + + + + + + + + + + + + + + + + + + + addElementProcessorProgenitor + + + + + + + + + + + + + + + + name + + + + + + + + + + + progenitor + + + + + + + + + + + + + + + + + + + + + + + lookupElementProcessorProgenitor + + + + + + + + + + + + + + + + return + + + + + + + + + + + name + + + + + + + + + + + + + + + + + + + + + + + doCreateElementProcessor + + + + + + + + + + + + + + + + return + + + + + + + + + + + progenitor + + + + + + + + + + + + + + + + + + + + + + + constructElementProcessor + + + + + + + + + + + + + + + + return + + + + + + + + + + + progenitor + + + + + + + + + + + + + + + + + + + + + + + createNewElementProcessorInstance + + + + + + + + + + + + + + + + return + + + + + + + + + + + progenitor + + + + + + + + + + + + + + + + + + + + + + + + + HSSFSerializer + + + + + + + + + + + + + + + _element_processor_factory + + + + + + + + + + + + getMimeType + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HSSFElementProcessorFactory + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ElementProcessorFactory.CannotCreateElementProcessorException + + + + + + + + + + + + + + + + + + + + + + + + + + + includes + + + + + + + + + + + + + extends + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + java + + + + + + + + + + lang + + + + + + + + + + Object + + + + + + + + + + + Integer + + + + + + + + + + + int + + + + + + + + + + String + + + + + + + + + + + Char + + + + + + + + + + + short + + + + + + + + + + byte + + + + + + + + + + Byte + + + + + + + + + + + Short + + + + + + + + + + + boolean + + + + + + + + + + long + + + + + + + + + + double + + + + + + + + + + char + + + + + + + + + + Cloneable + + + + + + + + + + + reflect + + + + + + + + + + Constructor + + + + + + + + + + + + + Class + + + + + + + + + + + Exception + + + + + + + + + + + + + util + + + + + + + + + + Iterator + + + + + + + + + + Collection + + + + + + + + + + List + + + + + + + + + + Vector + + + + + + + + + + + SortedSet + + + + + + + + + + Set + + + + + + + + + + Stack + + + + + + + + + + + Map + + + + + + + + + + + + io + + + + + + + + + + InputStream + + + + + + + + + + + OutputStream + + + + + + + + + + + + + + + util + + + + + + + + + + FixedField + + + + + + + + + + + + + + + + + readFromBytes + + + + + + + + + + + + + + + + return + + + + + + + + + + + data[] + + + + + + + + + + + + + + + + + + + + + + + readFromStream + + + + + + + + + + + + + + + + return + + + + + + + + + + + stream + + + + + + + + + + + + + + + + + + + + + + + writeToBytes + + + + + + + + + + + + + + + + return + + + + + + + + + + + data[] + + + + + + + + + + + + + + + + + + + + + + + toString + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + + + BitField + + + + + + + + + + + + getValue + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + + + + + + + + + + + + + getShortValue + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + + + + + + + + + + + + + getRawValue + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + + + + + + + + + + + + + getShortRawValue + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + + + + + + + + + + + + + isSet + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + + + + + + + + + + + + + isAllSet + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + + + + + + + + + + + + + setValue + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + setShortValue + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + clear + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + + + + + + + + + + + + + clearShort + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + + + + + + + + + + + + + clearByte + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + + + + + + + + + + + + + set + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + + + + + + + + + + + + + setShort + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + + + + + + + + + + + + + setByte + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + + + + + + + + + + + + + setBoolean + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + flag + + + + + + + + + + + + + + + + + + + + + + + setShortBoolean + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + flag + + + + + + + + + + + + + + + + + + + + + + + setByteBoolean + + + + + + + + + + + + + + + + return + + + + + + + + + + + holder + + + + + + + + + + + flag + + + + + + + + + + + + + + + + + + + + + + + + + ByteField + + + + + + + + + + + + + + + get + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + set + + + + + + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + set + + + + + + + + + + + + + + + + value + + + + + + + + + + + data[] + + + + + + + + + + + + + + + + + + + + + + + + + HexDump + + + + + + + + + + + + EOL + + + + + + + + + + + + dump + + + + + + + + + + + + + + + + data[] + + + + + + + + + + + offset + + + + + + + + + + + stream + + + + + + + + + + + index + + + + + + + + + + + + + + + + + + + + + + + + + IntList + + + + + + + + + + + + add + + + + + + + + + + + + + + + + index + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + add + + + + + + + + + + + + + + + + return + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + addAll + + + + + + + + + + + + + + + + return + + + + + + + + + + + c + + + + + + + + + + + + + + + + + + + + + + + addAll + + + + + + + + + + + + + + + + return + + + + + + + + + + + index + + + + + + + + + + + c + + + + + + + + + + + + + + + + + + + + + + + clear + + + + + + + + + + + + + + + + + + + + + + + + + + contains + + + + + + + + + + + + + + + + return + + + + + + + + + + + o + + + + + + + + + + + + + + + + + + + + + + + containsAll + + + + + + + + + + + + + + + + return + + + + + + + + + + + c + + + + + + + + + + + + + + + + + + + + + + + equals + + + + + + + + + + + + + + + + return + + + + + + + + + + + o + + + + + + + + + + + + + + + + + + + + + + + get + + + + + + + + + + + + + + + + return + + + + + + + + + + + index + + + + + + + + + + + + + + + + + + + + + + + hashCode + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + indexOf + + + + + + + + + + + + + + + + return + + + + + + + + + + + o + + + + + + + + + + + + + + + + + + + + + + + isEmpty + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + lastIndexOf + + + + + + + + + + + + + + + + return + + + + + + + + + + + o + + + + + + + + + + + + + + + + + + + + + + + remove + + + + + + + + + + + + + + + + return + + + + + + + + + + + index + + + + + + + + + + + + + + + + + + + + + + + removeValue + + + + + + + + + + + + + + + + return + + + + + + + + + + + o + + + + + + + + + + + + + + + + + + + + + + + removeAll + + + + + + + + + + + + + + + + return + + + + + + + + + + + c + + + + + + + + + + + + + + + + + + + + + + + retainAll + + + + + + + + + + + + + + + + return + + + + + + + + + + + c + + + + + + + + + + + + + + + + + + + + + + + set + + + + + + + + + + + + + + + + return + + + + + + + + + + + index + + + + + + + + + + + element + + + + + + + + + + + + + + + + + + + + + + + size + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + toArray + + + + + + + + + + + + + + + + return[] + + + + + + + + + + + + + + + + + + + + + + + toArray + + + + + + + + + + + + + + + + return[] + + + + + + + + + + + a[] + + + + + + + + + + + + + + + + + + + + + + + + + LittleEndian + + + + + + + + + + + + BufferUnderrunException + + + + + + + + + + + + + + getShort + + + + + + + + + + + + + + + + return + + + + + + + + + + + data[] + + + + + + + + + + + offset + + + + + + + + + + + + + + + + + + + + + + + getShort + + + + + + + + + + + + + + + + return + + + + + + + + + + + data[] + + + + + + + + + + + + + + + + + + + + + + + getInt + + + + + + + + + + + + + + + + return + + + + + + + + + + + data[] + + + + + + + + + + + offset + + + + + + + + + + + + + + + + + + + + + + + getInt + + + + + + + + + + + + + + + + return + + + + + + + + + + + data[] + + + + + + + + + + + + + + + + + + + + + + + getLong + + + + + + + + + + + + + + + + return + + + + + + + + + + + data[] + + + + + + + + + + + offset + + + + + + + + + + + + + + + + + + + + + + + getDouble + + + + + + + + + + + + + + + + return + + + + + + + + + + + data[] + + + + + + + + + + + offset + + + + + + + + + + + + + + + + + + + + + + + getDouble + + + + + + + + + + + + + + + + return + + + + + + + + + + + data[] + + + + + + + + + + + + + + + + + + + + + + + putShort + + + + + + + + + + + + + + + + data[] + + + + + + + + + + + offset + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + putShort + + + + + + + + + + + + + + + + data[] + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + getLong + + + + + + + + + + + + + + + + return + + + + + + + + + + + data[] + + + + + + + + + + + + + + + + + + + + + + + putInt + + + + + + + + + + + + + + + + data[] + + + + + + + + + + + offset + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + putInt + + + + + + + + + + + + + + + + data[] + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + putLong + + + + + + + + + + + + + + + + data[] + + + + + + + + + + + offset + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + putLong + + + + + + + + + + + + + + + + data[] + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + readShort + + + + + + + + + + + + + + + + return + + + + + + + + + + + stream + + + + + + + + + + + + + + + + + + + + + + + readInt + + + + + + + + + + + + + + + + return + + + + + + + + + + + stream + + + + + + + + + + + + + + + + + + + + + + + readLong + + + + + + + + + + + + + + + + return + + + + + + + + + + + stream + + + + + + + + + + + + + + + + + + + + + + + readFromStream + + + + + + + + + + + + + + + + return [] + + + + + + + + + + + stream + + + + + + + + + + + size + + + + + + + + + + + + + + + + + + + + + + + + + LittleEndianConsts + + + + + + + + + + + + SHORT_SIZE + + + + + + + java + 2 + + + + + + + + + + + INT_SIZE + + + + + + + java + 4 + + + + + + + + + + + LONG_SIZE + + + + + + + java + 8 + + + + + + + + + + + DOUBLE_SIZE + + + + + + + java + 8 + + + + + + + + + + + transient + false + + + + + + + + + + LongField + + + + + + + + + + + + + + + get + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + set + + + + + + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + set + + + + + + + + + + + + + + + + value + + + + + + + + + + + data[] + + + + + + + + + + + + + + + + + + + + + + + + + ShortField + + + + + + + + + + + + + + + get + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + set + + + + + + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + set + + + + + + + + + + + + + + + + value + + + + + + + + + + + data[] + + + + + + + + + + + + + + + + + + + + + + + + + ShortList + + + + + + + + + + + + add + + + + + + + + + + + + + + + + index + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + add + + + + + + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + addAll + + + + + + + + + + + + + + + + return + + + + + + + + + + + c + + + + + + + + + + + + + + + + + + + + + + + addAll + + + + + + + + + + + + + + + + return + + + + + + + + + + + index + + + + + + + + + + + c + + + + + + + + + + + + + + + + + + + + + + + clear + + + + + + + + + + + + + + + + + + + + + + + + + + contains + + + + + + + + + + + + + + + + return + + + + + + + + + + + o + + + + + + + + + + + + + + + + + + + + + + + containsAll + + + + + + + + + + + + + + + + return + + + + + + + + + + + c + + + + + + + + + + + + + + + + + + + + + + + equals + + + + + + + + + + + + + + + + return + + + + + + + + + + + o + + + + + + + + + + + + + + + + + + + + + + + get + + + + + + + + + + + + + + + + return + + + + + + + + + + + index + + + + + + + + + + + + + + + + + + + + + + + hashCode + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + indexOf + + + + + + + + + + + + + + + + return + + + + + + + + + + + o + + + + + + + + + + + + + + + + + + + + + + + isEmpty + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + lastIndexof + + + + + + + + + + + + + + + + return + + + + + + + + + + + o + + + + + + + + + + + + + + + + + + + + + + + remove + + + + + + + + + + + + + + + + return + + + + + + + + + + + index + + + + + + + + + + + + + + + + + + + + + + + removeValue + + + + + + + + + + + + + + + + return + + + + + + + + + + + o + + + + + + + + + + + + + + + + + + + + + + + removeAll + + + + + + + + + + + + + + + + return + + + + + + + + + + + c + + + + + + + + + + + + + + + + + + + + + + + retainAll + + + + + + + + + + + + + + + + return + + + + + + + + + + + c + + + + + + + + + + + + + + + + + + + + + + + set + + + + + + + + + + + + + + + + return + + + + + + + + + + + index + + + + + + + + + + + element + + + + + + + + + + + + + + + + + + + + + + + size + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + toArray + + + + + + + + + + + + + + + + return[] + + + + + + + + + + + + + + + + + + + + + + + toArray + + + + + + + + + + + + + + + + return [] + + + + + + + + + + + a[] + + + + + + + + + + + + + + + + + + + + + + + + + IntegerField + + + + + + + + + + + + + + + get + + + + + + + + + + + + + + + + return + + + + + + + + + + + + + + + + + + + + + + + set + + + + + + + + + + + + + + + + value + + + + + + + + + + + + + + + + + + + + + + + set + + + + + + + + + + + + + + + + value + + + + + + + + + + + data[] + + + + + + + + + + + + + + + + + + + + + + + + + StringUtil + + + + + + + + + + + + getFromUnicode + + + + + + + + + + + + + + + + return + + + + + + + + + + + string[] + + + + + + + + + + + offset + + + + + + + + + + + len + + + + + + + + + + + + + + + + + + + + + + + getFromUnicode + + + + + + + + + + + + + + + + return + + + + + + + + + + + string[] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + realize + + + + + + + + + + + + + + + + + + + + + + + + + realize + + + + + + + + + + + + + + + + + + + + + + + + + realize + + + + + + + + + + + + + + + + + + + + + + + + + realize + + + + + + + + + + + + + + + create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + addProperty + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + addChild + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create + + + + + + + + + + + create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Filesystem + + + + + + + + + + + + + + + + + HeaderBlock + + + + + + + + + + + + + + + PropertyTable + + + + + + + + + + + + + + + + + RootProperty + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create + + + + + + + + + + + create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + getDocumentProperty + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + getRoot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create (multiple) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Filesystem + + + + + + + + + + + + + + + + + + + + + Document + + + + + + + + + + + + + + + + + + + + + DocumentBlock + + + + + + + + + + + + + DocumentProperty + + + + + + + + + + + + + PropertyTable + + + + + + + + + + + + + + + RootProperty + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create (1 .. n) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + getDocumentProperty + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + addProperty + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + getRoot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + addChild + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create + + + + + + + + + + + setIndex (for each Property) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + createPropertyBlockArray + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create (enough so we have a multiple of 4 properties) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create (1 for every 4 properties) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + preWrite (for each Property) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + setNextFile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + set _child_property + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + setPreviousFile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + preWrite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + countBlocks + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + allocateSpace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + setStartBlock + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + createBlocks + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + setBatBlocks + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + setPropertyStart + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + writeBlocks + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + setXBATStart + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + createDocument + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + writeFileSystem + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create + + + + + + + + + + + Filesystem + + + + + + + + + + + + + + + HeaderBlock + + + + + + + + + + + + + PropertyTable + + + + + + + + + + + + + + + + + RootProperty + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Filesystem + + + + + + + + + + + + + + + + + + + + + Document + + + + + + + + + + + + + + + + + + + + + DocumentProperty + + + + + + + + + + + + + DocumentBlock + + + + + + + + + + + + + PropertyTable + + + + + + + + + + + + + + + RootProperty + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PropertyTable + + + + + + + + + + + + + + + + + Property + + + + + + + + + + + + + + + PropertyBlock + + + + + + + + + + + + + + + + + + + PropertyBlock + + + + + + + + + + + + + Property + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RootProperty + + + + + + + + + + + + + + + + + + + + + Property + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Filesystem + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PropertyTable + + + + + + + + + + + + + BATManaged + + + + + + + + + + + + + + + BlockAllocationTable + + + + + + + + + + + + + + + + + HeaderBlock + + + + + + + + + + + + + + + + + BlockWritable + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (Client Application) + + + + + + + + + + + + + + + + + Filesystem + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/models/poifsAnalysisClasses.pgml b/src/models/poifsAnalysisClasses.pgml new file mode 100755 index 000000000..39c4ab62c --- /dev/null +++ b/src/models/poifsAnalysisClasses.pgml @@ -0,0 +1,1225 @@ + + + + + + + + + POIFileSystem + + + +readFileSystem(InputStream in)() : POIFileSystem + + + + + + + Block + + + +createBlock(byte[] bytes, int offset, int length)() : Block + + + + + + + HeaderBlock + + + + + + + + + + BATBlock + + + + + + + + + + PropertyTableBlock + + + + + + + + + + Property + + + + + + + + + + RootProperty + + + + + + + + + + BAT + + -blocks[0..*] : BATBlock + +createRecord(bytes:Collection) : int ++getBlocks() : Collection + + + + + + + PropertyTable + + + +createRecord(name:String, startBlock:int, :) + + + + + + + DirectoryProperty + + + + + + + + + + FileProperty + + + + + + + sourcePortFig="Fig3.0" + destPortFig="Fig1.0" + sourceFigNode="Fig3" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig4.0" + destPortFig="Fig1.0" + sourceFigNode="Fig4" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig2.0" + destPortFig="Fig1.0" + sourceFigNode="Fig2" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig7.0" + destPortFig="Fig1.0" + sourceFigNode="Fig7" + destFigNode="Fig1" + + + + + + + 0..* + + + + + sourcePortFig="Fig4.0" + destPortFig="Fig5.0" + sourceFigNode="Fig4" + destFigNode="Fig5" + + + + + + + 0..* + + + + + sourcePortFig="Fig9.0" + destPortFig="Fig5.0" + sourceFigNode="Fig9" + destFigNode="Fig5" + + + + + + + + + + + sourcePortFig="Fig6.0" + destPortFig="Fig9.0" + sourceFigNode="Fig6" + destFigNode="Fig9" + + + + + + + + + + + sourcePortFig="Fig10.0" + destPortFig="Fig5.0" + sourceFigNode="Fig10" + destFigNode="Fig5" + + + + + + + + + + + sourcePortFig="Fig9.0" + destPortFig="Fig5.0" + sourceFigNode="Fig9" + destFigNode="Fig5" + + + + + + + child + + + + + sourcePortFig="Fig5.0" + destPortFig="Fig5.0" + sourceFigNode="Fig5" + destFigNode="Fig5" + + + + + + + + + +next + 0..1 + + + + + sourcePortFig="Fig5.0" + destPortFig="Fig5.0" + sourceFigNode="Fig5" + destFigNode="Fig5" + + + + + + + + + 0..1 + previous + + + diff --git a/src/models/projectmain.pgml b/src/models/projectmain.pgml new file mode 100755 index 000000000..9bb2a67c9 --- /dev/null +++ b/src/models/projectmain.pgml @@ -0,0 +1,138 @@ + + + + + + + + analysisModel + + + + + + + designModel + + + + + + + util + + + diff --git a/src/models/readFileFromFilesystemSequenceDiagram.pgml b/src/models/readFileFromFilesystemSequenceDiagram.pgml new file mode 100755 index 000000000..8b732a1c3 --- /dev/null +++ b/src/models/readFileFromFilesystemSequenceDiagram.pgml @@ -0,0 +1,1278 @@ + + + + + + enclosingFig="Fig0" + + + + : ClientApps + + + + + + + + + + + + + + + + enclosingFig="Fig1" + + + + : POIFileSystem + + + + + + + + + + + + + + + + + + + + enclosingFig="Fig2" + + + + : PropertyTable + + + + + + + + + + + + + + + + enclosingFig="Fig3" + + + + PropertyBlock : + + + + + + + + + + + + + + + enclosingFig="Fig4" + + + + : BAT + + + + + + + + + + + + + + + + enclosingFig="Fig5" + + + + : BATBlock + + + + + + + + + + + + + + + enclosingFig="Fig6" + + + + : Block + + + + + + + + + + + + + + + enclosingFig="Fig7" + + + + ByteArrayInputStream : Object + + + + + + + + + + + + + + + + : gets property from + + + + + : gets property from + + + + + : gets BAT Chain from + + + + + : gets next bat chain element [until all are read] + + + + + : gets bytes [from each block in bat chain] + + + + + : constructs a byte array input stream with file bytes + + + + + : requests file + + + + + : returns input stream + + + + sourcePortFig="Fig1.7" + destPortFig="Fig2.7" + sourceFigNode="Fig1" + destFigNode="Fig2" + + + + + + + + + + + sourcePortFig="Fig2.8" + destPortFig="Fig3.7" + sourceFigNode="Fig2" + destFigNode="Fig3" + + + + + + + + + + + sourcePortFig="Fig1.8" + destPortFig="Fig4.7" + sourceFigNode="Fig1" + destFigNode="Fig4" + + + + + + + + + + + sourcePortFig="Fig4.8" + destPortFig="Fig5.7" + sourceFigNode="Fig4" + destFigNode="Fig5" + + + + + + + + + + + sourcePortFig="Fig1.9" + destPortFig="Fig6.7" + sourceFigNode="Fig1" + destFigNode="Fig6" + + + + + + + + + + + sourcePortFig="Fig1.10" + destPortFig="Fig7.7" + sourceFigNode="Fig1" + destFigNode="Fig7" + + + + + + + + + + + sourcePortFig="Fig0.7" + destPortFig="Fig1.11" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig1.12" + destPortFig="Fig0.8" + sourceFigNode="Fig1" + destFigNode="Fig0" + + + + + + + + + diff --git a/src/models/readFileSystemDirectorySequenceDiagram.pgml b/src/models/readFileSystemDirectorySequenceDiagram.pgml new file mode 100755 index 000000000..d10ec34e3 --- /dev/null +++ b/src/models/readFileSystemDirectorySequenceDiagram.pgml @@ -0,0 +1,410 @@ + + + + + + + + + : ClientApps + + + + + + + + + + + + + + + + + + : POIFileSystem + + + + + + + + + + + + + + + + + + + : PropertyTable + + + + + + + + + + + + + + + + : requests directory listing + + + + + : enumerates properties + + + + sourcePortFig="Fig0.7" + destPortFig="Fig1.7" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig1.8" + destPortFig="Fig2.7" + sourceFigNode="Fig1" + destFigNode="Fig2" + + + + + + + + + diff --git a/src/models/readFilesystemSequenceDiagram.pgml b/src/models/readFilesystemSequenceDiagram.pgml new file mode 100755 index 000000000..09c55b7bd --- /dev/null +++ b/src/models/readFilesystemSequenceDiagram.pgml @@ -0,0 +1,1364 @@ + + + + + + enclosingFig="Fig0" + + + + : ClientApps + + + + + + + + + + + + + + + enclosingFig="Fig1" + + + + : POIFileSystem + + + + + + + + + + + + + + + + + + + + + + + + + InputStream : Object + + + + + + + + + + + + + + + enclosingFig="Fig3" + + + + : HeaderBlock + + + + + + + + + + + + + + + enclosingFig="Fig4" + + + + : Block + + + + + + + + + + + + + + + enclosingFig="Fig5" + + + + : BATBlock + + + + + + + + + + + + + + + + + + : PropertyTableBlock + + + + + + + + + + + + + + + enclosingFig="Fig7" + + + + : BAT + + + + + + + + + + + + + + + + + + : PropertyTable + + + + + + + + + + + + + + + + : create the filesystem + + + + + : read all bytes + + + + + : create a header block from first 512 bytes + + + + + : create blocks from all blocks that are not header,bat or property blocks + + + + + : create bat blocks from bytes that are in bat + + + + + : create property table blocks from bytes starting at header.rootstartblock + + + + + : assign BAT Blocks to the BAT + + + + + : derive property instances from the Property Table Blocks and add them to the property table + + + + sourcePortFig="Fig0.7" + destPortFig="Fig1.7" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig1.8" + destPortFig="Fig2.7" + sourceFigNode="Fig1" + destFigNode="Fig2" + + + + + + + + + + + sourcePortFig="Fig1.9" + destPortFig="Fig3.7" + sourceFigNode="Fig1" + destFigNode="Fig3" + + + + + + + + + + + sourcePortFig="Fig1.10" + destPortFig="Fig4.7" + sourceFigNode="Fig1" + destFigNode="Fig4" + + + + + + + + + + + sourcePortFig="Fig1.11" + destPortFig="Fig5.7" + sourceFigNode="Fig1" + destFigNode="Fig5" + + + + + + + + + + + sourcePortFig="Fig1.12" + destPortFig="Fig6.7" + sourceFigNode="Fig1" + destFigNode="Fig6" + + + + + + + + + + + sourcePortFig="Fig1.13" + destPortFig="Fig7.7" + sourceFigNode="Fig1" + destFigNode="Fig7" + + + + + + + + + + + sourcePortFig="Fig1.14" + destPortFig="Fig8.7" + sourceFigNode="Fig1" + destFigNode="Fig8" + + + + + + + + + diff --git a/src/models/utilClasses.pgml b/src/models/utilClasses.pgml new file mode 100755 index 000000000..fb86a0ff0 --- /dev/null +++ b/src/models/utilClasses.pgml @@ -0,0 +1,1105 @@ + + + + + + + + + <<Interface>> + FixedField + +readFromBytes(in data[]:byte) ++readFromStream(in stream:InputStream) ++writeToBytes(in data[]:byte) ++toString() : String + + + + + + + BitField + + + +getValue(in holder:int) : int ++getShortValue(in holder:Short) : short ++getRawValue(in holder:int) : int ++getShortRawValue(in holder:short) : short ++isSet(in holder:int) : boolean ++isAllSet(in holder:int) : boolean ++setValue(in holder:int, in value:int) : int ++setShortValue(in holder:short, in value:short) : short ++clear(in holder:int) : int ++clearShort(in holder:short) : short ++clearByte(in holder:byte) : byte ++set(in holder:int) : int ++setShort(in holder:short) : short ++setByte(in holder:byte) : byte ++setBoolean(in holder:int, in flag:boolean) : int ++setShortBoolean(in holder:short, in flag:boolean) : short ++setByteBoolean(in holder:byte, in flag:boolean) : byte + + + + + + + ByteField + + + +get() : byte ++set(in value:byte) ++set(in value:byte, in data[]:byte) + + + + + + + HexDump + + +EOL : String + +dump(in data[]:byte, in offset:long, in stream:OutputStream, in index:int) + + + + + + + IntList + + + +add(in index:int, in value:int) ++add(in value:int) : boolean ++addAll(in c:IntList) : boolean ++addAll(in index:int, in c:IntList) : boolean ++clear() ++contains(in o:int) : boolean ++containsAll(in c:IntList) : boolean ++equals(in o:Object) : boolean ++get(in index:int) : int ++hashCode() : int ++indexOf(in o:int) : int ++isEmpty() : boolean ++lastIndexOf(in o:int) : int ++remove(in index:int) : int ++removeValue(in o:int) : boolean ++removeAll(in c:IntList) : boolean ++retainAll(in c:IntList) : boolean ++set(in index:int, in element:int) : int ++size() : int ++toArray() : int ++toArray(in a[]:int) : int + + + + + + + LittleEndian + + + +getShort(in data[]:byte, in offset:int) : short ++getShort(in data[]:byte) : short ++getInt(in data[]:byte, in offset:int) : int ++getInt(in data[]:byte) : int ++getLong(in data[]:byte, in offset:int) : long ++getDouble(in data[]:byte, in offset:int) : double ++getDouble(in data[]:byte) : double ++putShort(in data[]:byte, in offset:int, in value:short) ++putShort(in data[]:byte, in value:short) ++getLong(in data[]:byte) : long ++putInt(in data[]:byte, in offset:int, in value:int) ++putInt(in data[]:byte, in value:int) ++putLong(in data[]:byte, in offset:int, in value:long) ++putLong(in data[]:byte, in value:long) ++readShort(in stream:InputStream) : short ++readInt(in stream:InputStream) : int ++readLong(in stream:InputStream) : long ++readFromStream(in stream:InputStream, in size:int) : byte + + + + + + + LittleEndianConsts + + +SHORT_SIZE : int = 2 ++INT_SIZE : int = 4 ++LONG_SIZE : int = 8 ++DOUBLE_SIZE : int = 8 + + + + + + + + LongField + + + +get() : long ++set(in value:long) ++set(in value:long, in data[]:byte) + + + + + + + ShortField + + + +get() : short ++set(in value:short) ++set(in value:short, in data[]:byte) + + + + + + + ShortList + + + +add(in index:int, in value:short) ++add(in value:short) ++addAll(in c:ShortList) : boolean ++addAll(in index:int, in c:ShortList) : boolean ++clear() ++contains(in o:short) : boolean ++containsAll(in c:ShortList) : boolean ++equals(in o:Object) : boolean ++get(in index:int) : short ++hashCode() : int ++indexOf(in o:short) : int ++isEmpty() : boolean ++lastIndexof(in o:short) : int ++remove(in index:int) : short ++removeValue(in o:short) : boolean ++removeAll(in c:ShortList) : boolean ++retainAll(in return:boolean, in c:ShortList) ++set(in index:int, in element:short) : short ++size() : int ++toArray() : short ++toArray(in a[]:short) : short + + + + + + + IntegerField + + + +get() : int ++set(in value:int) ++set(in value:int, in data[]:byte) + + + + + + + StringUtil + + + +getFromUnicode(in string[]:byte, in offset:int, in len:int) : String ++getFromUnicode(in string[]:byte) : String + + + + sourcePortFig="Fig2.0" + destPortFig="Fig0.0" + sourceFigNode="Fig2" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig10.0" + destPortFig="Fig0.0" + sourceFigNode="Fig10" + destFigNode="Fig0" + + + + + + + + + + + + sourcePortFig="Fig7.0" + destPortFig="Fig0.0" + sourceFigNode="Fig7" + destFigNode="Fig0" + + + + + + + + + + + sourcePortFig="Fig8.0" + destPortFig="Fig0.0" + sourceFigNode="Fig8" + destFigNode="Fig0" + + + + + + + + + diff --git a/src/models/writeFilesystemSequenceDiagram.pgml b/src/models/writeFilesystemSequenceDiagram.pgml new file mode 100755 index 000000000..d21bef7b3 --- /dev/null +++ b/src/models/writeFilesystemSequenceDiagram.pgml @@ -0,0 +1,1874 @@ + + + + + + + + + : ClientApps + + + + + + + + + + + + + + + + enclosingFig="Fig1" + + + + : POIFileSystem + + + + + + + + + + + + + + + + + + + + + + + enclosingFig="Fig2" + + + + : HeaderBlock + + + + + + + + + + + + + + + + + enclosingFig="Fig3" + + + + : Block + + + + + + + + + + + + + + + enclosingFig="Fig4" + + + + : BAT + + + + + + + + + + + + + + + + + + enclosingFig="Fig5" + + + + : BATBlock + + + + + + + + + + + + + + + + + + : PropertyTable + + + + + + + + + + + + + + + + + + enclosingFig="Fig7" + + + + : PropertyTableBlock + + + + + + + + + + + + + + + + enclosingFig="Fig8" + + + + : Property + + + + + + + + + + + + + + + enclosingFig="Fig9" + + + + OutputStream : Object + + + + + + + + + + + + + + + + : createFileSystem + + + + + : createHeaderBlock + + + + + : createBlock [until all files have blocks] + + + + + : create a record [until all files have records] + + + + + : create bat block [if need more] + + + + + : create a record [until all files have records] + + + + + : get the bat array info + + + + + : get the extended bat array info + + + + + : set the bat info + + + + + : set the extended bat info + + + + + : create a block [if needed] + + + + + : create a property + + + + + : add the propert to the block + + + + + : write all blocks to stream + + + + sourcePortFig="Fig0.7" + destPortFig="Fig1.7" + sourceFigNode="Fig0" + destFigNode="Fig1" + + + + + + + + + + + sourcePortFig="Fig1.8" + destPortFig="Fig2.7" + sourceFigNode="Fig1" + destFigNode="Fig2" + + + + + + + + + + + sourcePortFig="Fig1.9" + destPortFig="Fig3.7" + sourceFigNode="Fig1" + destFigNode="Fig3" + + + + + + + + + + + sourcePortFig="Fig1.10" + destPortFig="Fig4.7" + sourceFigNode="Fig1" + destFigNode="Fig4" + + + + + + + + + + + sourcePortFig="Fig4.8" + destPortFig="Fig5.7" + sourceFigNode="Fig4" + destFigNode="Fig5" + + + + + + + + + + + sourcePortFig="Fig1.11" + destPortFig="Fig6.7" + sourceFigNode="Fig1" + destFigNode="Fig6" + + + + + + + + + + + sourcePortFig="Fig1.12" + destPortFig="Fig4.9" + sourceFigNode="Fig1" + destFigNode="Fig4" + + + + + + + + + + + sourcePortFig="Fig1.13" + destPortFig="Fig4.10" + sourceFigNode="Fig1" + destFigNode="Fig4" + + + + + + + + + + + sourcePortFig="Fig1.14" + destPortFig="Fig2.8" + sourceFigNode="Fig1" + destFigNode="Fig2" + + + + + + + + + + + sourcePortFig="Fig1.15" + destPortFig="Fig2.9" + sourceFigNode="Fig1" + destFigNode="Fig2" + + + + + + + + + + + sourcePortFig="Fig6.8" + destPortFig="Fig7.7" + sourceFigNode="Fig6" + destFigNode="Fig7" + + + + + + + + + + + sourcePortFig="Fig6.9" + destPortFig="Fig8.7" + sourceFigNode="Fig6" + destFigNode="Fig8" + + + + + + + + + + + sourcePortFig="Fig6.10" + destPortFig="Fig7.8" + sourceFigNode="Fig6" + destFigNode="Fig7" + + + + + + + + + + + sourcePortFig="Fig0.8" + destPortFig="Fig9.7" + sourceFigNode="Fig0" + destFigNode="Fig9" + + + + + + + + + diff --git a/src/resources/entities/CatalogManager.properties b/src/resources/entities/CatalogManager.properties new file mode 100755 index 000000000..5fb94de4a --- /dev/null +++ b/src/resources/entities/CatalogManager.properties @@ -0,0 +1,50 @@ +# CatalogManager.properties +# +# This is the default properties file for Apache Cocoon. This facilitates local +# configuration of application-specific catalogs. You can also use cocoon.xconf +# to over-ride or supplement these settings. +# +# Apache Cocoon will automatically load a default catalog from +# webapps/cocoon/resources/entities/catalog +# +# See the documentation (catalog.html). + +# verbosity ... level of messages for status/debug (messages go to STDOUT) +# The following messages are provided ... +# 0 = none +# 1 = ? +# 2 = 1+, Loading catalog, Resolved public, Resolved system +# 3 = 2+, Catalog does not exist, resolvePublic, resolveSystem +# 10 = 3+, List all catalog entries when loading a catalog +# (Cocoon also logs the "Resolved public" messages.) +# TODO: determine all messages at each level +# +verbosity=1 + +# catalogs ... list of additional catalogs to load +# use full pathnames +# pathname separator is always semi-colon (;) regardless of operating system +# directory separator is always slash (/) regardless of operating system +# +#catalogs=/path/to/local/catalog +catalogs= + +# prefer ... we prefer to use Public Identifiers for entity resolution +# +prefer=public + +# static-catalog ... see the Sun doco +# TODO: ? what impact does this setting have for Apache Cocoon +# +static-catalog=yes + +# allow-oasis-xml-catalog-pi ... see the Sun doco +# TODO: ? what impact does this setting have for Apache Cocoon +# +allow-oasis-xml-catalog-pi=yes + +# catalog-class-name ... specify an alternate class name to use +# Apache Cocoon does not need this setting - we already have a named class +# +# catalog-class-name=com.sun.resolver.Resolver + diff --git a/src/resources/entities/ISOdia.pen b/src/resources/entities/ISOdia.pen new file mode 100755 index 000000000..df5c05d2e --- /dev/null +++ b/src/resources/entities/ISOdia.pen @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/resources/entities/ISOgrk1.pen b/src/resources/entities/ISOgrk1.pen new file mode 100755 index 000000000..cdab380fc --- /dev/null +++ b/src/resources/entities/ISOgrk1.pen @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/resources/entities/ISOlat1.pen b/src/resources/entities/ISOlat1.pen new file mode 100755 index 000000000..82e5a7a6c --- /dev/null +++ b/src/resources/entities/ISOlat1.pen @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/resources/entities/ISOnum.pen b/src/resources/entities/ISOnum.pen new file mode 100755 index 000000000..02605bfb5 --- /dev/null +++ b/src/resources/entities/ISOnum.pen @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/resources/entities/ISOpub.pen b/src/resources/entities/ISOpub.pen new file mode 100755 index 000000000..04a5732b4 --- /dev/null +++ b/src/resources/entities/ISOpub.pen @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/resources/entities/ISOtech.pen b/src/resources/entities/ISOtech.pen new file mode 100755 index 000000000..b3b39f9f1 --- /dev/null +++ b/src/resources/entities/ISOtech.pen @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/resources/entities/README b/src/resources/entities/README new file mode 100755 index 000000000..5473cec24 --- /dev/null +++ b/src/resources/entities/README @@ -0,0 +1,5 @@ +See Apache Cocoon documentation +"Entity resolution with catalogs" (catalog.html) + +Note: You must move the CatalogManager.properties file to +some filesystem location that is accessible to your classpath. diff --git a/src/resources/entities/XMLSchema.dtd b/src/resources/entities/XMLSchema.dtd new file mode 100755 index 000000000..aa3564caa --- /dev/null +++ b/src/resources/entities/XMLSchema.dtd @@ -0,0 +1,395 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +%xs-datatypes; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/resources/entities/book-cocoon-v10.dtd b/src/resources/entities/book-cocoon-v10.dtd new file mode 100755 index 000000000..77652f8ce --- /dev/null +++ b/src/resources/entities/book-cocoon-v10.dtd @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + diff --git a/src/resources/entities/catalog b/src/resources/entities/catalog new file mode 100755 index 000000000..4ebdde7b9 --- /dev/null +++ b/src/resources/entities/catalog @@ -0,0 +1,67 @@ +-- this is the default OASIS catalog for Apache Cocoon -- + +OVERRIDE YES + +-- ISO public identifiers for sets of character entities -- +PUBLIC "ISO 8879-1986//ENTITIES Added Latin 1//EN//XML" + "ISOlat1.pen" +PUBLIC "ISO 8879:1986//ENTITIES Added Latin 1//EN//XML" + "ISOlat1.pen" +PUBLIC "ISO 9573-15:1993//ENTITIES Greek Letters//EN//XML" + "ISOgrk1.pen" +PUBLIC "ISO 8879:1986//ENTITIES Publishing//EN//XML" + "ISOpub.pen" +PUBLIC "ISO 8879:1986//ENTITIES General Technical//EN//XML" + "ISOtech.pen" +PUBLIC "ISO 8879:1986//ENTITIES Numeric and Special Graphic//EN//XML" + "ISOnum.pen" + +-- Document Type Definitions -- +PUBLIC "-//APACHE//DTD Documentation V1.0//EN" + "document-v10.dtd" +PUBLIC "-//APACHE//DTD Changes V1.0//EN" + "changes-v10.dtd" +PUBLIC "-//APACHE//DTD FAQ V1.0//EN" + "faq-v10.dtd" +PUBLIC "-//APACHE//DTD JavaDoc V1.0//EN" + "javadoc-v04draft.dtd" +PUBLIC "-//APACHE//DTD Specification V1.0//EN" + "specification-v10.dtd" +PUBLIC "-//APACHE//DTD Todo V1.0//EN" + "todo-v10.dtd" +PUBLIC "-//APACHE//DTD Cocoon Sitemap V0.2//EN" + "sitemap-v02.dtd" + +-- enabling validation during Cocoon's own "build docs" -- +-- all *.xml require DTD for validation during "build docs" -- +PUBLIC "-//APACHE//DTD Cocoon Documentation Book V1.0//EN" + "book-cocoon-v10.dtd" + +-- Cocoon has extra