1 2 17 18 19 package org.apache.poi.hssf.record; 20 21 import org.apache.poi.util.BinaryTree; 22 import org.apache.poi.util.LittleEndian; 23 import org.apache.poi.util.LittleEndianConsts; 24 25 import java.util.Iterator ; 26 import java.util.List ; 27 28 43 44 public class SSTRecord 45 extends Record 46 { 47 48 49 static final int MAX_RECORD_SIZE = 8228; 50 51 52 static final int STD_RECORD_OVERHEAD = 53 2 * LittleEndianConsts.SHORT_SIZE; 54 55 56 static final int SST_RECORD_OVERHEAD = 57 ( STD_RECORD_OVERHEAD + ( 2 * LittleEndianConsts.INT_SIZE ) ); 58 59 60 static final int MAX_DATA_SPACE = MAX_RECORD_SIZE - SST_RECORD_OVERHEAD; 61 62 63 static final int STRING_MINIMAL_OVERHEAD = LittleEndianConsts.SHORT_SIZE + LittleEndianConsts.BYTE_SIZE; 64 65 public static final short sid = 0xfc; 66 67 68 private int field_1_num_strings; 69 70 71 private int field_2_num_unique_strings; 72 private BinaryTree field_3_strings; 73 74 75 private List _record_lengths = null; 76 private SSTDeserializer deserializer; 77 78 79 int[] bucketAbsoluteOffsets; 80 81 int[] bucketRelativeOffsets; 82 83 86 public SSTRecord() 87 { 88 field_1_num_strings = 0; 89 field_2_num_unique_strings = 0; 90 field_3_strings = new BinaryTree(); 91 deserializer = new SSTDeserializer(field_3_strings); 92 } 93 94 102 103 public SSTRecord( final short id, final short size, final byte[] data ) 104 { 105 super( id, size, data ); 106 } 107 108 117 118 public SSTRecord( final short id, final short size, final byte[] data, 119 int offset ) 120 { 121 super( id, size, data, offset ); 122 } 123 124 138 139 public int addString( final String string ) 140 { 141 int rval; 142 143 if ( string == null ) 144 { 145 rval = addString( "", false ); 146 } 147 else 148 { 149 150 boolean useUTF16 = false; 154 int strlen = string.length(); 155 156 for ( int j = 0; j < strlen; j++ ) 157 { 158 if ( string.charAt( j ) > 255 ) 159 { 160 useUTF16 = true; 161 break; 162 } 163 } 164 rval = addString( string, useUTF16 ); 165 } 166 return rval; 167 } 168 169 184 185 public int addString( final String string, final boolean useUTF16 ) 186 { 187 field_1_num_strings++; 188 String str = ( string == null ) ? "" 189 : string; 190 int rval; 191 UnicodeString ucs = new UnicodeString(); 192 193 ucs.setString( str ); 194 ucs.setCharCount( (short) str.length() ); 195 ucs.setOptionFlags( (byte) ( useUTF16 ? 1 196 : 0 ) ); 197 Integer integer = (Integer ) field_3_strings.getKeyForValue( ucs ); 198 199 if ( integer != null ) 200 { 201 rval = integer.intValue(); 202 } 203 else 204 { 205 206 rval = field_3_strings.size(); 209 field_2_num_unique_strings++; 210 integer = new Integer ( rval ); 211 SSTDeserializer.addToStringTable( field_3_strings, integer, ucs ); 212 } 214 return rval; 215 } 216 217 220 221 public int getNumStrings() 222 { 223 return field_1_num_strings; 224 } 225 226 229 230 public int getNumUniqueStrings() 231 { 232 return field_2_num_unique_strings; 233 } 234 235 245 246 public void setNumStrings( final int count ) 247 { 248 field_1_num_strings = count; 249 } 250 251 261 262 public void setNumUniqueStrings( final int count ) 263 { 264 field_2_num_unique_strings = count; 265 } 266 267 274 275 public String getString( final int id ) 276 { 277 return ( (UnicodeString) field_3_strings.get( new Integer ( id ) ) ).getString(); 278 } 279 280 public boolean isString16bit( final int id ) 281 { 282 UnicodeString unicodeString = ( (UnicodeString) field_3_strings.get( new Integer ( id ) ) ); 283 return ( ( unicodeString.getOptionFlags() & 0x01 ) == 1 ); 284 } 285 286 291 292 public String toString() 293 { 294 StringBuffer buffer = new StringBuffer (); 295 296 buffer.append( "[SST]\n" ); 297 buffer.append( " .numstrings = " ) 298 .append( Integer.toHexString( getNumStrings() ) ).append( "\n" ); 299 buffer.append( " .uniquestrings = " ) 300 .append( Integer.toHexString( getNumUniqueStrings() ) ).append( "\n" ); 301 for ( int k = 0; k < field_3_strings.size(); k++ ) 302 { 303 buffer.append( " .string_" + k + " = " ) 304 .append( ( field_3_strings 305 .get( new Integer ( k ) ) ).toString() ).append( "\n" ); 306 } 307 buffer.append( "[/SST]\n" ); 308 return buffer.toString(); 309 } 310 311 314 public short getSid() 315 { 316 return sid; 317 } 318 319 322 public int hashCode() 323 { 324 return field_2_num_unique_strings; 325 } 326 327 public boolean equals( Object o ) 328 { 329 if ( ( o == null ) || ( o.getClass() != this.getClass() ) ) 330 { 331 return false; 332 } 333 SSTRecord other = (SSTRecord) o; 334 335 return ( ( field_1_num_strings == other 336 .field_1_num_strings ) && ( field_2_num_unique_strings == other 337 .field_2_num_unique_strings ) && field_3_strings 338 .equals( other.field_3_strings ) ); 339 } 340 341 348 349 protected void validateSid( final short id ) 350 throws RecordFormatException 351 { 352 if ( id != sid ) 353 { 354 throw new RecordFormatException( "NOT An SST RECORD" ); 355 } 356 } 357 358 437 438 protected void fillFields( final byte[] data, final short size, 439 int offset ) 440 { 441 442 field_1_num_strings = LittleEndian.getInt( data, 0 + offset ); 446 field_2_num_unique_strings = LittleEndian.getInt( data, 4 + offset ); 447 field_3_strings = new BinaryTree(); 448 deserializer = new SSTDeserializer(field_3_strings); 449 deserializer.manufactureStrings( data, 8 + offset); 450 } 451 452 453 457 458 Iterator getStrings() 459 { 460 return field_3_strings.values().iterator(); 461 } 462 463 466 467 int countStrings() 468 { 469 return field_3_strings.size(); 470 } 471 472 479 480 public int serialize( int offset, byte[] data ) 481 { 482 SSTSerializer serializer = new SSTSerializer( 483 _record_lengths, field_3_strings, getNumStrings(), getNumUniqueStrings() ); 484 int bytes = serializer.serialize( getRecordSize(), offset, data ); 485 bucketAbsoluteOffsets = serializer.getBucketAbsoluteOffsets(); 486 bucketRelativeOffsets = serializer.getBucketRelativeOffsets(); 487 return bytes; 493 } 494 495 496 public int getRecordSize() 497 { 498 SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(field_3_strings); 499 int recordSize = calculator.getRecordSize(); 500 _record_lengths = calculator.getRecordLengths(); 501 return recordSize; 502 } 503 504 SSTDeserializer getDeserializer() 505 { 506 return deserializer; 507 } 508 509 512 public void processContinueRecord( byte[] record ) 513 { 514 deserializer.processContinueRecord( record ); 515 } 516 517 530 public ExtSSTRecord createExtSSTRecord(int sstOffset) 531 { 532 if (bucketAbsoluteOffsets == null || bucketAbsoluteOffsets == null) 533 throw new IllegalStateException ("SST record has not yet been serialized."); 534 535 ExtSSTRecord extSST = new ExtSSTRecord(); 536 extSST.setNumStringsPerBucket((short)8); 537 int[] absoluteOffsets = (int[]) bucketAbsoluteOffsets.clone(); 538 int[] relativeOffsets = (int[]) bucketRelativeOffsets.clone(); 539 for ( int i = 0; i < absoluteOffsets.length; i++ ) 540 absoluteOffsets[i] += sstOffset; 541 extSST.setBucketOffsets(absoluteOffsets, relativeOffsets); 542 return extSST; 543 } 544 545 551 public int calcExtSSTRecordSize() 552 { 553 return ExtSSTRecord.getRecordSizeForStrings(field_3_strings.size()); 554 } 555 } 556 557 558 | Popular Tags |