]> source.dussan.org Git - poi.git/commitdiff
More work on FeatRecord/Shared Features. More is still needed though, it's still WIP
authorNick Burch <nick@apache.org>
Sat, 26 Dec 2009 19:57:09 +0000 (19:57 +0000)
committerNick Burch <nick@apache.org>
Sat, 26 Dec 2009 19:57:09 +0000 (19:57 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@894018 13f79535-47bb-0310-9956-ffa450edef68

13 files changed:
src/java/org/apache/poi/hssf/dev/BiffViewer.java
src/java/org/apache/poi/hssf/model/RecordOrderer.java
src/java/org/apache/poi/hssf/record/FeatHdrRecord.java
src/java/org/apache/poi/hssf/record/FeatRecord.java
src/java/org/apache/poi/hssf/record/RecordFactory.java
src/java/org/apache/poi/hssf/record/RecordInputStream.java
src/java/org/apache/poi/hssf/record/UnknownRecord.java
src/java/org/apache/poi/hssf/record/common/FtrHeader.java [new file with mode: 0644]
src/testcases/org/apache/poi/hssf/eventusermodel/TestHSSFEventFactory.java
src/testcases/org/apache/poi/hssf/record/TestFeatRecord.java [new file with mode: 0644]
src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java [new file with mode: 0644]
test-data/spreadsheet/46136-NoWarnings.xls [new file with mode: 0644]
test-data/spreadsheet/46136-WithWarnings.xls [new file with mode: 0644]

index 66223b227497cbbc0f14c9ba93639a7b26a4c681..aed5c199e43d7a50f9fcd80e94213ae3eba3faa7 100644 (file)
@@ -162,6 +162,8 @@ public final class BiffViewer {
                        case ExtSSTRecord.sid:         return new ExtSSTRecord(in);
                        case ExtendedFormatRecord.sid: return new ExtendedFormatRecord(in);
                        case ExternSheetRecord.sid:    return new ExternSheetRecord(in);
+                       case FeatRecord.sid:           return new FeatRecord(in);
+                       case FeatHdrRecord.sid:        return new FeatHdrRecord(in);
                        case FilePassRecord.sid:       return new FilePassRecord(in);
                        case FileSharingRecord.sid:    return new FileSharingRecord(in);
                        case FnGroupCountRecord.sid:   return new FnGroupCountRecord(in);
index 5740f209259963a79e8fb4a49109ce08f21f896e..31c25db8502780fe8c0d1597f0410fb1997fb10b 100644 (file)
@@ -34,6 +34,7 @@ import org.apache.poi.hssf.record.DimensionsRecord;
 import org.apache.poi.hssf.record.DrawingRecord;
 import org.apache.poi.hssf.record.DrawingSelectionRecord;
 import org.apache.poi.hssf.record.EOFRecord;
+import org.apache.poi.hssf.record.FeatRecord;
 import org.apache.poi.hssf.record.FormulaRecord;
 import org.apache.poi.hssf.record.GridsetRecord;
 import org.apache.poi.hssf.record.GutsRecord;
@@ -341,7 +342,7 @@ final class RecordOrderer {
                switch(sid) {
                        case UnknownRecord.SHEETEXT_0862:
                        case UnknownRecord.SHEETPROTECTION_0867:
-                       case UnknownRecord.RANGEPROTECTION_0868:
+                       case FeatRecord.sid:
                        case EOFRecord.sid:
                                return true;
                }
index fcc5cd5c00312849e6bf52d7d1d7e8b6c5389172..fe7a137eb6cdfefe73ab51739fd4d42eb3259bf9 100644 (file)
@@ -17,6 +17,7 @@
 
 package org.apache.poi.hssf.record;
 
+import org.apache.poi.hssf.record.common.FtrHeader;
 import org.apache.poi.util.LittleEndianOutput;
 
 /**
@@ -51,7 +52,8 @@ public final class FeatHdrRecord extends StandardRecord  {
 
        
        public final static short sid = 0x0867;
-       
+
+       private FtrHeader futureHeader;
        private int isf_sharedFeatureType; // See SHAREDFEATURES_
        private byte reserved; // Should always be one
        /** 
@@ -63,6 +65,8 @@ public final class FeatHdrRecord extends StandardRecord  {
        private byte[] rgbHdrData;
 
        public FeatHdrRecord() {
+               futureHeader = new FtrHeader();
+               futureHeader.setRecordType(sid);
        }
 
        public short getSid() {
@@ -70,9 +74,11 @@ public final class FeatHdrRecord extends StandardRecord  {
        }
 
        public FeatHdrRecord(RecordInputStream in) {
+               futureHeader = new FtrHeader(in);
+               
                isf_sharedFeatureType = in.readShort();
                reserved = in.readByte();
-               cbHdrData = in.readLong();
+               cbHdrData = in.readInt();
                // Don't process this just yet, need the BOFRecord
                rgbHdrData = in.readRemainder();
        }
@@ -88,13 +94,15 @@ public final class FeatHdrRecord extends StandardRecord  {
        }
 
        public void serialize(LittleEndianOutput out) {
+               futureHeader.serialize(out);
+               
                out.writeShort(isf_sharedFeatureType);
                out.writeByte(reserved);
-               out.writeLong(cbHdrData);
+               out.writeInt((int)cbHdrData);
                out.write(rgbHdrData);
        }
 
        protected int getDataSize() {
-               return 2+1+4+rgbHdrData.length;
+               return 12 + 2+1+4+rgbHdrData.length;
        }
 }
index 6e2f4d6432374ecd7b6f4d9d759ba7dc9c89baf8..a772ca54887560143c6480028bfd18fd31dc6f61 100644 (file)
@@ -17,6 +17,7 @@
 
 package org.apache.poi.hssf.record;
 
+import org.apache.poi.hssf.record.common.FtrHeader;
 import org.apache.poi.hssf.record.common.Ref8U;
 import org.apache.poi.util.LittleEndianOutput;
 
@@ -29,14 +30,14 @@ import org.apache.poi.util.LittleEndianOutput;
 public final class FeatRecord extends StandardRecord  {
        public final static short sid = 0x0868;
        
+       private FtrHeader futureHeader;
+       
        /**
         * See SHAREDFEATURES_* on {@link FeatHdrRecord}
         */
        private int isf_sharedFeatureType; 
        private byte reserved1; // Should always be zero
        private long reserved2; // Should always be zero
-       /** The number of refs */
-       private int cref;
        /** Only matters if type is ISFFEC2 */
        private long cbFeatData;
        private int reserved3; // Should always be zero
@@ -45,6 +46,8 @@ public final class FeatRecord extends StandardRecord  {
        private byte[] rgbFeat; 
        
        public FeatRecord() {
+               futureHeader = new FtrHeader();
+               futureHeader.setRecordType(sid);
        }
 
        public short getSid() {
@@ -52,11 +55,13 @@ public final class FeatRecord extends StandardRecord  {
        }
 
        public FeatRecord(RecordInputStream in) {
+               futureHeader = new FtrHeader(in);
+               
                isf_sharedFeatureType = in.readShort();
                reserved1 = in.readByte();
-               reserved2 = in.readLong();
-               cref = in.readUShort();
-               cbFeatData = in.readLong();
+               reserved2 = in.readInt();
+               int cref = in.readUShort();
+               cbFeatData = in.readInt();
                reserved3 = in.readShort();
 
                cellRefs = new Ref8U[cref];
@@ -69,7 +74,7 @@ public final class FeatRecord extends StandardRecord  {
 
        public String toString() {
                StringBuffer buffer = new StringBuffer();
-               buffer.append("[SHARDED FEATURE]\n");
+               buffer.append("[SHARED FEATURE]\n");
                
                // TODO ...
                
@@ -78,13 +83,23 @@ public final class FeatRecord extends StandardRecord  {
        }
 
        public void serialize(LittleEndianOutput out) {
+               futureHeader.serialize(out);
+               
                out.writeShort(isf_sharedFeatureType);
+               out.writeByte(reserved1);
+               out.writeInt((int)reserved2);
+               out.writeShort(cellRefs.length);
+               out.writeInt((int)cbFeatData);
+               out.writeShort(reserved3);
                
-               // TODO ...
+               for(int i=0; i<cellRefs.length; i++) {
+                       cellRefs[i].serialize(out);
+               }
                
+               out.write(rgbFeat);
        }
 
        protected int getDataSize() {
-               return -1; // TODO
+               return 12 + 2+1+4+2+4+2+Ref8U.getDataSize()+rgbFeat.length;
        }
 }
index 6937c7dbe88bb38d84d65be51e3ca933fe8d1b0d..da4a065f9b8b7c9092b528f5663ed5370f9d9574 100644 (file)
@@ -143,6 +143,8 @@ public final class RecordFactory {
                ExternalNameRecord.class,
                ExternSheetRecord.class,
                ExtSSTRecord.class,
+               FeatRecord.class,
+               FeatHdrRecord.class,
                FilePassRecord.class,
                FileSharingRecord.class,
                FnGroupCountRecord.class,
index 0997232fb20b5c8a7c8f09cfc729d9ffd86ce283..7333e39c789b056ac93a886784fabce1356c56fc 100644 (file)
@@ -234,12 +234,18 @@ public final class RecordInputStream implements LittleEndianInput {
                return _dataInput.readShort();
        }
 
+       /**
+        * Reads a 32 bit, signed value 
+        */
        public int readInt() {
                checkRecordPosition(LittleEndian.INT_SIZE);
                _currentDataOffset += LittleEndian.INT_SIZE;
                return _dataInput.readInt();
        }
 
+       /**
+        * Reads a 64 bit, signed value
+        */
        public long readLong() {
                checkRecordPosition(LittleEndian.LONG_SIZE);
                _currentDataOffset += LittleEndian.LONG_SIZE;
index 1351b7be59be0dc98fd6645f857109a5c88fb57f..7056cb2c31a1107e4ad16786a1d99eee513683be 100644 (file)
@@ -56,7 +56,6 @@ public final class UnknownRecord extends StandardRecord {
        public static final int QUICKTIP_0800        = 0x0800;
        public static final int SHEETEXT_0862        = 0x0862; // OOO calls this SHEETLAYOUT
        public static final int SHEETPROTECTION_0867 = 0x0867;
-       public static final int RANGEPROTECTION_0868 = 0x0868;
        public static final int HEADER_FOOTER_089C   = 0x089C;
 
        private int _sid;
@@ -173,7 +172,6 @@ public final class UnknownRecord extends StandardRecord {
                        case 0x0863: return "BOOKEXT";
                        case 0x0864: return "SXADDL";    // Pivot Table Additional Info
                        case SHEETPROTECTION_0867: return "SHEETPROTECTION";
-                       case RANGEPROTECTION_0868: return "RANGEPROTECTION";
                        case 0x086B: return "DATALABEXTCONTENTS";
                        case 0x086C: return "CELLWATCH";
                        case 0x0874: return "DROPDOWNOBJIDS";
diff --git a/src/java/org/apache/poi/hssf/record/common/FtrHeader.java b/src/java/org/apache/poi/hssf/record/common/FtrHeader.java
new file mode 100644 (file)
index 0000000..dc2d4e2
--- /dev/null
@@ -0,0 +1,89 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record.common;
+
+import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.util.LittleEndianOutput;
+
+/**
+ * Title: FtrHeader (Future Record Header) common record part
+ * <P>
+ * This record part specifies a header for a Ftr (Future)
+ *  style record, which includes extra attributes above and
+ *  beyond those of a traditional record. 
+ */
+public final class FtrHeader {
+       /** This MUST match the type on the containing record */
+       private short recordType;
+       /** This is a FrtFlags */
+       private short grbitFrt;
+       /** MUST be 8 bytes and all zero */
+       private byte[] reserved;
+
+       public FtrHeader() {
+               reserved = new byte[8];
+       }
+
+       public FtrHeader(RecordInputStream in) {
+               recordType = in.readShort();
+               grbitFrt   = in.readShort();
+               
+               reserved = new byte[8];
+               in.read(reserved, 0, 8);
+       }
+
+       public String toString() {
+               StringBuffer buffer = new StringBuffer();
+               buffer.append(" [FUTURE HEADER]\n");
+               buffer.append("   Type " + recordType);
+               buffer.append("   Flags " + grbitFrt);
+               buffer.append(" [/FUTURE HEADER]\n");
+               return buffer.toString();
+       }
+
+       public void serialize(LittleEndianOutput out) {
+               out.writeShort(recordType);
+               out.writeShort(grbitFrt);
+               out.write(reserved);
+       }
+
+       public static int getDataSize() {
+               return 12;
+       }
+
+       public short getRecordType() {
+               return recordType;
+       }
+       public void setRecordType(short recordType) {
+               this.recordType = recordType;
+       }
+
+       public short getGrbitFrt() {
+               return grbitFrt;
+       }
+       public void setGrbitFrt(short grbitFrt) {
+               this.grbitFrt = grbitFrt;
+       }
+
+       public byte[] getReserved() {
+               return reserved;
+       }
+       public void setReserved(byte[] reserved) {
+               this.reserved = reserved;
+       }
+}
\ No newline at end of file
index 74e1ceb4a5bad217739177d4e102322062eadf59..97663310850e25d562aebd5cb3ca08bd49a1ed11 100644 (file)
@@ -27,6 +27,7 @@ import org.apache.poi.hssf.record.ContinueRecord;
 import org.apache.poi.hssf.record.DVALRecord;
 import org.apache.poi.hssf.record.DVRecord;
 import org.apache.poi.hssf.record.EOFRecord;
+import org.apache.poi.hssf.record.FeatHdrRecord;
 import org.apache.poi.hssf.record.Record;
 import org.apache.poi.hssf.record.SelectionRecord;
 import org.apache.poi.hssf.record.WindowTwoRecord;
@@ -86,9 +87,10 @@ public final class TestHSSFEventFactory extends TestCase {
                // Check that the last few records are as we expect
                // (Makes sure we don't accidently skip the end ones)
                int numRec = recs.length;
-               assertEquals(DVALRecord.class, recs[numRec-3].getClass());
-               assertEquals(DVRecord.class,  recs[numRec-2].getClass());
-               assertEquals(EOFRecord.class, recs[numRec-1].getClass());
+               assertEquals(DVALRecord.class,    recs[numRec-4].getClass());
+               assertEquals(DVRecord.class,      recs[numRec-3].getClass());
+               assertEquals(FeatHdrRecord.class, recs[numRec-2].getClass());
+               assertEquals(EOFRecord.class,     recs[numRec-1].getClass());
        }
 
        /**
@@ -110,7 +112,7 @@ public final class TestHSSFEventFactory extends TestCase {
        }
 
        private static class MockHSSFListener implements HSSFListener {
-               private final List records = new ArrayList();
+               private final List<Record> records = new ArrayList<Record>();
 
                public MockHSSFListener() {}
                public Record[] getRecords() {
diff --git a/src/testcases/org/apache/poi/hssf/record/TestFeatRecord.java b/src/testcases/org/apache/poi/hssf/record/TestFeatRecord.java
new file mode 100644 (file)
index 0000000..0ba8b77
--- /dev/null
@@ -0,0 +1,89 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.hssf.model.InternalWorkbook;
+import org.apache.poi.hssf.usermodel.HSSFTestHelper;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+import junit.framework.TestCase;
+/**
+ * Tests for <tt>FeatRecord</tt>
+ * 
+ * @author Josh Micich
+ */
+public final class TestFeatRecord extends TestCase {
+       public void testWithoutFeatRecord() throws Exception {
+               HSSFWorkbook hssf = 
+                       HSSFTestDataSamples.openSampleWorkbook("46136-WithWarnings.xls");
+               InternalWorkbook wb = HSSFTestHelper.getWorkbookForTest(hssf);
+               
+               int countFR = 0;
+               int countFRH = 0;
+               for(Record r : wb.getRecords()) {
+                       if(r instanceof FeatRecord) {
+                               countFR++;
+                       } else if (r.getSid() == FeatRecord.sid) {
+                               countFR++;
+                       }
+                       if(r instanceof FeatHdrRecord) {
+                               countFRH++;
+                       } else if (r.getSid() == FeatHdrRecord.sid) {
+                               countFRH++;
+                       }
+               }
+               
+               assertEquals(0, countFR);
+               assertEquals(0, countFRH);
+       }
+
+       /**
+        * TODO - make this work!
+        * (Need to have the Internal Workbook capture it or something)
+        */
+       public void DISABLEDtestReadFeatRecord() throws Exception {
+               HSSFWorkbook hssf = 
+                       HSSFTestDataSamples.openSampleWorkbook("46136-NoWarnings.xls");
+               InternalWorkbook wb = HSSFTestHelper.getWorkbookForTest(hssf);
+               
+               FeatRecord fr = null;
+               
+               int countFR = 0;
+               int countFRH = 0;
+               for(Record r : wb.getRecords()) {
+                       if(r instanceof FeatRecord) {
+                               fr = (FeatRecord)r;
+                               countFR++;
+                       } else if (r.getSid() == FeatRecord.sid) {
+                               fail("FeatRecord SID found but not created correctly!");
+                       }
+                       if(r instanceof FeatHdrRecord) {
+                               countFRH++;
+                       } else if (r.getSid() == FeatHdrRecord.sid) {
+                               fail("FeatHdrRecord SID found but not created correctly!");
+                       }
+               }
+               
+               assertEquals(1, countFR);
+               assertEquals(1, countFRH);
+               assertNotNull(fr);
+               
+               // Now check the contents are as expected
+       }
+}
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java
new file mode 100644 (file)
index 0000000..132013d
--- /dev/null
@@ -0,0 +1,33 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.usermodel;
+import org.apache.poi.hssf.model.InternalWorkbook;
+
+/**
+ * Helper class for HSSF tests that aren't within the
+ *  HSSF UserModel package, but need to do internal
+ *  UserModel things.
+ */
+public class HSSFTestHelper {
+       /**
+        * Lets non UserModel tests at the low level Workbook
+        */
+       public static InternalWorkbook getWorkbookForTest(HSSFWorkbook wb) {
+               return wb.getWorkbook();
+       }
+}
diff --git a/test-data/spreadsheet/46136-NoWarnings.xls b/test-data/spreadsheet/46136-NoWarnings.xls
new file mode 100644 (file)
index 0000000..3a67049
Binary files /dev/null and b/test-data/spreadsheet/46136-NoWarnings.xls differ
diff --git a/test-data/spreadsheet/46136-WithWarnings.xls b/test-data/spreadsheet/46136-WithWarnings.xls
new file mode 100644 (file)
index 0000000..c943b82
Binary files /dev/null and b/test-data/spreadsheet/46136-WithWarnings.xls differ