1 16 17 package org.apache.poi.hssf.eventmodel; 18 19 import java.io.IOException ; 20 import java.io.InputStream ; 21 import java.lang.reflect.Constructor ; 22 import java.util.ArrayList ; 23 import java.util.HashMap ; 24 import java.util.Iterator ; 25 import java.util.List ; 26 import java.util.Map ; 27 28 import org.apache.poi.hssf.record.BOFRecord; 29 import org.apache.poi.hssf.record.BackupRecord; 30 import org.apache.poi.hssf.record.BlankRecord; 31 import org.apache.poi.hssf.record.BookBoolRecord; 32 import org.apache.poi.hssf.record.BoolErrRecord; 33 import org.apache.poi.hssf.record.BottomMarginRecord; 34 import org.apache.poi.hssf.record.BoundSheetRecord; 35 import org.apache.poi.hssf.record.CalcCountRecord; 36 import org.apache.poi.hssf.record.CalcModeRecord; 37 import org.apache.poi.hssf.record.CodepageRecord; 38 import org.apache.poi.hssf.record.ColumnInfoRecord; 39 import org.apache.poi.hssf.record.ContinueRecord; 40 import org.apache.poi.hssf.record.CountryRecord; 41 import org.apache.poi.hssf.record.DBCellRecord; 42 import org.apache.poi.hssf.record.DSFRecord; 43 import org.apache.poi.hssf.record.DateWindow1904Record; 44 import org.apache.poi.hssf.record.DefaultColWidthRecord; 45 import org.apache.poi.hssf.record.DefaultRowHeightRecord; 46 import org.apache.poi.hssf.record.DeltaRecord; 47 import org.apache.poi.hssf.record.DimensionsRecord; 48 import org.apache.poi.hssf.record.EOFRecord; 49 import org.apache.poi.hssf.record.ExtSSTRecord; 50 import org.apache.poi.hssf.record.ExtendedFormatRecord; 51 import org.apache.poi.hssf.record.ExternSheetRecord; 52 import org.apache.poi.hssf.record.FnGroupCountRecord; 53 import org.apache.poi.hssf.record.FontRecord; 54 import org.apache.poi.hssf.record.FooterRecord; 55 import org.apache.poi.hssf.record.FormatRecord; 56 import org.apache.poi.hssf.record.GridsetRecord; 57 import org.apache.poi.hssf.record.GutsRecord; 58 import org.apache.poi.hssf.record.HCenterRecord; 59 import org.apache.poi.hssf.record.HeaderRecord; 60 import org.apache.poi.hssf.record.HideObjRecord; 61 import org.apache.poi.hssf.record.IndexRecord; 62 import org.apache.poi.hssf.record.InterfaceEndRecord; 63 import org.apache.poi.hssf.record.InterfaceHdrRecord; 64 import org.apache.poi.hssf.record.IterationRecord; 65 import org.apache.poi.hssf.record.LabelRecord; 66 import org.apache.poi.hssf.record.LabelSSTRecord; 67 import org.apache.poi.hssf.record.LeftMarginRecord; 68 import org.apache.poi.hssf.record.MMSRecord; 69 import org.apache.poi.hssf.record.MergeCellsRecord; 70 import org.apache.poi.hssf.record.MulBlankRecord; 71 import org.apache.poi.hssf.record.MulRKRecord; 72 import org.apache.poi.hssf.record.NameRecord; 73 import org.apache.poi.hssf.record.NumberRecord; 74 import org.apache.poi.hssf.record.PaletteRecord; 75 import org.apache.poi.hssf.record.PasswordRecord; 76 import org.apache.poi.hssf.record.PasswordRev4Record; 77 import org.apache.poi.hssf.record.PrecisionRecord; 78 import org.apache.poi.hssf.record.PrintGridlinesRecord; 79 import org.apache.poi.hssf.record.PrintHeadersRecord; 80 import org.apache.poi.hssf.record.PrintSetupRecord; 81 import org.apache.poi.hssf.record.ProtectRecord; 82 import org.apache.poi.hssf.record.ProtectionRev4Record; 83 import org.apache.poi.hssf.record.RKRecord; 84 import org.apache.poi.hssf.record.Record; 85 import org.apache.poi.hssf.record.RecordFormatException; 86 import org.apache.poi.hssf.record.RefModeRecord; 87 import org.apache.poi.hssf.record.RefreshAllRecord; 88 import org.apache.poi.hssf.record.RightMarginRecord; 89 import org.apache.poi.hssf.record.RowRecord; 90 import org.apache.poi.hssf.record.SSTRecord; 91 import org.apache.poi.hssf.record.SaveRecalcRecord; 92 import org.apache.poi.hssf.record.SelectionRecord; 93 import org.apache.poi.hssf.record.SharedFormulaRecord; 94 import org.apache.poi.hssf.record.StringRecord; 95 import org.apache.poi.hssf.record.StyleRecord; 96 import org.apache.poi.hssf.record.TabIdRecord; 97 import org.apache.poi.hssf.record.TopMarginRecord; 98 import org.apache.poi.hssf.record.UnknownRecord; 99 import org.apache.poi.hssf.record.UseSelFSRecord; 100 import org.apache.poi.hssf.record.VCenterRecord; 101 import org.apache.poi.hssf.record.WSBoolRecord; 102 import org.apache.poi.hssf.record.WindowOneRecord; 103 import org.apache.poi.hssf.record.WindowProtectRecord; 104 import org.apache.poi.hssf.record.WindowTwoRecord; 105 import org.apache.poi.hssf.record.WriteAccessRecord; 106 import org.apache.poi.util.LittleEndian; 107 108 109 120 public class EventRecordFactory 121 { 122 123 126 private static final Class [] records; 127 128 static { 129 records = new Class [] 130 { 131 BOFRecord.class, InterfaceHdrRecord.class, MMSRecord.class, 132 InterfaceEndRecord.class, WriteAccessRecord.class, 133 CodepageRecord.class, DSFRecord.class, TabIdRecord.class, 134 FnGroupCountRecord.class, WindowProtectRecord.class, 135 ProtectRecord.class, PasswordRecord.class, ProtectionRev4Record.class, 136 PasswordRev4Record.class, WindowOneRecord.class, BackupRecord.class, 137 HideObjRecord.class, DateWindow1904Record.class, 138 PrecisionRecord.class, RefreshAllRecord.class, BookBoolRecord.class, 139 FontRecord.class, FormatRecord.class, ExtendedFormatRecord.class, 140 StyleRecord.class, UseSelFSRecord.class, BoundSheetRecord.class, 141 CountryRecord.class, SSTRecord.class, ExtSSTRecord.class, 142 EOFRecord.class, IndexRecord.class, CalcModeRecord.class, 143 CalcCountRecord.class, RefModeRecord.class, IterationRecord.class, 144 DeltaRecord.class, SaveRecalcRecord.class, PrintHeadersRecord.class, 145 PrintGridlinesRecord.class, GridsetRecord.class, GutsRecord.class, 146 DefaultRowHeightRecord.class, WSBoolRecord.class, HeaderRecord.class, 147 FooterRecord.class, HCenterRecord.class, VCenterRecord.class, 148 PrintSetupRecord.class, DefaultColWidthRecord.class, 149 DimensionsRecord.class, RowRecord.class, LabelSSTRecord.class, 150 RKRecord.class, NumberRecord.class, DBCellRecord.class, 151 WindowTwoRecord.class, SelectionRecord.class, ContinueRecord.class, 152 LabelRecord.class, BlankRecord.class, ColumnInfoRecord.class, 153 MulRKRecord.class, MulBlankRecord.class, MergeCellsRecord.class, 154 BoolErrRecord.class, ExternSheetRecord.class, NameRecord.class, 155 LeftMarginRecord.class, RightMarginRecord.class, 156 TopMarginRecord.class, BottomMarginRecord.class, 157 PaletteRecord.class, StringRecord.class, SharedFormulaRecord.class 158 }; 159 160 } 161 162 165 private static Map recordsMap = recordsToMap(records); 166 167 171 private static short[] sidscache; 172 173 176 private List listeners; 177 178 181 private boolean abortable; 182 183 188 public EventRecordFactory() { 189 this(true); 190 } 191 192 198 public EventRecordFactory(boolean abortable) { 199 this.abortable = abortable; 200 listeners = new ArrayList (recordsMap.size()); 201 202 if (sidscache == null) { 203 sidscache = getAllKnownRecordSIDs(); 204 } 205 206 } 207 208 216 public void registerListener(ERFListener listener, short[] sids) { 217 if (sids == null) 218 sids = sidscache; 219 ERFListener wrapped = new ListenerWrapper(listener, sids, abortable); 220 listeners.add(wrapped); 221 } 222 223 227 protected Iterator listeners() { 228 return listeners.iterator(); 229 } 230 231 237 private boolean throwRecordEvent(Record record) 238 { 239 boolean result = true; 240 Iterator i = listeners.iterator(); 241 242 while (i.hasNext()) { 243 result = ((ERFListener) i.next()).processRecord(record); 244 if (abortable == true && result == false) { 245 break; 246 } 247 } 248 return result; 249 } 250 251 260 public void processRecords(InputStream in) 261 throws RecordFormatException 262 { 263 Record last_record = null; 264 265 try 266 { 267 short rectype = 0; 268 269 do 270 { 271 rectype = LittleEndian.readShort(in); 272 if (rectype != 0) 273 { 274 short recsize = LittleEndian.readShort(in); 275 byte[] data = new byte[ ( int ) recsize ]; 276 277 in.read(data); 278 Record[] recs = createRecord(rectype, recsize, 279 data); 281 if (recs.length > 1) 282 { 283 for (int k = 0; k < recs.length; k++) 284 { 285 if ( last_record != null ) { 286 if (throwRecordEvent(last_record) == false && abortable == true) { 287 last_record = null; 288 break; 289 } 290 } 291 last_record = 294 recs[ k ]; } } 297 else 298 { 299 Record record = recs[ 0 ]; 300 301 if (record != null) 302 { 303 if (rectype == ContinueRecord.sid && 304 ! (last_record instanceof ContinueRecord) && ! (last_record instanceof UnknownRecord) ) { 307 if (last_record == null) 308 { 309 throw new RecordFormatException( 310 "First record is a ContinueRecord??"); 311 } 312 last_record.processContinueRecord(data); 313 } 314 else 315 { 316 if (last_record != null) { 317 if (throwRecordEvent(last_record) == false && abortable == true) { 318 last_record = null; 319 break; 320 } 321 } 322 323 last_record = record; 324 325 } 327 } 328 } 329 } 330 } 331 while (rectype != 0); 332 333 if (last_record != null) { 334 throwRecordEvent(last_record); 335 } 336 } 337 catch (IOException e) 338 { 339 throw new RecordFormatException("Error reading bytes"); 340 } 341 342 345 } 346 347 351 public static Record [] createRecord(short rectype, short size, 352 byte [] data) 353 { 354 Record retval = null; 355 Record[] realretval = null; 356 357 try 358 { 359 Constructor constructor = 360 ( Constructor ) recordsMap.get(new Short (rectype)); 361 362 if (constructor != null) 363 { 364 retval = ( Record ) constructor.newInstance(new Object [] 365 { 366 new Short (rectype), new Short (size), data 367 }); 368 } 369 else 370 { 371 retval = new UnknownRecord(rectype, size, data); 372 } 373 } 374 catch (Exception introspectionException) 375 { 376 introspectionException.printStackTrace(); 377 throw new RecordFormatException( 378 "Unable to construct record instance, the following exception occured: " + introspectionException.getMessage()); 379 } 380 if (retval instanceof RKRecord) 381 { 382 RKRecord rk = ( RKRecord ) retval; 383 NumberRecord num = new NumberRecord(); 384 385 num.setColumn(rk.getColumn()); 386 num.setRow(rk.getRow()); 387 num.setXFIndex(rk.getXFIndex()); 388 num.setValue(rk.getRKNumber()); 389 retval = num; 390 } 391 else if (retval instanceof DBCellRecord) 392 { 393 retval = null; 394 } 395 else if (retval instanceof MulRKRecord) 396 { 397 MulRKRecord mrk = ( MulRKRecord ) retval; 398 399 realretval = new Record[ mrk.getNumColumns() ]; 400 for (int k = 0; k < mrk.getNumColumns(); k++) 401 { 402 NumberRecord nr = new NumberRecord(); 403 404 nr.setColumn(( short ) (k + mrk.getFirstColumn())); 405 nr.setRow(mrk.getRow()); 406 nr.setXFIndex(mrk.getXFAt(k)); 407 nr.setValue(mrk.getRKNumberAt(k)); 408 realretval[ k ] = nr; 409 } 410 } 411 else if (retval instanceof MulBlankRecord) 412 { 413 MulBlankRecord mb = ( MulBlankRecord ) retval; 414 415 realretval = new Record[ mb.getNumColumns() ]; 416 for (int k = 0; k < mb.getNumColumns(); k++) 417 { 418 BlankRecord br = new BlankRecord(); 419 420 br.setColumn(( short ) (k + mb.getFirstColumn())); 421 br.setRow(mb.getRow()); 422 br.setXFIndex(mb.getXFAt(k)); 423 realretval[ k ] = br; 424 } 425 } 426 if (realretval == null) 427 { 428 realretval = new Record[ 1 ]; 429 realretval[ 0 ] = retval; 430 } 431 return realretval; 432 } 433 434 437 public static short [] getAllKnownRecordSIDs() 438 { 439 short[] results = new short[ recordsMap.size() ]; 440 int i = 0; 441 442 for (Iterator iterator = recordsMap.keySet().iterator(); 443 iterator.hasNext(); ) 444 { 445 Short sid = ( Short ) iterator.next(); 446 447 results[ i++ ] = sid.shortValue(); 448 } 449 return results; 450 } 451 452 457 private static Map recordsToMap(Class [] records) 458 { 459 Map result = new HashMap (); 460 Constructor constructor; 461 462 for (int i = 0; i < records.length; i++) 463 { 464 Class record = null; 465 short sid = 0; 466 467 record = records[ i ]; 468 try 469 { 470 sid = record.getField("sid").getShort(null); 471 constructor = record.getConstructor(new Class [] 472 { 473 short.class, short.class, byte [].class 474 }); 475 } 476 catch (Exception illegalArgumentException) 477 { 478 throw new RecordFormatException( 479 "Unable to determine record types"); 480 } 481 result.put(new Short (sid), constructor); 482 } 483 return result; 484 } 485 486 } 487 488 492 class ListenerWrapper implements ERFListener { 493 private ERFListener listener; 494 private short[] sids; 495 private boolean abortable; 496 497 ListenerWrapper(ERFListener listener, short[] sids, boolean abortable) { 498 this.listener = listener; 499 this.sids = sids; 500 this.abortable = abortable; 501 } 502 503 504 public boolean processRecord(Record rec) 505 { 506 boolean result = true; 507 for (int k = 0; k < sids.length; k++) { 508 if (sids[k] == rec.getSid()) { 509 result = listener.processRecord(rec); 510 511 if (abortable == true && result == false) { 512 break; 513 } 514 } 515 } 516 return result; 517 } 518 } 519 | Popular Tags |