1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* $Id: FixedColRowGroupBuilder.java 1762060 2016-09-23 12:57:46Z ssteiner $ */ 19 20 package org.apache.fop.fo.flow.table; 21 22 import java.util.ArrayList; 23 import java.util.List; 24 25 import org.apache.fop.fo.Constants; 26 import org.apache.fop.fo.ValidationException; 27 28 29 /** 30 * A row group builder optimised for a fixed number of columns, known before the parsing 31 * of cells starts (that is, if the fo:table has explicit fo:table-column children). 32 */ 33 class FixedColRowGroupBuilder extends RowGroupBuilder { 34 35 /** Number of columns in the corresponding table. */ 36 private int numberOfColumns; 37 38 private TableRow currentTableRow; 39 40 /** 0-based, index in the row group. */ 41 private int currentRowIndex; 42 43 /** The rows belonging to this row group. List of List of {@link GridUnit}s. */ 44 private List<List<GridUnit>> rows; 45 46 private boolean firstInPart = true; 47 48 /** The last encountered row. This is the last row of the table if it has no footer. */ 49 private List lastRow; 50 51 private BorderResolver borderResolver; 52 FixedColRowGroupBuilder(Table t)53 FixedColRowGroupBuilder(Table t) { 54 super(t); 55 numberOfColumns = t.getNumberOfColumns(); 56 if (t.isSeparateBorderModel()) { 57 borderResolver = new SeparateBorderResolver(); 58 } else { 59 borderResolver = new CollapsingBorderResolver(t); 60 } 61 initialize(); 62 } 63 64 /** 65 * Prepares this builder for creating a new row group. 66 */ initialize()67 private void initialize() { 68 rows = new ArrayList(); 69 currentRowIndex = 0; 70 } 71 72 /** {@inheritDoc} */ addTableCell(TableCell cell)73 void addTableCell(TableCell cell) { 74 for (int i = rows.size(); i < currentRowIndex + cell.getNumberRowsSpanned(); i++) { 75 List effRow = new ArrayList(numberOfColumns); 76 for (int j = 0; j < numberOfColumns; j++) { 77 effRow.add(null); 78 } 79 rows.add(effRow); 80 } 81 int columnIndex = cell.getColumnNumber() - 1; 82 PrimaryGridUnit pgu = new PrimaryGridUnit(cell, columnIndex); 83 List row = (List) rows.get(currentRowIndex); 84 row.set(columnIndex, pgu); 85 // TODO 86 GridUnit[] cellRow = new GridUnit[cell.getNumberColumnsSpanned()]; 87 cellRow[0] = pgu; 88 for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) { 89 GridUnit gu = new GridUnit(pgu, j, 0); 90 row.set(columnIndex + j, gu); 91 cellRow[j] = gu; 92 } 93 pgu.addRow(cellRow); 94 for (int i = 1; i < cell.getNumberRowsSpanned(); i++) { 95 row = (List) rows.get(currentRowIndex + i); 96 cellRow = new GridUnit[cell.getNumberColumnsSpanned()]; 97 for (int j = 0; j < cell.getNumberColumnsSpanned(); j++) { 98 GridUnit gu = new GridUnit(pgu, j, i); 99 row.set(columnIndex + j, gu); 100 cellRow[j] = gu; 101 } 102 pgu.addRow(cellRow); 103 } 104 } 105 setFlagForCols(int flag, List row)106 private static void setFlagForCols(int flag, List row) { 107 for (Object aRow : row) { 108 ((GridUnit) aRow).setFlag(flag); 109 } 110 } 111 112 /** {@inheritDoc} */ startTableRow(TableRow tableRow)113 void startTableRow(TableRow tableRow) { 114 currentTableRow = tableRow; 115 } 116 117 /** {@inheritDoc} */ endTableRow()118 void endTableRow() { 119 assert currentTableRow != null; 120 if (currentRowIndex > 0 && currentTableRow.getBreakBefore() != Constants.EN_AUTO) { 121 TableEventProducer eventProducer = TableEventProducer.Provider.get( 122 currentTableRow.getUserAgent().getEventBroadcaster()); 123 eventProducer.breakIgnoredDueToRowSpanning(this, currentTableRow.getName(), true, 124 currentTableRow.getLocator()); 125 } 126 if (currentRowIndex < rows.size() - 1 127 && currentTableRow.getBreakAfter() != Constants.EN_AUTO) { 128 TableEventProducer eventProducer = TableEventProducer.Provider.get( 129 currentTableRow.getUserAgent().getEventBroadcaster()); 130 eventProducer.breakIgnoredDueToRowSpanning(this, currentTableRow.getName(), false, 131 currentTableRow.getLocator()); 132 } 133 for (Object o : ((List) rows.get(currentRowIndex))) { 134 GridUnit gu = (GridUnit) o; 135 // The row hasn't been filled with empty grid units yet 136 if (gu != null) { 137 gu.setRow(currentTableRow); 138 } 139 } 140 handleRowEnd(currentTableRow); 141 } 142 143 /** {@inheritDoc} */ endRow(TablePart part)144 void endRow(TablePart part) { 145 handleRowEnd(part); 146 } 147 handleRowEnd(TableCellContainer container)148 private void handleRowEnd(TableCellContainer container) { 149 List currentRow = (List) rows.get(currentRowIndex); 150 lastRow = currentRow; 151 // Fill gaps with empty grid units 152 for (int i = 0; i < numberOfColumns; i++) { 153 if (currentRow.get(i) == null) { 154 currentRow.set(i, new EmptyGridUnit(table, currentTableRow, i)); 155 } 156 } 157 borderResolver.endRow(currentRow, container); 158 if (firstInPart) { 159 setFlagForCols(GridUnit.FIRST_IN_PART, currentRow); 160 firstInPart = false; 161 } 162 if (currentRowIndex == rows.size() - 1) { 163 // Means that the current row has no cell spanning over following rows 164 container.getTablePart().addRowGroup(rows); 165 initialize(); 166 } else { 167 currentRowIndex++; 168 } 169 currentTableRow = null; 170 } 171 172 /** {@inheritDoc} */ startTablePart(TablePart part)173 void startTablePart(TablePart part) { 174 firstInPart = true; 175 borderResolver.startPart(part); 176 } 177 178 /** {@inheritDoc} */ endTablePart()179 void endTablePart() throws ValidationException { 180 if (rows.size() > 0) { 181 throw new ValidationException( 182 "A table-cell is spanning more rows than available in its parent element."); 183 } 184 setFlagForCols(GridUnit.LAST_IN_PART, lastRow); 185 borderResolver.endPart(); 186 } 187 188 /** {@inheritDoc} */ endTable()189 void endTable() { 190 borderResolver.endTable(); 191 } 192 } 193