1 17 18 19 20 package org.apache.fop.layoutmgr.table; 21 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.ListIterator ; 25 26 import org.apache.commons.logging.Log; 27 import org.apache.commons.logging.LogFactory; 28 import org.apache.fop.fo.flow.Marker; 29 import org.apache.fop.fo.flow.Table; 30 import org.apache.fop.fo.flow.TableBody; 31 import org.apache.fop.fo.flow.TableCell; 32 import org.apache.fop.fo.flow.TableColumn; 33 import org.apache.fop.fo.flow.TableRow; 34 import org.apache.fop.fo.properties.CommonBorderPaddingBackground; 35 36 37 42 public class TableRowIterator { 43 44 45 public static final int BODY = 0; 46 47 public static final int HEADER = 1; 48 49 public static final int FOOTER = 2; 50 51 52 private static Log log = LogFactory.getLog(TableRowIterator.class); 53 54 55 protected Table table; 56 57 private ColumnSetup columns; 58 59 60 private int tablePart; 61 62 63 private List currentRow = new java.util.ArrayList (); 64 65 70 private List previousRowsSpanningCells = new java.util.ArrayList (); 71 72 73 private int fetchIndex = -1; 74 75 76 private int pendingRowSpans; 77 78 81 private List fetchedRows = new java.util.ArrayList (); 82 83 88 private int iteratorIndex = 0; 89 90 95 private ListIterator tablePartIterator = null; 96 97 private ListIterator tablePartChildIterator = null; 98 99 105 public TableRowIterator(Table table, ColumnSetup columns, int tablePart) { 106 this.table = table; 107 this.columns = columns; 108 this.tablePart = tablePart; 109 switch(tablePart) { 110 case HEADER: { 111 List bodyList = new java.util.ArrayList (); 112 bodyList.add(table.getTableHeader()); 113 this.tablePartIterator = bodyList.listIterator(); 114 break; 115 } 116 case FOOTER: { 117 List bodyList = new java.util.ArrayList (); 118 bodyList.add(table.getTableFooter()); 119 this.tablePartIterator = bodyList.listIterator(); 120 break; 121 } 122 default: { 123 this.tablePartIterator = table.getChildNodes(); 124 } 125 } 126 } 127 128 132 public void prefetchAll() { 133 while (prefetchNext()) { 134 log.trace("found row..."); 135 } 136 } 137 138 143 public EffRow[] getNextRowGroup() { 144 EffRow firstRowInGroup = getNextRow(); 145 if (firstRowInGroup == null) { 146 return null; 147 } 148 EffRow lastRowInGroup = firstRowInGroup; 149 int lastIndex = lastRowInGroup.getIndex(); 150 boolean allFinished; 151 do { 152 allFinished = true; 153 Iterator iter = lastRowInGroup.getGridUnits().iterator(); 154 while (iter.hasNext()) { 155 GridUnit gu = (GridUnit)iter.next(); 156 if (!gu.isLastGridUnitRowSpan()) { 157 allFinished = false; 158 break; 159 } 160 } 161 lastIndex = lastRowInGroup.getIndex(); 162 if (!allFinished) { 163 lastRowInGroup = getNextRow(); 164 if (lastRowInGroup == null) { 165 allFinished = true; 166 } 167 } 168 } while (!allFinished); 169 int rowCount = lastIndex - firstRowInGroup.getIndex() + 1; 170 EffRow[] rowGroup = new EffRow[rowCount]; 171 for (int i = 0; i < rowCount; i++) { 172 rowGroup[i] = getCachedRow(i + firstRowInGroup.getIndex()); 173 } 174 return rowGroup; 175 } 176 177 184 private EffRow getRow(int index) { 185 boolean moreRows = true; 186 while (moreRows && fetchedRows.size() <= index) { 187 moreRows = prefetchNext(); 188 } 189 return getCachedRow(index); 191 } 192 193 197 private EffRow getNextRow() { 198 return getRow(iteratorIndex++); 199 } 200 201 208 public EffRow getPrecedingRow(EffRow row) { 209 return getRow(row.getIndex() - 1); 210 } 211 212 218 public EffRow getFollowingRow(EffRow row) { 219 return getRow(row.getIndex() + 1); 220 } 221 222 225 public void backToPreviousRow() { 226 iteratorIndex--; 227 } 228 229 233 public EffRow getFirstRow() { 234 if (fetchedRows.size() == 0) { 235 prefetchNext(); 236 } 237 return getCachedRow(0); 238 } 239 240 246 public EffRow getLastRow() { 247 while (prefetchNext()) { 248 } 250 return getCachedRow(fetchedRows.size() - 1); 251 } 252 253 262 public EffRow getCachedRow(int index) { 263 if (index < 0 || index >= fetchedRows.size()) { 264 return null; 265 } else { 266 return (EffRow)fetchedRows.get(index); 267 } 268 } 269 270 276 private boolean prefetchNext() { 277 boolean firstInTable = false; 278 boolean firstInTablePart = false; 279 if (tablePartChildIterator != null && !tablePartChildIterator.hasNext()) { 281 if (pendingRowSpans > 0) { 283 this.currentRow.clear(); 284 this.fetchIndex++; 285 EffRow gridUnits = buildGridRow(this.currentRow, null); 286 log.debug(gridUnits); 287 fetchedRows.add(gridUnits); 288 return true; 289 } 290 tablePartChildIterator = null; 291 if (fetchedRows.size() > 0) { 292 getCachedRow(fetchedRows.size() - 1).setFlagForAllGridUnits( 293 GridUnit.LAST_IN_PART, true); 294 } 295 } 296 if (tablePartChildIterator == null) { 298 if (tablePartIterator.hasNext()) { 299 tablePartChildIterator = ((TableBody)tablePartIterator.next()).getChildNodes(); 300 if (fetchedRows.size() == 0) { 301 firstInTable = true; 302 } 303 firstInTablePart = true; 304 } else { 305 if (fetchedRows.size() > 0) { 307 getCachedRow(fetchedRows.size() - 1).setFlagForAllGridUnits( 308 GridUnit.LAST_IN_PART, true); 309 if (tablePart == FOOTER 311 || (tablePart == BODY && table.getTableFooter() == null)) { 312 getCachedRow(fetchedRows.size() - 1).setFlagForAllGridUnits( 313 GridUnit.LAST_IN_TABLE, true); 314 } 315 } 316 return false; 317 } 318 } 319 Object node = tablePartChildIterator.next(); 320 while (node instanceof Marker) { 321 node = tablePartChildIterator.next(); 322 } 323 this.currentRow.clear(); 324 this.fetchIndex++; 325 TableRow rowFO = null; 326 if (node instanceof TableRow) { 327 rowFO = (TableRow)node; 328 ListIterator cellIterator = rowFO.getChildNodes(); 329 while (cellIterator.hasNext()) { 330 this.currentRow.add(cellIterator.next()); 331 } 332 } else if (node instanceof TableCell) { 333 this.currentRow.add(node); 334 if (!((TableCell)node).endsRow()) { 335 while (tablePartChildIterator.hasNext()) { 336 TableCell cell = (TableCell)tablePartChildIterator.next(); 337 if (cell.startsRow()) { 338 tablePartChildIterator.previous(); 340 break; 341 } 342 this.currentRow.add(cell); 343 if (cell.endsRow()) { 344 break; 345 } 346 } 347 } 348 } else { 349 throw new IllegalStateException ("Illegal class found: " + node.getClass().getName()); 350 } 351 EffRow gridUnits = buildGridRow(this.currentRow, rowFO); 352 if (firstInTablePart) { 353 gridUnits.setFlagForAllGridUnits(GridUnit.FIRST_IN_PART, true); 354 } 355 if (firstInTable && (tablePart == HEADER || table.getTableHeader() == null) 356 && tablePart != FOOTER) { 357 gridUnits.setFlagForAllGridUnits(GridUnit.FIRST_IN_TABLE, true); 358 } 359 log.debug(gridUnits); 360 fetchedRows.add(gridUnits); 361 return true; 362 } 363 364 372 private void safelySetListItem(List list, int position, Object obj) { 373 while (position >= list.size()) { 374 list.add(null); 375 } 376 list.set(position, obj); 377 } 378 379 private Object safelyGetListItem(List list, int position) { 380 if (position >= list.size()) { 381 return null; 382 } else { 383 return list.get(position); 384 } 385 } 386 387 394 private EffRow buildGridRow(List cells, TableRow rowFO) { 395 EffRow row = new EffRow(this.fetchIndex, tablePart); 396 List gridUnits = row.getGridUnits(); 397 398 TableBody bodyFO = null; 399 400 int colnum = 1; 402 GridUnit[] horzSpan = null; if (pendingRowSpans > 0) { 404 ListIterator spanIter = previousRowsSpanningCells.listIterator(); 405 while (spanIter.hasNext()) { 406 GridUnit gu = (GridUnit)spanIter.next(); 407 if (gu != null) { 408 if (gu.getColSpanIndex() == 0) { 409 horzSpan = new GridUnit[gu.getCell().getNumberColumnsSpanned()]; 410 } 411 GridUnit newGU = gu.createNextRowSpanningGridUnit(); 412 newGU.setRow(rowFO); 413 safelySetListItem(gridUnits, colnum - 1, newGU); 414 horzSpan[newGU.getColSpanIndex()] = newGU; 415 if (newGU.isLastGridUnitColSpan()) { 416 newGU.getPrimary().addRow(horzSpan); 418 horzSpan = null; 419 } 420 if (newGU.isLastGridUnitRowSpan()) { 421 spanIter.set(null); 422 pendingRowSpans--; 423 } else { 424 spanIter.set(newGU); 425 } 426 } 427 colnum++; 428 } 429 } 430 if (pendingRowSpans < 0) { 431 throw new IllegalStateException ("pendingRowSpans must not become negative!"); 432 } 433 434 colnum = 1; 436 ListIterator iter = cells.listIterator(); 437 while (iter.hasNext()) { 438 TableCell cell = (TableCell)iter.next(); 439 440 colnum = cell.getColumnNumber(); 441 442 GridUnit other = (GridUnit)safelyGetListItem(gridUnits, colnum - 1); 447 if (other != null) { 448 String err = "A table-cell (" 449 + cell.getContextInfo() 450 + ") is overlapping with another (" 451 + other.getCell().getContextInfo() 452 + ") in column " + colnum; 453 throw new IllegalStateException (err 454 + " (this should have been catched by FO tree validation)"); 455 } 456 TableColumn col = columns.getColumn(colnum); 457 458 PrimaryGridUnit gu = new PrimaryGridUnit(cell, col, colnum - 1, this.fetchIndex); 460 safelySetListItem(gridUnits, colnum - 1, gu); 461 boolean hasRowSpanningLeft = !gu.isLastGridUnitRowSpan(); 462 if (hasRowSpanningLeft) { 463 pendingRowSpans++; 464 safelySetListItem(previousRowsSpanningCells, colnum - 1, gu); 465 } 466 467 if (gu.hasSpanning()) { 468 horzSpan = new GridUnit[cell.getNumberColumnsSpanned()]; 470 horzSpan[0] = gu; 471 for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) { 472 colnum++; 473 GridUnit guSpan = new GridUnit(gu, columns.getColumn(colnum), colnum - 1, j); 474 other = (GridUnit)safelyGetListItem(gridUnits, colnum - 1); 476 if (other != null) { 477 String err = "A table-cell (" 478 + cell.getContextInfo() 479 + ") is overlapping with another (" 480 + other.getCell().getContextInfo() 481 + ") in column " + colnum; 482 throw new IllegalStateException (err 483 + " (this should have been catched by FO tree validation)"); 484 } 485 safelySetListItem(gridUnits, colnum - 1, guSpan); 486 if (hasRowSpanningLeft) { 487 pendingRowSpans++; 488 safelySetListItem(previousRowsSpanningCells, colnum - 1, gu); 489 } 490 horzSpan[j] = guSpan; 491 } 492 gu.addRow(horzSpan); 493 } 494 495 if (bodyFO == null) { 497 bodyFO = gu.getBody(); 498 } 499 500 colnum++; 501 } 502 503 fillEmptyGridUnits(gridUnits, rowFO, bodyFO); 505 resolveStartEndBorders(gridUnits); 506 507 return row; 508 } 509 510 private void fillEmptyGridUnits(List gridUnits, TableRow row, TableBody body) { 511 for (int pos = 1; pos <= gridUnits.size(); pos++) { 512 GridUnit gu = (GridUnit)gridUnits.get(pos - 1); 513 514 if (gu == null) { 516 gu = new EmptyGridUnit(row, columns.getColumn(pos), body, 518 pos - 1); 519 gridUnits.set(pos - 1, gu); 520 } 521 522 gu.setFlag(GridUnit.IN_FIRST_COLUMN, (pos == 1)); 524 gu.setFlag(GridUnit.IN_LAST_COLUMN, (pos == gridUnits.size())); 525 } 526 } 527 528 private void resolveStartEndBorders(List gridUnits) { 529 for (int pos = 1; pos <= gridUnits.size(); pos++) { 530 GridUnit starting = (GridUnit)gridUnits.get(pos - 1); 531 532 if (table.isSeparateBorderModel()) { 534 starting.assignBorderForSeparateBorderModel(); 535 } else { 536 GridUnit start = null; 538 int find = pos - 1; 539 while (find >= 1) { 540 GridUnit candidate = (GridUnit)gridUnits.get(find - 1); 541 if (candidate.isLastGridUnitColSpan()) { 542 start = candidate; 543 break; 544 } 545 find--; 546 } 547 548 GridUnit ending = null; 550 if (starting.getCell() != null) { 551 pos += starting.getCell().getNumberColumnsSpanned() - 1; 552 } 553 ending = (GridUnit)gridUnits.get(pos - 1); 554 555 GridUnit end = null; 557 find = pos + 1; 558 while (find <= gridUnits.size()) { 559 GridUnit candidate = (GridUnit)gridUnits.get(find - 1); 560 if (candidate.isPrimary()) { 561 end = candidate; 562 break; 563 } 564 find++; 565 } 566 starting.resolveBorder(start, 567 CommonBorderPaddingBackground.START); 568 ending.resolveBorder(end, 569 CommonBorderPaddingBackground.END); 570 } 572 } 573 } 574 575 } 576 | Popular Tags |