FileDocCategorySizeDatePackage
EscherArrayProperty.javaAPI DocApache Poi 3.0.18109Thu May 31 18:44:06 BST 2007org.apache.poi.ddf

EscherArrayProperty

public class EscherArrayProperty extends EscherComplexProperty
Escher array properties are the most wierd construction ever invented with all sorts of special cases. I'm hopeful I've got them all.
author
Glen Stampoultzis (glens at superlinksoftware.com)

Fields Summary
private static final int
FIXED_SIZE
The size of the header that goes at the start of the array, before the data
private boolean
sizeIncludesHeaderSize
Normally, the size recorded in the simple data (for the complex data) includes the size of the header. There are a few cases when it doesn't though...
private boolean
emptyComplexPart
When reading a property from data stream remeber if the complex part is empty and set this flag.
Constructors Summary
public EscherArrayProperty(short id, byte[] complexData)


          
    
        super( id, checkComplexData(complexData) );
        emptyComplexPart = complexData.length == 0;
    
public EscherArrayProperty(short propertyNumber, boolean isBlipId, byte[] complexData)

        super( propertyNumber, isBlipId, checkComplexData(complexData) );
    
Methods Summary
private static byte[]checkComplexData(byte[] complexData)

        if (complexData == null || complexData.length == 0)
            complexData = new byte[6];

        return complexData;
    
public static intgetActualSizeOfElements(short sizeOfElements)
Sometimes the element size is stored as a negative number. We negate it and shift it to get the real value.

        if (sizeOfElements < 0)
            return (short) ( ( -sizeOfElements ) >> 2 );
        else
            return sizeOfElements;
    
public byte[]getElement(int index)

        int actualSize = getActualSizeOfElements(getSizeOfElements());
        byte[] result = new byte[actualSize];
        System.arraycopy(complexData, FIXED_SIZE + index * actualSize, result, 0, result.length );
        return result;
    
public intgetNumberOfElementsInArray()

        return LittleEndian.getUShort( complexData, 0 );
    
public intgetNumberOfElementsInMemory()

        return LittleEndian.getUShort( complexData, 2 );
    
public shortgetSizeOfElements()

        return LittleEndian.getShort( complexData, 4 );
    
public intserializeSimplePart(byte[] data, int pos)
Serializes the simple part of this property. ie the first 6 bytes. Needs special code to handle the case when the size doesn't include the size of the header block

        LittleEndian.putShort(data, pos, getId());
        int recordSize = complexData.length;
        if(!sizeIncludesHeaderSize) {
        	recordSize -= 6;
        }
        LittleEndian.putInt(data, pos + 2, recordSize);
        return 6;
    
public intsetArrayData(byte[] data, int offset)
We have this method because the way in which arrays in escher works is screwed for seemly arbitary reasons. While most properties are fairly consistent and have a predictable array size, escher arrays have special cases.

param
data The data array containing the escher array information
param
offset The offset into the array to start reading from.
return
the number of bytes used by this complex property.

        if (emptyComplexPart){
            complexData = new byte[0];
        } else {
            short numElements = LittleEndian.getShort(data, offset);
            short numReserved = LittleEndian.getShort(data, offset + 2);
            short sizeOfElements = LittleEndian.getShort(data, offset + 4);

            int arraySize = getActualSizeOfElements(sizeOfElements) * numElements;
            if (arraySize == complexData.length) {
                // The stored data size in the simple block excludes the header size
                complexData = new byte[arraySize + 6];
                sizeIncludesHeaderSize = false;
            }
            System.arraycopy(data, offset, complexData, 0, complexData.length );
        }
        return complexData.length;
    
public voidsetElement(int index, byte[] element)

        int actualSize = getActualSizeOfElements(getSizeOfElements());
        System.arraycopy( element, 0, complexData, FIXED_SIZE + index * actualSize, actualSize);
    
public voidsetNumberOfElementsInArray(int numberOfElements)

        int expectedArraySize = numberOfElements * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE;
        if ( expectedArraySize != complexData.length )
        {
            byte[] newArray = new byte[expectedArraySize];
            System.arraycopy( complexData, 0, newArray, 0, complexData.length );
            complexData = newArray;
        }
        LittleEndian.putShort( complexData, 0, (short) numberOfElements );
    
public voidsetNumberOfElementsInMemory(int numberOfElements)

        int expectedArraySize = numberOfElements * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE;
        if ( expectedArraySize != complexData.length )
        {
            byte[] newArray = new byte[expectedArraySize];
            System.arraycopy( complexData, 0, newArray, 0, expectedArraySize );
            complexData = newArray;
        }
        LittleEndian.putShort( complexData, 2, (short) numberOfElements );
    
public voidsetSizeOfElements(int sizeOfElements)

        LittleEndian.putShort( complexData, 4, (short) sizeOfElements );

        int expectedArraySize = getNumberOfElementsInArray() * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE;
        if ( expectedArraySize != complexData.length )
        {
            // Keep just the first 6 bytes.  The rest is no good to us anyway.
            byte[] newArray = new byte[expectedArraySize];
            System.arraycopy( complexData, 0, newArray, 0, 6 );
            complexData = newArray;
        }
    
public java.lang.StringtoString()

        String nl = System.getProperty("line.separator");

        StringBuffer results = new StringBuffer();
        results.append("    {EscherArrayProperty:" + nl);
        results.append("     Num Elements: " + getNumberOfElementsInArray() + nl);
        results.append("     Num Elements In Memory: " + getNumberOfElementsInMemory() + nl);
        results.append("     Size of elements: " + getSizeOfElements() + nl);
        for (int i = 0; i < getNumberOfElementsInArray(); i++)
        {
            results.append("     Element " + i + ": " + HexDump.toHex(getElement(i)) + nl);
        }
        results.append("}" + nl);

        return "propNum: " + getPropertyNumber()
                + ", propName: " + EscherProperties.getPropertyName( getPropertyNumber() )
                + ", complex: " + isComplex()
                + ", blipId: " + isBlipId()
                + ", data: " + nl + results.toString();