FileDocCategorySizeDatePackage
Chunk.javaAPI DocApache Poi 3.0.18108Wed Jun 27 19:50:22 BST 2007org.apache.poi.hdgf.chunks

Chunk

public class Chunk extends Object
Base of all chunks, which hold data, flags etc

Fields Summary
private byte[]
contents
The contents of the chunk, excluding the header, trailer and separator
private ChunkHeader
header
private ChunkTrailer
trailer
May be null
private ChunkSeparator
separator
May be null
protected org.apache.poi.hdgf.chunks.ChunkFactory.CommandDefinition[]
commandDefinitions
The possible different commands we can hold
private Command[]
commands
The command+value pairs we hold
private String
name
The name of the chunk, as found from the commandDefinitions
private POILogger
logger
For logging warnings about the structure of the file
Constructors Summary
public Chunk(ChunkHeader header, ChunkTrailer trailer, ChunkSeparator separator, byte[] contents)

	
	         
		this.header = header;
		this.trailer = trailer;
		this.separator = separator;
		this.contents = contents;
	
Methods Summary
public byte[]_getContents()

		return contents;
	
public org.apache.poi.hdgf.chunks.ChunkFactory.CommandDefinition[]getCommandDefinitions()
Gets the command definitions, which define and describe much of the data held by the chunk.

		return commandDefinitions;
	
public org.apache.poi.hdgf.chunks.Chunk$Command[]getCommands()

		return commands;
	
public org.apache.poi.hdgf.chunks.ChunkHeadergetHeader()

		return header;
	
public java.lang.StringgetName()
Get the name of the chunk, as found from the CommandDefinitions

		return name;
	
public intgetOnDiskSize()
Returns the size of the chunk, including any headers, trailers and separators.

		int size = header.getSizeInBytes() + contents.length;
		if(trailer != null) {
			size += trailer.trailerData.length;
		}
		if(separator != null) {
			size += separator.separatorData.length;
		}
		return size;
	
public org.apache.poi.hdgf.chunks.ChunkSeparatorgetSeparator()
Gets the separator between this chunk and the next, if it exists

		return separator;
	
public org.apache.poi.hdgf.chunks.ChunkTrailergetTrailer()
Gets the trailer for this chunk, if it exists

		return trailer;
	
protected voidprocessCommands()
Uses our CommandDefinitions to process the commands our chunk type has, and figure out the values for them.

		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) {
				logger.log(POILogger.WARN, 
						"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 12:
				// A Little Endian String
				// Starts 8 bytes into the data segment
				// Ends at end of data, or 00 00
				int startsAt = 8;
				int endsAt = startsAt;
				for(int j=startsAt; j<contents.length-1 && endsAt == startsAt; j++) {
					if(contents[j] == 0 && contents[j+1] == 0) {
						endsAt = j;
					}
				}
				if(endsAt == startsAt) {
					endsAt = contents.length;
				}
				
				int strLen = (endsAt-startsAt) / 2;
				command.value = StringUtil.getFromUnicodeLE(contents, startsAt, strLen);
				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:
				logger.log(POILogger.INFO, 
						"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