FileDocCategorySizeDatePackage
SSTRecord.javaAPI DocApache Poi 3.0.114305Mon Jan 01 12:39:40 GMT 2007org.apache.poi.hssf.record

SSTRecord

public class SSTRecord extends Record
Title: Static String Table Record

Description: This holds all the strings for LabelSSTRecords.

REFERENCE: PG 389 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

author
Andrew C. Oliver (acoliver at apache dot org)
author
Marc Johnson (mjohnson at apache dot org)
author
Glen Stampoultzis (glens at apache.org)
see
org.apache.poi.hssf.record.LabelSSTRecord
see
org.apache.poi.hssf.record.ContinueRecord

Fields Summary
private static UnicodeString
EMPTY_STRING
static final int
MAX_RECORD_SIZE
how big can an SST record be? As big as any record can be: 8228 bytes
static final int
STD_RECORD_OVERHEAD
standard record overhead: two shorts (record id plus data space size)
static final int
SST_RECORD_OVERHEAD
SST overhead: the standard record overhead, plus the number of strings and the number of unique strings -- two ints
static final int
MAX_DATA_SPACE
how much data can we stuff into an SST record? That would be _max minus the standard SST record overhead
static final int
STRING_MINIMAL_OVERHEAD
overhead for each string includes the string's character count (a short) and the flag describing its characteristics (a byte)
public static final short
sid
private int
field_1_num_strings
union of strings in the SST and EXTSST
private int
field_2_num_unique_strings
according to docs ONLY SST
private IntMapper
field_3_strings
private SSTDeserializer
deserializer
int[]
bucketAbsoluteOffsets
Offsets from the beginning of the SST record (even across continuations)
int[]
bucketRelativeOffsets
Offsets relative the start of the current SST or continue record
Constructors Summary
public SSTRecord()
default constructor


           
     
    
        field_1_num_strings = 0;
        field_2_num_unique_strings = 0;
        field_3_strings = new IntMapper();
        deserializer = new SSTDeserializer(field_3_strings);
    
public SSTRecord(RecordInputStream in)
Constructs an SST record and sets its fields appropriately.

param
id must be 0xfc or an exception will be throw upon validation
param
size the size of the data area of the record
param
data of the record (should not contain sid/len)

        super( in );
    
Methods Summary
public intaddString(org.apache.poi.hssf.record.UnicodeString string)
Add a string.

param
string string to be added
return
the index of that string in the table

        field_1_num_strings++;
        UnicodeString ucs = ( string == null ) ? EMPTY_STRING
                : string;
        int rval;
        int index = field_3_strings.getIndex(ucs);

        if ( index != -1 )
        {
            rval = index;
        }
        else
        {
            // This is a new string -- we didn't see it among the
            // strings we've already collected
            rval = field_3_strings.size();
            field_2_num_unique_strings++;
            SSTDeserializer.addToStringTable( field_3_strings, ucs );
        }
        return rval;
    
public intcalcExtSSTRecordSize()
Calculates the size in bytes of the EXTSST record as it would be if the record was serialized.

return
The size of the ExtSST record in bytes.

      return ExtSSTRecord.getRecordSizeForStrings(field_3_strings.size());
    
intcountStrings()

return
count of the strings we hold.

        return field_3_strings.size();
    
public org.apache.poi.hssf.record.ExtSSTRecordcreateExtSSTRecord(int sstOffset)
Creates an extended string record based on the current contents of the current SST record. The offset within the stream to the SST record is required because the extended string record points directly to the strings in the SST record.

NOTE: THIS FUNCTION MUST ONLY BE CALLED AFTER THE SST RECORD HAS BEEN SERIALIZED.

param
sstOffset The offset in the stream to the start of the SST record.
return
The new SST record.

        if (bucketAbsoluteOffsets == null || bucketAbsoluteOffsets == null)
            throw new IllegalStateException("SST record has not yet been serialized.");

        ExtSSTRecord extSST = new ExtSSTRecord();
        extSST.setNumStringsPerBucket((short)8);
        int[] absoluteOffsets = (int[]) bucketAbsoluteOffsets.clone();
        int[] relativeOffsets = (int[]) bucketRelativeOffsets.clone();
        for ( int i = 0; i < absoluteOffsets.length; i++ )
            absoluteOffsets[i] += sstOffset;
        extSST.setBucketOffsets(absoluteOffsets, relativeOffsets);
        return extSST;
    
public booleanequals(java.lang.Object o)

        if ( ( o == null ) || ( o.getClass() != this.getClass() ) )
        {
            return false;
        }
        SSTRecord other = (SSTRecord) o;

        return ( ( field_1_num_strings == other
                .field_1_num_strings ) && ( field_2_num_unique_strings == other
                .field_2_num_unique_strings ) && field_3_strings
                .equals( other.field_3_strings ) );
    
protected voidfillFields(org.apache.poi.hssf.record.RecordInputStream in)
Fill the fields from the data

The data consists of sets of string data. This string data is arranged as follows:

short string_length; // length of string data
byte string_flag; // flag specifying special string
// handling
short run_count; // optional count of formatting runs
int extend_length; // optional extension length
char[] string_data; // string data, can be byte[] or
// short[] (length of array is
// string_length)
int[] formatting_runs; // optional formatting runs (length of
// array is run_count)
byte[] extension; // optional extension (length of array
// is extend_length)

The string_flag is bit mapped as follows:

Bit number Meaning if 0 Meaning if 1
0 string_data is byte[] string_data is short[]
1 Should always be 0 string_flag is defective
2 extension is not included extension is included
3 formatting run data is not included formatting run data is included
4 Should always be 0 string_flag is defective
5 Should always be 0 string_flag is defective
6 Should always be 0 string_flag is defective
7 Should always be 0 string_flag is defective

We can handle eating the overhead associated with bits 2 or 3 (or both) being set, but we have no idea what to do with the associated data. The UnicodeString class can handle the byte[] vs short[] nature of the actual string data

param
data raw data
param
size size of the raw data

        // this method is ALWAYS called after construction -- using
        // the nontrivial constructor, of course -- so this is where
        // we initialize our fields
        field_1_num_strings = in.readInt();
        field_2_num_unique_strings = in.readInt();
        field_3_strings = new IntMapper();
        deserializer = new SSTDeserializer(field_3_strings);
        deserializer.manufactureStrings( field_2_num_unique_strings, in );
    
org.apache.poi.hssf.record.SSTDeserializergetDeserializer()

        return deserializer;
    
public intgetNumStrings()

return
number of strings

        return field_1_num_strings;
    
public intgetNumUniqueStrings()

return
number of unique strings

        return field_2_num_unique_strings;
    
public intgetRecordSize()

        SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(field_3_strings);
        int recordSize = calculator.getRecordSize();
        return recordSize;
    
public shortgetSid()

return
sid

        return sid;
    
public org.apache.poi.hssf.record.UnicodeStringgetString(int id)
Get a particular string by its index

param
id index into the array of strings
return
the desired string

        return (UnicodeString) field_3_strings.get( id );
    
java.util.IteratorgetStrings()

return
an iterator of the strings we hold. All instances are UnicodeStrings

        return field_3_strings.iterator();
    
public inthashCode()

return
hashcode

        return field_2_num_unique_strings;
    
public booleanisString16bit(int id)

        UnicodeString unicodeString = ( (UnicodeString) field_3_strings.get( id  ) );
        return ( ( unicodeString.getOptionFlags() & 0x01 ) == 1 );
    
public intserialize(int offset, byte[] data)
called by the class that is responsible for writing this sucker. Subclasses should implement this so that their data is passed back in a byte array.

return
size

        SSTSerializer serializer = new SSTSerializer(
               field_3_strings, getNumStrings(), getNumUniqueStrings() );
        int bytes = serializer.serialize( offset, data );
        bucketAbsoluteOffsets = serializer.getBucketAbsoluteOffsets();
        bucketRelativeOffsets = serializer.getBucketRelativeOffsets();
        return bytes;
    
public voidsetNumStrings(int count)
USE THIS METHOD AT YOUR OWN PERIL: THE addString METHODS MANIPULATE THE NUMBER OF STRINGS AS A SIDE EFFECT; YOUR ATTEMPTS AT MANIPULATING THE STRING COUNT IS LIKELY TO BE VERY WRONG AND WILL RESULT IN BAD BEHAVIOR WHEN THIS RECORD IS WRITTEN OUT AND ANOTHER PROCESS ATTEMPTS TO READ THE RECORD

param
count number of strings

        field_1_num_strings = count;
    
public voidsetNumUniqueStrings(int count)
USE THIS METHOD AT YOUR OWN PERIL: THE addString METHODS MANIPULATE THE NUMBER OF UNIQUE STRINGS AS A SIDE EFFECT; YOUR ATTEMPTS AT MANIPULATING THE UNIQUE STRING COUNT IS LIKELY TO BE VERY WRONG AND WILL RESULT IN BAD BEHAVIOR WHEN THIS RECORD IS WRITTEN OUT AND ANOTHER PROCESS ATTEMPTS TO READ THE RECORD

param
count number of strings

        field_2_num_unique_strings = count;
    
public java.lang.StringtoString()
Return a debugging string representation

return
string representation

        StringBuffer buffer = new StringBuffer();

        buffer.append( "[SST]\n" );
        buffer.append( "    .numstrings     = " )
                .append( Integer.toHexString( getNumStrings() ) ).append( "\n" );
        buffer.append( "    .uniquestrings  = " )
                .append( Integer.toHexString( getNumUniqueStrings() ) ).append( "\n" );
        for ( int k = 0; k < field_3_strings.size(); k++ )
        {
          UnicodeString s = (UnicodeString)field_3_strings.get( k );
            buffer.append( "    .string_" + k + "      = " )
                    .append( s.getDebugInfo() ).append( "\n" );
        }
        buffer.append( "[/SST]\n" );
        return buffer.toString();
    
protected voidvalidateSid(short id)
validate SID

param
id the alleged SID
exception
RecordFormatException if validation fails

        if ( id != sid )
        {
            throw new RecordFormatException( "NOT An SST RECORD" );
        }