]> source.dussan.org Git - poi.git/commitdiff
Make a start on processing the commands within the chunks, and their values. Includes...
authorNick Burch <nick@apache.org>
Thu, 21 Jun 2007 21:24:25 +0000 (21:24 +0000)
committerNick Burch <nick@apache.org>
Thu, 21 Jun 2007 21:24:25 +0000 (21:24 +0000)
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@549616 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hdgf/chunks/Chunk.java
src/scratchpad/src/org/apache/poi/hdgf/chunks/ChunkFactory.java
src/scratchpad/src/org/apache/poi/hdgf/dev/VSDDumper.java
src/scratchpad/testcases/org/apache/poi/hdgf/chunks/TestChunks.java

index 9018edf4a2833c6997ff1faf5a0f53a22129597d..54c37b3e8304a22ffbdc80418dcca4b5a34de66a 100644 (file)
 ==================================================================== */
 package org.apache.poi.hdgf.chunks;
 
+import java.util.ArrayList;
+
 import org.apache.poi.hdgf.chunks.ChunkFactory.CommandDefinition;
+import org.apache.poi.util.LittleEndian;
 
 /**
  * Base of all chunks, which hold data, flags etc
@@ -34,6 +37,12 @@ public class Chunk {
        private ChunkSeparator separator;
        /** The possible different commands we can hold */
        protected CommandDefinition[] commandDefinitions;
+       /** The command+value pairs we hold */
+       private Command[] commands;
+       /** The blocks (if any) we hold */
+       //private Block[] blocks
+       /** The name of the chunk, as found from the commandDefinitions */
+       private String name;
        
        public Chunk(ChunkHeader header, ChunkTrailer trailer, ChunkSeparator separator, byte[] contents) {
                this.header = header;
@@ -63,6 +72,15 @@ public class Chunk {
        public CommandDefinition[] getCommandDefinitions() {
                return commandDefinitions;
        }
+       public Command[] getCommands() {
+               return commands;
+       }
+       /**
+        * Get the name of the chunk, as found from the CommandDefinitions
+        */
+       public String getName() {
+               return name;
+       }
 
        /**
         * Returns the size of the chunk, including any
@@ -78,4 +96,156 @@ public class Chunk {
                }
                return size;
        }
+       
+       /**
+        * Uses our CommandDefinitions to process the commands
+        *  our chunk type has, and figure out the
+        *  values for them.
+        */
+       protected void processCommands() {
+               if(commandDefinitions == null) {
+                       throw new IllegalStateException("You must supply the command definitions before calling processCommands!");
+               }
+               
+               // Loop over the definitions, building the commands
+               //  and getting their values
+               ArrayList commands = new ArrayList();
+               for(int i=0; i<commandDefinitions.length; i++) {
+                       int type = commandDefinitions[i].getType();
+                       int offset = commandDefinitions[i].getOffset();
+                       
+                       // Handle virtual commands
+                       if(type == 10) {
+                               name = commandDefinitions[i].getName();
+                               continue;
+                       } else if(type == 18) {
+                               continue;
+                       }
+
+                       
+                       // Build the appropriate command for the type
+                       Command command;
+                       if(type == 11 || type == 21) {
+                               command = new BlockOffsetCommand(commandDefinitions[i]);
+                       } else {
+                               command = new Command(commandDefinitions[i]);
+                       }
+                       
+                       // Bizarely, many of the offsets are from the start of the
+                       //  header, not from the start of the chunk body
+                       switch(type) {
+                       case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+                       case 11: case 21:
+                       case 12: case 16: case 17: case 18: case 28: case 29:
+                               // Offset is from start of chunk
+                               break;
+                       default:
+                               // Offset is from start of header!
+                               if(offset >= 19) {
+                                       offset -= 19;
+                               }
+                       }
+                       
+                       // Check we seem to have enough data
+                       if(offset >= contents.length) {
+                               System.err.println("Command offset " + offset + " past end of data at " + contents.length);
+                               continue;
+                       }
+               
+                       // Process
+                       switch(type) {
+                       // Types 0->7 = a flat at bit 0->7
+                       case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+                               int val = contents[offset] & (1<<type);
+                               command.value = new Boolean( (val > 0) );
+                               break;
+                       case 8:
+                               command.value = new Byte( contents[offset] );
+                               break;
+                       case 9:
+                               command.value = new Double(
+                                               LittleEndian.getDouble(contents, offset)
+                               );
+                               break;
+                       case 25:
+                               command.value = new Short(
+                                               LittleEndian.getShort(contents, offset)
+                               );
+                               break;
+                       case 26:
+                               command.value = new Integer(
+                                               LittleEndian.getInt(contents, offset)
+                               );
+                               break;
+                               
+                       // Types 11 and 21 hold the offset to the blocks
+                       case 11: case 21:
+                               if(offset < contents.length - 3) {
+                                       int bOffset = (int)LittleEndian.getUInt(contents, offset);
+                                       BlockOffsetCommand bcmd = (BlockOffsetCommand)command;
+                                       bcmd.setOffset(bOffset);
+                               }
+                               break;
+                               
+                       default:
+                               //System.err.println("Warning - Command of type " + type + " not processed!");
+                       }
+                       
+                       // Add to the array
+                       commands.add(command);
+               }
+               
+               // Save the commands we liked the look of
+               this.commands = (Command[])commands.toArray(
+                                                       new Command[commands.size()] );
+               
+               // Now build up the blocks, if we had a command that tells
+               //  us where a block is
+       }
+       
+       /**
+        * A command in the visio file. In order to make things fun, 
+        *  all the chunk actually stores is the value of the command.
+        * You have to have your own lookup table to figure out what
+        *  the commands are based on the chunk type.
+        */
+       public static class Command {
+               protected Object value;
+               private CommandDefinition definition;
+               
+               private Command(CommandDefinition definition, Object value) {
+                       this.definition = definition;
+                       this.value = value;
+               }
+               private Command(CommandDefinition definition) {
+                       this(definition, null);
+               }
+               
+               public CommandDefinition getDefinition() { return definition; }
+               public Object getValue() { return value; }
+       }
+       /**
+        * A special kind of command that is an artificat of how we
+        *  process CommandDefinitions, and so doesn't actually exist
+        *  in the chunk
+        */
+//     public static class VirtualCommand extends Command {
+//             private VirtualCommand(CommandDefinition definition) {
+//                     super(definition);
+//             }
+//     }
+       /**
+        * A special kind of command that holds the offset to
+        *  a block
+        */
+       public static class BlockOffsetCommand extends Command {
+               private int offset;
+               private BlockOffsetCommand(CommandDefinition definition) {
+                       super(definition, null);
+               }
+               private void setOffset(int offset) {
+                       this.offset = offset;
+                       value = new Integer(offset);
+               }
+       }
 }
index 8b9d03df24560b2536370470ae7dd9af8633c5fd..efac0d357458b684c86e8dc886c23ccd5c2cd164 100644 (file)
@@ -152,8 +152,12 @@ public class ChunkFactory {
                // Feed in the stuff from  chunks_parse_cmds.tbl
                CommandDefinition[] defs = (CommandDefinition[])
                        chunkCommandDefinitions.get(new Integer(header.getType()));
+               if(defs == null) defs = new CommandDefinition[0];
                chunk.commandDefinitions = defs;
                
+               // Now get the chunk to process its commands
+               chunk.processCommands();
+               
                // All done
                return chunk;
        }
index 364963f291c8fbfac1bec7205b64680794d7a486..3a4328858db6b2bc735be1e1ebc6cfde9ab357eb 100644 (file)
@@ -19,7 +19,10 @@ package org.apache.poi.hdgf.dev;
 import java.io.FileInputStream;
 
 import org.apache.poi.hdgf.HDGFDiagram;
+import org.apache.poi.hdgf.chunks.Chunk;
+import org.apache.poi.hdgf.chunks.Chunk.Command;
 import org.apache.poi.hdgf.pointers.Pointer;
+import org.apache.poi.hdgf.streams.ChunkStream;
 import org.apache.poi.hdgf.streams.PointerContainingStream;
 import org.apache.poi.hdgf.streams.Stream;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
@@ -54,6 +57,9 @@ public class VSDDumper {
                for(int i=0; i<indent; i++) {
                        ind += "    ";
                }
+               String ind2 = ind  + "    ";
+               String ind3 = ind2 + "    ";
+               
                
                Pointer ptr = stream.getPointer();
                System.out.println(ind + "Stream at\t" + ptr.getOffset() +
@@ -86,5 +92,23 @@ public class VSDDumper {
                                dumpStream(pcs.getPointedToStreams()[i], (indent+1));
                        }
                }
+               if(stream instanceof ChunkStream) {
+                       ChunkStream cs = (ChunkStream)stream;
+                       System.out.println(ind + "  Has " + cs.getChunks().length +
+                                       " chunks:");
+                       
+                       for(int i=0; i<cs.getChunks().length; i++) {
+                               Chunk chunk = cs.getChunks()[i];
+                               System.out.println(ind2 + "" + chunk.getName());
+                               System.out.println(ind2 + "  Holds " + chunk.getCommands().length + " commands");
+                               for(int j=0; j<chunk.getCommands().length; j++) {
+                                       Command command = chunk.getCommands()[j];
+                                       System.out.println(ind3 + "" + 
+                                                       command.getDefinition().getName() +
+                                                       " " + command.getValue()
+                                       );
+                               }
+                       }
+               }
        }
 }
index 9cf11ce3aa0a113a566c6372fc9251bd7974e931..a470f1e98b6301492c893849f081cd94f3b64ef4 100644 (file)
@@ -47,7 +47,7 @@ public static final byte[] data_a = new byte[] { 70, 0, 0, 0,
        0, 0, 0, 1, 0, 84, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
        -125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 2, 0, 85, 5, 0, 0, 
-       0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0
+       0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 public static final byte[] data_b = new byte[] { 70, 0, 0, 0,
        -1, -1, -1, -1, 3, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 
@@ -137,9 +137,10 @@ public static final byte[] data_b = new byte[] { 70, 0, 0, 0,
                assertEquals(70, chunk.getHeader().getType());
                assertEquals(0x46, chunk.getHeader().getType());
                
-               // Should have two different chunk commands, a
+               // Should have two virtual chunk commands, a
                //  10 (page sheet) and an 18
                assertEquals(2, chunk.commandDefinitions.length);
+               assertEquals(0, chunk.getCommands().length);
                
                assertEquals(10, chunk.commandDefinitions[0].getType());
                assertEquals(0, chunk.commandDefinitions[0].getOffset());
@@ -171,9 +172,10 @@ public static final byte[] data_b = new byte[] { 70, 0, 0, 0,
                assertEquals(104, chunk.getHeader().getType());
                assertEquals(0x68, chunk.getHeader().getType());
                
-               // Should have two different chunk commands, a
+               // Should have two virtual chunk commands, a
                //  10 (Unknown) and an 18
                assertEquals(2, chunk.commandDefinitions.length);
+               assertEquals(0, chunk.getCommands().length);
                
                assertEquals(10, chunk.commandDefinitions[0].getType());
                assertEquals(0, chunk.commandDefinitions[0].getOffset());