]> source.dussan.org Git - poi.git/commitdiff
Start to support HPBF PLC parts
authorNick Burch <nick@apache.org>
Sat, 30 Aug 2008 16:59:55 +0000 (16:59 +0000)
committerNick Burch <nick@apache.org>
Sat, 30 Aug 2008 16:59:55 +0000 (16:59 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@690534 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hpbf/dev/PLCDumper.java
src/scratchpad/src/org/apache/poi/hpbf/model/QuillContents.java
src/scratchpad/src/org/apache/poi/hpbf/model/qcbits/QCPLCBit.java [new file with mode: 0644]
src/scratchpad/testcases/org/apache/poi/hpbf/model/TestQuillContents.java

index 368755efc0ba9b8717c3cbdf1c9cbdcf0db0f95c..cdec78c8cf1daa3562415a6ec9587110f82299df 100644 (file)
@@ -20,17 +20,11 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
-import org.apache.poi.ddf.DefaultEscherRecordFactory;
-import org.apache.poi.ddf.EscherRecord;
 import org.apache.poi.hpbf.HPBFDocument;
 import org.apache.poi.hpbf.model.QuillContents;
 import org.apache.poi.hpbf.model.qcbits.QCBit;
-import org.apache.poi.poifs.filesystem.DirectoryNode;
-import org.apache.poi.poifs.filesystem.DocumentEntry;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.apache.poi.util.HexDump;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.StringUtil;
 
 /**
  * For dumping out the PLC contents of QC Bits of a
@@ -41,8 +35,8 @@ public class PLCDumper {
        private HPBFDocument doc;
        private QuillContents qc;
        
-       public PLCDumper(HPBFDocument doc) {
-               this.doc = doc;
+       public PLCDumper(HPBFDocument hpbfDoc) {
+               doc = hpbfDoc;
                qc = doc.getQuillContents();
        }
        public PLCDumper(POIFSFileSystem fs) throws IOException {
@@ -67,7 +61,6 @@ public class PLCDumper {
        }
        
        private void dumpPLC() {        
-               QuillContents qc = doc.getQuillContents();
                QCBit[] bits = qc.getBits();
                
                for(int i=0; i<bits.length; i++) {
@@ -82,8 +75,8 @@ public class PLCDumper {
                System.out.println("");
                System.out.println("Dumping " + bit.getBitType() + " bit at " + index);
                System.out.println("  Is a " + bit.getThingType() + ", number is " + bit.getOptA());
-               System.out.println("  Starts at " + bit.getDataOffset() + " (" + Integer.toHexString(bit.getDataOffset()) + ")");
-               System.out.println("  Runs for  " + bit.getLength() + " (" + Integer.toHexString(bit.getLength()) + ")");
+               System.out.println("  Starts at " + bit.getDataOffset() + " (0x" + Integer.toHexString(bit.getDataOffset()) + ")");
+               System.out.println("  Runs for  " + bit.getLength() + " (0x" + Integer.toHexString(bit.getLength()) + ")");
                
                System.out.println(HexDump.dump(bit.getData(), 0, 0));
        }
index b8d4ad298ad7541ad4b1fda003905e2145f96689..56f7bfcc9cbb9444d0b259cc2a1f35e4bf75c2f9 100644 (file)
@@ -19,6 +19,7 @@ package org.apache.poi.hpbf.model;
 import java.io.IOException;
 
 import org.apache.poi.hpbf.model.qcbits.QCBit;
+import org.apache.poi.hpbf.model.qcbits.QCPLCBit;
 import org.apache.poi.hpbf.model.qcbits.QCTextBit;
 import org.apache.poi.hpbf.model.qcbits.UnknownQCBit;
 import org.apache.poi.poifs.filesystem.DirectoryNode;
@@ -64,6 +65,8 @@ public final class QuillContents extends HPBFPart {
                                // Create
                                if(bitType.equals("TEXT")) {
                                        bits[i] = new QCTextBit(thingType, bitType, bitData);
+                               } else if(bitType.equals("PLC ")) {
+                                       bits[i] = QCPLCBit.createQCPLCBit(thingType, bitType, bitData);
                                } else {
                                        bits[i] = new UnknownQCBit(thingType, bitType, bitData);
                                }
diff --git a/src/scratchpad/src/org/apache/poi/hpbf/model/qcbits/QCPLCBit.java b/src/scratchpad/src/org/apache/poi/hpbf/model/qcbits/QCPLCBit.java
new file mode 100644 (file)
index 0000000..92e9365
--- /dev/null
@@ -0,0 +1,175 @@
+/* ====================================================================
+   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.hpbf.model.qcbits;
+
+import org.apache.poi.util.LittleEndian;
+
+
+/**
+ * A "PLC " (PLC) based bit of Quill Contents. The exact
+ *  format is determined by the type of the PLCs.
+ */
+public class QCPLCBit extends QCBit {
+       protected int numberOfPLCs;
+       protected int typeOfPLCS;
+       /** 
+        * The data which goes before the main PLC entries.
+        * This is apparently always made up of 2 byte 
+        *  un-signed ints..
+        */
+       protected int[] preData;
+       /** The first value of each PLC, normally 4 bytes */
+       protected long[] plcValA;
+       /** The second value of each PLC, normally 4 bytes */
+       protected long[] plcValB;
+       
+       
+       private QCPLCBit(String thingType, String bitType, byte[] data) {
+               super(thingType, bitType, data);
+               
+               // First four bytes are the number
+               numberOfPLCs = (int)LittleEndian.getUInt(data, 0);
+               
+               // Next four bytes are the type
+               typeOfPLCS = (int)LittleEndian.getUInt(data, 4);
+               
+               // Init the arrays that we can
+               plcValA = new long[numberOfPLCs];
+               plcValB = new long[numberOfPLCs];
+       }
+       
+       
+       
+       public int getNumberOfPLCs() {
+               return numberOfPLCs;
+       }
+       public int getTypeOfPLCS() {
+               return typeOfPLCS;
+       }
+
+       public int[] getPreData() {
+               return preData;
+       }
+
+       public long[] getPlcValA() {
+               return plcValA;
+       }
+       public long[] getPlcValB() {
+               return plcValB;
+       }
+
+
+
+       public static QCPLCBit createQCPLCBit(String thingType, String bitType, byte[] data) {
+               // Grab the type
+               int type = (int)LittleEndian.getUInt(data, 4);
+               switch(type) {
+                       case 0:
+                               return new Type0(thingType, bitType, data);
+                       case 4:
+                               return new Type4(thingType, bitType, data);
+                       case 8:
+                               return new Type8(thingType, bitType, data);
+                       case 12: // 0xc
+                               return new Type12(thingType, bitType, data);
+                       default:
+                               throw new IllegalArgumentException("Sorry, I don't know how to deal with PLCs of type " + type);
+               }
+       }
+
+       
+       /**
+        * Type 0 seem to be somewhat rare. They have 8 bytes of pre-data,
+        *  then 2x 2 byte values.
+        */
+       public static class Type0 extends QCPLCBit {
+               private Type0(String thingType, String bitType, byte[] data) {
+                       super(thingType, bitType, data);
+                       
+                       // Grab our 4x pre-data
+                       preData = new int[4];
+                       preData[0] = LittleEndian.getUShort(data, 8+0);
+                       preData[1] = LittleEndian.getUShort(data, 8+2);
+                       preData[2] = LittleEndian.getUShort(data, 8+4);
+                       preData[3] = LittleEndian.getUShort(data, 8+6);
+                       
+                       // And grab the 2 byte values
+                       for(int i=0; i<numberOfPLCs; i++) {
+                               plcValA[i] = LittleEndian.getUShort(data, 16+(4*i));
+                               plcValB[i] = LittleEndian.getUShort(data, 16+(4*i)+2);
+                       }
+               }
+       }
+       
+       /**
+        * Type 4 is quite common. They have 8 bytes of pre-data,
+        *  then 2x 4 byte values.
+        */
+       public static class Type4 extends QCPLCBit {
+               private Type4(String thingType, String bitType, byte[] data) {
+                       super(thingType, bitType, data);
+                       
+                       // Grab our 4x pre-data
+                       preData = new int[4];
+                       preData[0] = LittleEndian.getUShort(data, 8+0);
+                       preData[1] = LittleEndian.getUShort(data, 8+2);
+                       preData[2] = LittleEndian.getUShort(data, 8+4);
+                       preData[3] = LittleEndian.getUShort(data, 8+6);
+                       
+                       // And grab the 4 byte values
+                       for(int i=0; i<numberOfPLCs; i++) {
+                               plcValA[i] = LittleEndian.getUInt(data, 16+(8*i));
+                               plcValB[i] = LittleEndian.getUInt(data, 16+(8*i)+4);
+                       }
+               }
+       }
+       
+       /**
+        * Type 8 is quite common. They have 14 bytes of pre-data,
+        *  then 2x 4 byte values.
+        */
+       public static class Type8 extends QCPLCBit {
+               private Type8(String thingType, String bitType, byte[] data) {
+                       super(thingType, bitType, data);
+                       
+                       // Grab our 7x pre-data
+                       preData = new int[7];
+                       preData[0] = LittleEndian.getUShort(data, 8+0);
+                       preData[1] = LittleEndian.getUShort(data, 8+2);
+                       preData[2] = LittleEndian.getUShort(data, 8+4);
+                       preData[3] = LittleEndian.getUShort(data, 8+6);
+                       preData[4] = LittleEndian.getUShort(data, 8+8);
+                       preData[5] = LittleEndian.getUShort(data, 8+10);
+                       preData[6] = LittleEndian.getUShort(data, 8+12);
+                       
+                       // And grab the 4 byte values
+                       for(int i=0; i<numberOfPLCs; i++) {
+                               plcValA[i] = LittleEndian.getUInt(data, 22+(8*i));
+                               plcValB[i] = LittleEndian.getUInt(data, 22+(8*i)+4);
+                       }
+               }
+       }
+       
+       /**
+        * Type 12 holds hyperlinks, and is very complex.
+        */
+       public static class Type12 extends QCPLCBit {
+               private Type12(String thingType, String bitType, byte[] data) {
+                       super(thingType, bitType, data);
+               }
+       }
+}
index ce6ddf83efd73017bea790b1e9484bdf11882812..ecbc226098404fb41059fbe7a14e96068203c2dd 100644 (file)
@@ -21,6 +21,8 @@ import java.io.FileInputStream;
 
 import org.apache.poi.hpbf.HPBFDocument;
 import org.apache.poi.hpbf.model.qcbits.QCTextBit;
+import org.apache.poi.hpbf.model.qcbits.QCPLCBit.Type4;
+import org.apache.poi.hpbf.model.qcbits.QCPLCBit.Type8;
 
 import junit.framework.TestCase;
 
@@ -77,4 +79,65 @@ public class TestQuillContents extends TestCase {
                assertTrue(t.startsWith("This is some text on the first page"));
                assertTrue(t.endsWith("Within doc to page 1\r"));
        }
+       
+       public void testPLC() throws Exception {
+               File f = new File(dir, "Simple.pub");
+               HPBFDocument doc = new HPBFDocument(
+                               new FileInputStream(f)
+               );
+               
+               QuillContents qc = doc.getQuillContents();
+               assertEquals(20, qc.getBits().length);
+               
+               assertTrue(qc.getBits()[9] instanceof Type4);
+               assertTrue(qc.getBits()[10] instanceof Type4);
+               assertTrue(qc.getBits()[12] instanceof Type8);
+               
+               Type4 plc9 = (Type4)qc.getBits()[9];
+               Type4 plc10 = (Type4)qc.getBits()[10];
+               Type8 plc12 = (Type8)qc.getBits()[12];
+               
+               
+               assertEquals(1, plc9.getNumberOfPLCs());
+               assertEquals(4, plc9.getPreData().length);
+               assertEquals(1, plc9.getPlcValA().length);
+               assertEquals(1, plc9.getPlcValB().length);
+               
+               assertEquals(0, plc9.getPreData()[0]);
+               assertEquals(0, plc9.getPreData()[1]);
+               assertEquals(0, plc9.getPreData()[2]);
+               assertEquals(0, plc9.getPreData()[3]);
+               assertEquals(0x356, plc9.getPlcValA()[0]);
+               assertEquals(0x600, plc9.getPlcValB()[0]);
+               
+               
+               assertEquals(1, plc10.getNumberOfPLCs());
+               assertEquals(4, plc10.getPreData().length);
+               assertEquals(1, plc10.getPlcValA().length);
+               assertEquals(1, plc10.getPlcValB().length);
+               
+               assertEquals(0, plc10.getPreData()[0]);
+               assertEquals(0, plc10.getPreData()[1]);
+               assertEquals(0, plc10.getPreData()[2]);
+               assertEquals(0, plc10.getPreData()[3]);
+               assertEquals(0x356, plc10.getPlcValA()[0]);
+               assertEquals(0x800, plc10.getPlcValB()[0]);
+               
+               assertEquals(2, plc12.getNumberOfPLCs());
+               assertEquals(7, plc12.getPreData().length);
+               assertEquals(2, plc12.getPlcValA().length);
+               assertEquals(2, plc12.getPlcValB().length);
+               
+               assertEquals(0xff, plc12.getPreData()[0]);
+               assertEquals(0, plc12.getPreData()[1]);
+               assertEquals(0x3d, plc12.getPreData()[2]);
+               assertEquals(0, plc12.getPreData()[3]);
+               assertEquals(0x6e, plc12.getPreData()[4]);
+               assertEquals(0, plc12.getPreData()[5]);
+               assertEquals(0, plc12.getPreData()[6]);
+               assertEquals(0xa0000, plc12.getPlcValA()[0]);
+               assertEquals(0x22000000, plc12.getPlcValB()[0]);
+               assertEquals(0x05, plc12.getPlcValA()[1]);
+               assertEquals(0x04, plc12.getPlcValB()[1]);
+       }
 }