]> source.dussan.org Git - poi.git/commitdiff
Created ChartSubstreamRecordAggregate to manage chart sub-streams. Not fully incorpo...
authorJosh Micich <josh@apache.org>
Sun, 10 May 2009 23:54:29 +0000 (23:54 +0000)
committerJosh Micich <josh@apache.org>
Sun, 10 May 2009 23:54:29 +0000 (23:54 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@773434 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/model/Sheet.java
src/java/org/apache/poi/hssf/record/EscherAggregate.java
src/java/org/apache/poi/hssf/record/UnknownRecord.java
src/java/org/apache/poi/hssf/record/aggregates/ChartSubstreamRecordAggregate.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java

index 948b5befcbe489fcb8c90db63e84ab5123665020..78f7187ea2c830904bedfd8663c4e44bdb185481 100644 (file)
@@ -50,7 +50,6 @@ import org.apache.poi.hssf.record.PrintHeadersRecord;
 import org.apache.poi.hssf.record.ProtectRecord;
 import org.apache.poi.hssf.record.Record;
 import org.apache.poi.hssf.record.RecordBase;
-import org.apache.poi.hssf.record.RecordFormatException;
 import org.apache.poi.hssf.record.RefModeRecord;
 import org.apache.poi.hssf.record.RowRecord;
 import org.apache.poi.hssf.record.SCLRecord;
@@ -61,6 +60,7 @@ import org.apache.poi.hssf.record.UncalcedRecord;
 import org.apache.poi.hssf.record.UnknownRecord;
 import org.apache.poi.hssf.record.WSBoolRecord;
 import org.apache.poi.hssf.record.WindowTwoRecord;
+import org.apache.poi.hssf.record.aggregates.ChartSubstreamRecordAggregate;
 import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
 import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
 import org.apache.poi.hssf.record.aggregates.DataValidityTable;
@@ -71,8 +71,8 @@ import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
 import org.apache.poi.hssf.record.aggregates.RecordAggregate.PositionTrackingVisitor;
 import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
 import org.apache.poi.hssf.record.formula.FormulaShifter;
-import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.hssf.util.PaneInformation;
+import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
 
@@ -165,19 +165,16 @@ public final class Sheet implements Model {
         RowRecordsAggregate rra = null;
 
         records            = new ArrayList<RecordBase>(128);
-        // TODO - take chart streams off into separate java objects
-        int       bofEofNestingLevel = 1;  // nesting level can only get to 2 (when charts are present)
         int dimsloc = -1;
 
-        if (rs.peekNextSid() == BOFRecord.sid) {
-            BOFRecord bof = (BOFRecord) rs.getNext();
-            if (bof.getType() != BOFRecord.TYPE_WORKSHEET) {
-                // TODO - fix junit tests throw new RuntimeException("Bad BOF record type");
-            }
-            records.add(bof);
-        } else {
+        if (rs.peekNextSid() != BOFRecord.sid) {
             throw new RuntimeException("BOF record expected");
         }
+        BOFRecord bof = (BOFRecord) rs.getNext();
+        if (bof.getType() != BOFRecord.TYPE_WORKSHEET) {
+            // TODO - fix junit tests throw new RuntimeException("Bad BOF record type");
+        }
+        records.add(bof);
         while (rs.hasNext()) {
             int recSid = rs.peekNextSid();
 
@@ -198,7 +195,7 @@ public final class Sheet implements Model {
                 continue;
             }
 
-            if (RecordOrderer.isRowBlockRecord(recSid) && bofEofNestingLevel == 1 ) {
+            if (RecordOrderer.isRowBlockRecord(recSid)) {
                 //only add the aggregate once
                 if (rra != null) {
                     throw new RuntimeException("row/cell records found in the wrong place");
@@ -218,13 +215,7 @@ public final class Sheet implements Model {
                     records.add(psb);
                     continue;
                 }
-                if (bofEofNestingLevel == 2) {
-                    psb = new PageSettingsBlock(rs);
-                    // It's normal for a chart to have its own PageSettingsBlock
-                    // Fall through and add psb here, because chart records
-                    // are stored loose among the sheet records.
-                    // this latest psb does not clash with _psBlock
-                } else if (windowTwo != null) {
+                if (windowTwo != null) {
                     // probably 'Custom View Settings' sub-stream which is found between
                     // USERSVIEWBEGIN(01AA) and USERSVIEWEND(01AB)
                     // TODO - create UsersViewAggregate to hold these sub-streams, and simplify this code a bit
@@ -262,6 +253,17 @@ public final class Sheet implements Model {
                 _mergedCellsTable.read(rs);
                 continue;
             }
+            
+            if (recSid == BOFRecord.sid) {
+                ChartSubstreamRecordAggregate chartAgg = new ChartSubstreamRecordAggregate(rs);
+                if (false) {
+                    // TODO - would like to keep the chart aggregate packed, but one unit test needs attention
+                    records.add(chartAgg);
+                } else {
+                    spillAggregate(chartAgg, records);
+                }
+                continue;
+            }
 
             Record rec = rs.getNext();
             if ( recSid == IndexRecord.sid ) {
@@ -277,28 +279,12 @@ public final class Sheet implements Model {
                 continue;
             }
 
-            if (recSid == BOFRecord.sid)
-            {
-                bofEofNestingLevel++;
-                if (log.check( POILogger.DEBUG ))
-                    log.log(POILogger.DEBUG, "Hit BOF record. Nesting increased to " + bofEofNestingLevel);
-                BOFRecord bof = (BOFRecord)rec;
-                // TODO - extract chart sub-stream into record aggregate
-                if (bof.getType() != BOFRecord.TYPE_CHART) {
-                    throw new RecordFormatException("Bad BOF record type: " + bof.getType());
-                }
-            }
-            else if (recSid == EOFRecord.sid)
-            {
-                --bofEofNestingLevel;
-                if (log.check( POILogger.DEBUG ))
-                    log.log(POILogger.DEBUG, "Hit EOF record. Nesting decreased to " + bofEofNestingLevel);
-                if (bofEofNestingLevel == 0) {
-                    records.add(rec);
-                    break;
-                }
+            if (recSid == EOFRecord.sid) {
+                records.add(rec);
+                break;
             }
-            else if (recSid == DimensionsRecord.sid)
+
+            if (recSid == DimensionsRecord.sid)
             {
                 // Make a columns aggregate if one hasn't ready been created.
                 if (_columnInfos == null)
@@ -386,6 +372,12 @@ public final class Sheet implements Model {
         if (log.check( POILogger.DEBUG ))
             log.log(POILogger.DEBUG, "sheet createSheet (existing file) exited");
     }
+    private static void spillAggregate(RecordAggregate ra, final List<RecordBase> recs) {
+        ra.visitContainedRecords(new RecordVisitor() {
+            public void visitRecord(Record r) {
+                recs.add(r);
+            }});
+    }
     /**
      * Hack to recover from the situation where the page settings block has been split by
      * an intervening {@link WSBoolRecord}
index e96de6ec72cce6bc18842becb9ba07015ae67a4f..1c202f84707aca8358f0f13074ec7b042a68741e 100644 (file)
@@ -43,6 +43,7 @@ import org.apache.poi.hssf.model.CommentShape;
 import org.apache.poi.hssf.model.ConvertAnchor;
 import org.apache.poi.hssf.model.DrawingManager2;
 import org.apache.poi.hssf.model.TextboxShape;
+import org.apache.poi.hssf.record.aggregates.RecordAggregate;
 import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
 import org.apache.poi.hssf.usermodel.HSSFPatriarch;
 import org.apache.poi.hssf.usermodel.HSSFShape;
@@ -884,7 +885,11 @@ public final class EscherAggregate extends AbstractEscherHolderRecord {
 
        private static short sid( List records, int loc )
        {
-               return ( (Record) records.get( loc ) ).getSid();
+               Object obj = records.get( loc );
+               if (obj instanceof RecordAggregate) {
+                       return -1;
+               }
+               return ( (Record) obj ).getSid();
        }
 
 
index 0a7209332523d3da7c94b248e99c090122194e96..5b6faf315813b645c211f946110be007cff73f3c 100644 (file)
@@ -17,6 +17,7 @@
 
 package org.apache.poi.hssf.record;
 
+import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;
 import org.apache.poi.util.HexDump;
 import org.apache.poi.util.LittleEndianOutput;
 
@@ -35,6 +36,12 @@ public final class UnknownRecord extends StandardRecord {
        /*
         * Some Record IDs used by POI as 'milestones' in the record stream
         */
+       /**
+        * seems to be part of the {@link PageSettingsBlock}. Not interpreted by POI.
+        * The name 'PRINTSIZE' was taken from OOO source.<br/>
+        * The few POI test samples with this record have data { 0x03, 0x00 }.
+        */
+       public static final int PRINTSIZE_0033       = 0x0033;
        public static final int PLS_004D             = 0x004D;
        public static final int SHEETPR_0081         = 0x0081;
        public static final int STANDARDWIDTH_0099   = 0x0099;
@@ -123,6 +130,7 @@ public final class UnknownRecord extends StandardRecord {
                // Make sure you delete the corresponding entry from 
                // this method any time a new Record subclass is created.
                switch (sid) {
+                       case PRINTSIZE_0033: return "PRINTSIZE";
                        case PLS_004D: return "PLS";
                        case 0x0050: return "DCON"; // Data Consolidation Information
                        case 0x007F: return "IMDATA";
diff --git a/src/java/org/apache/poi/hssf/record/aggregates/ChartSubstreamRecordAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/ChartSubstreamRecordAggregate.java
new file mode 100644 (file)
index 0000000..bb13517
--- /dev/null
@@ -0,0 +1,81 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.hssf.record.aggregates;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.apache.poi.hssf.model.RecordStream;\r
+import org.apache.poi.hssf.record.BOFRecord;\r
+import org.apache.poi.hssf.record.EOFRecord;\r
+import org.apache.poi.hssf.record.Record;\r
+import org.apache.poi.hssf.record.RecordBase;\r
+\r
+/**\r
+ * Manages the all the records associated with a chart sub-stream.<br/>\r
+ * Includes the initial {@link BOFRecord} and final {@link EOFRecord}.\r
+ * \r
+ * @author Josh Micich\r
+ */\r
+public final class ChartSubstreamRecordAggregate extends RecordAggregate {\r
+\r
+       private final BOFRecord _bofRec;\r
+       /**\r
+        * All the records between BOF and EOF\r
+        */\r
+       private final List<RecordBase> _recs;\r
+       private PageSettingsBlock _psBlock;\r
+\r
+       public ChartSubstreamRecordAggregate(RecordStream rs) {\r
+               _bofRec = (BOFRecord) rs.getNext();\r
+               List<RecordBase> temp = new ArrayList<RecordBase>();\r
+               while (rs.peekNextClass() != EOFRecord.class) {\r
+                       if (PageSettingsBlock.isComponentRecord(rs.peekNextSid())) {\r
+                               if (_psBlock != null) {\r
+                                       throw new IllegalStateException(\r
+                                                       "Found more than one PageSettingsBlock in chart sub-stream");\r
+                               }\r
+                               _psBlock = new PageSettingsBlock(rs);\r
+                               temp.add(_psBlock);\r
+                               continue;\r
+                       }\r
+                       temp.add(rs.getNext());\r
+               }\r
+               _recs = temp;\r
+               Record eof = rs.getNext(); // no need to save EOF in field\r
+               if (!(eof instanceof EOFRecord)) {\r
+                       throw new IllegalStateException("Bad chart EOF");\r
+               }\r
+       }\r
+\r
+       public void visitContainedRecords(RecordVisitor rv) {\r
+               if (_recs.isEmpty()) {\r
+                       return;\r
+               }\r
+               rv.visitRecord(_bofRec);\r
+               for (int i = 0; i < _recs.size(); i++) {\r
+                       RecordBase rb = _recs.get(i);\r
+                       if (rb instanceof RecordAggregate) {\r
+                               ((RecordAggregate) rb).visitContainedRecords(rv);\r
+                       } else {\r
+                               rv.visitRecord((Record) rb);\r
+                       }\r
+               }\r
+               rv.visitRecord(EOFRecord.instance);\r
+       }\r
+}\r
index 1731a1c3a1af8a726ac80f60642f9ba72bcc4def..f906c7a9986a4a65f8cfc5a7d85654f7173e438b 100644 (file)
@@ -70,9 +70,10 @@ public final class PageSettingsBlock extends RecordAggregate {
         * include any trailing {@link ContinueRecord}s.
         */
        private List<ContinueRecord> _plsContinues;
-       private PrintSetupRecord printSetup;
+       private PrintSetupRecord _printSetup;
        private Record _bitmap;
        private Record _headerFooter;
+       private Record _printSize;
 
        public PageSettingsBlock(RecordStream rs) {
                while(true) {
@@ -92,7 +93,7 @@ public final class PageSettingsBlock extends RecordAggregate {
                _footer = new FooterRecord("");
                _hCenter = createHCenter();
                _vCenter = createVCenter();
-               printSetup = createPrintSetup();
+               _printSetup = createPrintSetup();
        }
 
        /**
@@ -114,6 +115,7 @@ public final class PageSettingsBlock extends RecordAggregate {
                        case UnknownRecord.PLS_004D:
                        case PrintSetupRecord.sid:
                        case UnknownRecord.BITMAP_00E9:
+                       case UnknownRecord.PRINTSIZE_0033: 
                        case UnknownRecord.HEADER_FOOTER_089C: // extra header/footer settings supported by Excel 2007 
                                return true;
                }
@@ -162,11 +164,14 @@ public final class PageSettingsBlock extends RecordAggregate {
                                }
                                break;
                        case PrintSetupRecord.sid:
-                               printSetup = (PrintSetupRecord)rs.getNext();
+                               _printSetup = (PrintSetupRecord)rs.getNext();
                                break;
                        case UnknownRecord.BITMAP_00E9:
                                _bitmap = rs.getNext();
                                break;
+                       case UnknownRecord.PRINTSIZE_0033:
+                               _printSize = rs.getNext();
+                               break;
                        case UnknownRecord.HEADER_FOOTER_089C:
                                _headerFooter = rs.getNext();
                                break;
@@ -228,8 +233,9 @@ public final class PageSettingsBlock extends RecordAggregate {
                                visitIfPresent(cr, rv);
                        }
                }
-               visitIfPresent(printSetup, rv);
+               visitIfPresent(_printSetup, rv);
                visitIfPresent(_bitmap, rv);
+               visitIfPresent(_printSize, rv);
                visitIfPresent(_headerFooter, rv);
        }
        private static void visitIfPresent(Record r, RecordVisitor rv) {
@@ -333,7 +339,7 @@ public final class PageSettingsBlock extends RecordAggregate {
         */
        public PrintSetupRecord getPrintSetup ()
        {
-               return printSetup;
+               return _printSetup;
        }
 
        /**
@@ -342,7 +348,7 @@ public final class PageSettingsBlock extends RecordAggregate {
         */
        public void setPrintSetup (PrintSetupRecord newPrintSetup)
        {
-               printSetup = newPrintSetup;
+               _printSetup = newPrintSetup;
        }