From 2a762125322db82658fb650b131f80ed600fc93d Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Mon, 5 Nov 2007 16:07:45 +0000 Subject: [PATCH] First step towards building row groups at the FO tree stage. The built row groups are currently not used and the TableRowIterator stuff remains unchanged; this allows for more atomic commits. - introduced RowGroupBuilder hierarchy; - moved TableRowIterator test cases into fotree, and integrated them in the test suite. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@592058 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/fo/flow/FixedColRowGroupBuilder.java | 35 +++ .../apache/fop/fo/flow/RowGroupBuilder.java | 132 +++++++++ src/java/org/apache/fop/fo/flow/Table.java | 57 +++- .../org/apache/fop/fo/flow/TableBody.java | 17 ++ .../fop/fo/flow/TableCellContainer.java | 2 + .../org/apache/fop/fo/flow/TableFooter.java | 2 + .../org/apache/fop/fo/flow/TableHeader.java | 2 + .../fo/flow/VariableColRowGroupBuilder.java | 64 +++++ .../TableRowIterator_no-col_no-row_simple.fo | 196 +++++++++++++ .../TableRowIterator_no-col_no-row_spans.fo | 122 +++++++++ .../table/TableRowIterator_no-col_simple.fo | 257 ++++++++++++++++++ .../table/TableRowIterator_no-col_spans.fo | 169 ++++++++++++ .../table/TableRowIterator_no-row_simple.fo | 0 .../table/TableRowIterator_no-row_spans.fo | 0 .../table/TableRowIterator_simple.fo | 0 .../table/TableRowIterator_spans.fo | 0 .../fop/fo/flow/AbstractTableTestCase.java | 6 + .../flow/TableColumnColumnNumberTestCase.java | 4 +- .../fop/fo/flow/TableRowIteratorTestCase.java | 201 ++++++++++++++ .../table/TableRowIteratorTestCase.java | 209 -------------- 20 files changed, 1255 insertions(+), 220 deletions(-) create mode 100644 src/java/org/apache/fop/fo/flow/FixedColRowGroupBuilder.java create mode 100644 src/java/org/apache/fop/fo/flow/RowGroupBuilder.java create mode 100644 src/java/org/apache/fop/fo/flow/VariableColRowGroupBuilder.java create mode 100644 test/fotree/unittests/table/TableRowIterator_no-col_no-row_simple.fo create mode 100644 test/fotree/unittests/table/TableRowIterator_no-col_no-row_spans.fo create mode 100644 test/fotree/unittests/table/TableRowIterator_no-col_simple.fo create mode 100644 test/fotree/unittests/table/TableRowIterator_no-col_spans.fo rename test/{layoutmgr => fotree/unittests}/table/TableRowIterator_no-row_simple.fo (100%) rename test/{layoutmgr => fotree/unittests}/table/TableRowIterator_no-row_spans.fo (100%) rename test/{layoutmgr => fotree/unittests}/table/TableRowIterator_simple.fo (100%) rename test/{layoutmgr => fotree/unittests}/table/TableRowIterator_spans.fo (100%) create mode 100644 test/java/org/apache/fop/fo/flow/TableRowIteratorTestCase.java delete mode 100644 test/java/org/apache/fop/layoutmgr/table/TableRowIteratorTestCase.java diff --git a/src/java/org/apache/fop/fo/flow/FixedColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/FixedColRowGroupBuilder.java new file mode 100644 index 000000000..5a4bd24b2 --- /dev/null +++ b/src/java/org/apache/fop/fo/flow/FixedColRowGroupBuilder.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo.flow; + + +/** + * A row group builder optimised for a fixed number of columns, known before the parsing + * of cells starts (that is, if the fo:table has explicit fo:table-column children). + */ +class FixedColRowGroupBuilder extends RowGroupBuilder { + + + FixedColRowGroupBuilder(Table t) { + super(t); + numberOfColumns = t.getNumberOfColumns(); + } + +} diff --git a/src/java/org/apache/fop/fo/flow/RowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/RowGroupBuilder.java new file mode 100644 index 000000000..359ccd59a --- /dev/null +++ b/src/java/org/apache/fop/fo/flow/RowGroupBuilder.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo.flow; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.fop.layoutmgr.table.GridUnit; +import org.apache.fop.layoutmgr.table.PrimaryGridUnit; + +/** + * A class that creates groups of rows belonging to a same set of spans. The first row of + * such a group has only cells which don't span over several rows, or whose spanning + * starts on this row. Similarly, the last row has only non-row spanning cells or spans + * which end on this row. + */ +abstract class RowGroupBuilder { + + /** Number of columns in the corresponding table. */ + protected int numberOfColumns; + + /** 0-based, index in the row group. */ + private int currentRowIndex; + + private Table table; + + /** The rows belonging to this row group. List of List of {@link GridUnit}s. */ + protected List rows; + + /** + * Creates and initialises a new builder for the given table. + * + * @param t a table + */ + protected RowGroupBuilder(Table t) { + table = t; + initialize(); + } + + /** + * Prepares this builder for creating a new row group. + */ + private void initialize() { + rows = new ArrayList(); + currentRowIndex = 0; + } + + /** + * Adds a table-cell to the row-group, creating {@link GridUnit}s accordingly. + * + * @param cell + */ + void addTableCell(TableCell cell) { + for (int i = rows.size(); i < currentRowIndex + cell.getNumberRowsSpanned(); i++) { + List effRow = new ArrayList(numberOfColumns); + for (int j = 0; j < numberOfColumns; j++) { + effRow.add(null); + } + rows.add(effRow); + } + int columnIndex = cell.getColumnNumber() - 1; + PrimaryGridUnit pgu = new PrimaryGridUnit(cell, table.getColumn(columnIndex), columnIndex, + currentRowIndex); + List row = (List) rows.get(currentRowIndex); + row.set(columnIndex, pgu); + for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) { + row.set(j + columnIndex, + new GridUnit(pgu, table.getColumn(columnIndex + j), columnIndex + j, j)); + } + for (int i = 1; i < cell.getNumberRowsSpanned(); i++) { + row = (List) rows.get(currentRowIndex + i); + for (int j = 0; j < cell.getNumberColumnsSpanned(); j++) { + row.set(j + columnIndex, + new GridUnit(pgu, table.getColumn(columnIndex + j), columnIndex + j, j)); + } + } + + } + + /** + * Signals that a table row has just ended, potentially finishing the current row + * group. + * + * @param body the table-body containing the row. Its + * {@link TableBody#addRowGroup(List)} method will be called if the current row group + * is finished. + */ + void signalNewRow(TableBody body) { + if (currentRowIndex == rows.size() - 1) { + // Means that the current row has no cell spanning over following rows + body.addRowGroup(rows); + initialize(); + } else { + currentRowIndex++; + } + } + + /** + * Finishes and records the last row-group of the given table-body, if any. If there + * is no fo:table-row and the last cell of the table-body didn't have ends-row="true", + * then the {@link signalNewRow} method has not been called and the last row group has + * yet to be recorded. + * + * @param tableBody + */ + void finishLastRowGroup(TableBody tableBody) { + if (rows.size() > 0) { + tableBody.addRowGroup(rows); + } + // Reset, in case this rowGroupBuilder is re-used for other + // table-header/footer/body + initialize(); + } + +} diff --git a/src/java/org/apache/fop/fo/flow/Table.java b/src/java/org/apache/fop/fo/flow/Table.java index 87f224c65..ab58686fc 100644 --- a/src/java/org/apache/fop/fo/flow/Table.java +++ b/src/java/org/apache/fop/fo/flow/Table.java @@ -20,13 +20,13 @@ package org.apache.fop.fo.flow; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.ValidationPercentBaseContext; import org.apache.fop.fo.FONode; -import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.StaticPropertyList; import org.apache.fop.fo.ValidationException; @@ -86,6 +86,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { private boolean hasExplicitColumns = false; private boolean columnsFinalized = false; + private RowGroupBuilder rowGroupBuilder; /** * The table's property list. Used in case the table has @@ -226,6 +227,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { } } this.propList = null; + rowGroupBuilder = null; } getFOEventHandler().endTable(this); @@ -250,9 +252,15 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { case FO_TABLE_HEADER: case FO_TABLE_FOOTER: case FO_TABLE_BODY: - if (hasExplicitColumns && !columnsFinalized) { + if (!columnsFinalized) { columnsFinalized = true; - finalizeColumns(); + if (hasExplicitColumns) { + finalizeColumns(); + rowGroupBuilder = new FixedColRowGroupBuilder(this); + } else { + rowGroupBuilder = new VariableColRowGroupBuilder(this); + } + } switch (childId) { case FO_TABLE_FOOTER: @@ -293,9 +301,36 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { * columns */ void ensureColumnNumber(int columnNumber) throws FOPException { + assert !hasExplicitColumns; for (int i = columns.size() + 1; i <= columnNumber; i++) { columns.add(createImplicitColumn(i)); } + ((VariableColRowGroupBuilder) rowGroupBuilder).ensureNumberOfColumns(columnNumber); + if (tableHeader != null) { + for (Iterator iter = tableHeader.getRowGroups().iterator(); iter.hasNext();) { + VariableColRowGroupBuilder.fillWithEmptyGridUnits((List) iter.next(), + columnNumber); + } + } + if (tableFooter != null) { + for (Iterator iter = tableFooter.getRowGroups().iterator(); iter.hasNext();) { + VariableColRowGroupBuilder.fillWithEmptyGridUnits((List) iter.next(), + columnNumber); + } + } + FONodeIterator bodyIter = getChildNodes(); + if (bodyIter != null) { + while (bodyIter.hasNext()) { + FONode node = bodyIter.nextNode(); + if (node instanceof TableBody) { // AFAIK, may be a marker + for (Iterator iter = ((TableBody) node).getRowGroups().iterator(); + iter.hasNext();) { + VariableColRowGroupBuilder.fillWithEmptyGridUnits((List) iter.next(), + columnNumber); + } + } + } + } } private TableColumn createImplicitColumn(int colNumber) @@ -499,18 +534,22 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { */ public FONode clone(FONode parent, boolean removeChildren) throws FOPException { - FObj fobj = (FObj) super.clone(parent, removeChildren); + Table clone = (Table) super.clone(parent, removeChildren); + clone.columnsFinalized = false; if (removeChildren) { - Table t = (Table) fobj; - t.columns = new ArrayList(); - t.tableHeader = null; - t.tableFooter = null; + clone.columns = new ArrayList(); + clone.tableHeader = null; + clone.tableFooter = null; } - return fobj; + return clone; } /** {@inheritDoc} */ public ColumnNumberManager getColumnNumberManager() { return columnNumberManager; } + + RowGroupBuilder getRowGroupBuilder() { + return rowGroupBuilder; + } } diff --git a/src/java/org/apache/fop/fo/flow/TableBody.java b/src/java/org/apache/fop/fo/flow/TableBody.java index 72c0ff610..e8e1183b3 100644 --- a/src/java/org/apache/fop/fo/flow/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/TableBody.java @@ -20,6 +20,8 @@ package org.apache.fop.fo.flow; import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; @@ -55,6 +57,8 @@ public class TableBody extends TableCellContainer { private boolean rowsStarted = false; + private List rowGroups = new LinkedList(); + /** * @param parent FONode that is the parent of the object */ @@ -119,6 +123,8 @@ public class TableBody extends TableCellContainer { + "Expected: marker* (table-row+|table-cell+)"); getParent().removeChild(this); } + } else { + getTable().getRowGroupBuilder().finishLastRowGroup(this); } } @@ -165,6 +171,7 @@ public class TableBody extends TableCellContainer { case FO_TABLE_ROW: if (rowsStarted) { columnNumberManager.prepareForNextRow(pendingSpans); + getTable().getRowGroupBuilder().signalNewRow(this); } rowsStarted = true; break; @@ -175,6 +182,7 @@ public class TableBody extends TableCellContainer { if (cell.endsRow()) { firstRow = false; columnNumberManager.prepareForNextRow(pendingSpans); + getTable().getRowGroupBuilder().signalNewRow(this); } break; default: @@ -184,6 +192,14 @@ public class TableBody extends TableCellContainer { super.addChildNode(child); } + void addRowGroup(List rowGroup) { + rowGroups.add(rowGroup); + } + + List getRowGroups() { + return rowGroups; + } + /** * @return the Common Border, Padding, and Background Properties. */ @@ -218,6 +234,7 @@ public class TableBody extends TableCellContainer { TableCell previousCell = (TableCell) getChildNodes().lastNode(); if (!previousCell.endsRow()) { columnNumberManager.prepareForNextRow(pendingSpans); + getTable().getRowGroupBuilder().signalNewRow(this); } } rowsStarted = true; diff --git a/src/java/org/apache/fop/fo/flow/TableCellContainer.java b/src/java/org/apache/fop/fo/flow/TableCellContainer.java index 9f9b72d75..c409e01af 100644 --- a/src/java/org/apache/fop/fo/flow/TableCellContainer.java +++ b/src/java/org/apache/fop/fo/flow/TableCellContainer.java @@ -95,6 +95,8 @@ public abstract class TableCellContainer extends TableFObj implements ColumnNumb } columnNumberManager.signalUsedColumnNumbers(colNumber, colNumber + colSpan - 1); + + t.getRowGroupBuilder().addTableCell(cell); } private void handleCellWidth(TableCell cell, int colNumber, int colSpan) throws FOPException { diff --git a/src/java/org/apache/fop/fo/flow/TableFooter.java b/src/java/org/apache/fop/fo/flow/TableFooter.java index a543ca11f..a16586af9 100644 --- a/src/java/org/apache/fop/fo/flow/TableFooter.java +++ b/src/java/org/apache/fop/fo/flow/TableFooter.java @@ -50,6 +50,8 @@ public class TableFooter extends TableBody { // getFOEventHandler().endFooter(this); if (!(tableRowsFound || tableCellsFound)) { missingChildElementError("marker* (table-row+|table-cell+)"); + } else { + getTable().getRowGroupBuilder().finishLastRowGroup(this); } // convertCellsToRows(); } diff --git a/src/java/org/apache/fop/fo/flow/TableHeader.java b/src/java/org/apache/fop/fo/flow/TableHeader.java index 568303c0d..eb3568d47 100644 --- a/src/java/org/apache/fop/fo/flow/TableHeader.java +++ b/src/java/org/apache/fop/fo/flow/TableHeader.java @@ -50,6 +50,8 @@ public class TableHeader extends TableBody { // getFOEventHandler().endHeader(this); if (!(tableRowsFound || tableCellsFound)) { missingChildElementError("marker* (table-row+|table-cell+)"); + } else { + getTable().getRowGroupBuilder().finishLastRowGroup(this); } // convertCellsToRows(); } diff --git a/src/java/org/apache/fop/fo/flow/VariableColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/VariableColRowGroupBuilder.java new file mode 100644 index 000000000..a59c98786 --- /dev/null +++ b/src/java/org/apache/fop/fo/flow/VariableColRowGroupBuilder.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo.flow; + +import java.util.List; + +import org.apache.fop.layoutmgr.table.EmptyGridUnit; + +/** + * A row group builder accommodating a variable number of columns. More flexible, but less + * efficient. + */ +class VariableColRowGroupBuilder extends RowGroupBuilder { + + VariableColRowGroupBuilder(Table t) { + super(t); + numberOfColumns = 1; + } + + /** + * Fills the given row group with empty grid units if necessary, so that it matches + * the given number of columns. + * + * @param rowGroup a List of List of GridUnit + * @param numberOfColumns the number of columns that the row group must have + */ + static void fillWithEmptyGridUnits(List rowGroup, int numberOfColumns) { + for (int i = 0; i < rowGroup.size(); i++) { + List effRow = (List) rowGroup.get(i); + for (int j = effRow.size(); j < numberOfColumns; j++) { + effRow.add(new EmptyGridUnit(null, null, null, j)); + } + } + } + + /** + * Updates the current row group to match the given number of columns, by adding empty + * grid units if necessary. + * + * @param numberOfColumns new number of columns + */ + void ensureNumberOfColumns(int numberOfColumns) { + this.numberOfColumns = numberOfColumns; + fillWithEmptyGridUnits(rows, numberOfColumns); + } + +} diff --git a/test/fotree/unittests/table/TableRowIterator_no-col_no-row_simple.fo b/test/fotree/unittests/table/TableRowIterator_no-col_no-row_simple.fo new file mode 100644 index 000000000..0d35a2bb9 --- /dev/null +++ b/test/fotree/unittests/table/TableRowIterator_no-col_no-row_simple.fo @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + Cell 1 + Cell 2 + + + + + + + Cell 1 + Cell 3 + Cell 4 + + + + + + + Cell 1 + Cell 2 + + + Cell 3 + Cell 4 + Cell 5 + + + + + + + Cell 1 + Cell 1.2 + Cell 2 + Cell 3 + Cell 4 + + + Cell 5 + Cell 6 + Cell 7 + Cell 8 + Cell 9 + Cell 10 + + + + + + + Header 1 + Header 2 + + + Cell 1 + Cell 1.2 + Cell 2 + + + + + + + Footer 1 + Footer 2 + + + Cell 1 + Cell 1.2 + Cell 2 + + + + + + + Header 1 + Header 2 + + + Footer 1 + Footer 1.2 + Footer 2 + + + Cell 1 + Cell 2 + + + + + + + Header 1 + Header 2 + Header 3 + Header 4 + + + Footer 1 + Footer 2 + Footer 4 + Footer 5 + Footer 5 + Footer 6 + + + Cell 1 + Cell 2 + Cell 3 + Cell 4 + + + + + + + Header 1 + Header 2 + Header 3 + Header 4 + Header 5 + Header 6 + + + Footer 1 + Footer 2 + Footer 4 + Footer 5 + + + Cell 1 + Cell 2 + Cell 3 + Cell 4 + + + Cell 5 + Cell 6 + + + Cell 7 + Cell 8 + Cell 9 + Cell 10 + Cell 10 + Cell 11 + + + + + + diff --git a/test/fotree/unittests/table/TableRowIterator_no-col_no-row_spans.fo b/test/fotree/unittests/table/TableRowIterator_no-col_no-row_spans.fo new file mode 100644 index 000000000..f20e47eb5 --- /dev/null +++ b/test/fotree/unittests/table/TableRowIterator_no-col_no-row_spans.fo @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + Cell 1 + + + + + + + Cell 1 + Cell 2 + Cell 4 + + + + + + + Cell 1 + Cell 2 + Cell 4 + Cell 5 + Cell 6 + + + + + + + Cell 1 + Cell 2 + Cell 3 + Cell 5 + Cell 7 + + + + + + + Cell 1 + Cell 2 + Cell 3 + Cell 4 + Cell 5 + Cell 8 + Cell 9 + Cell 10 + + + + + + + Header 1 + Header 2 + Header 4 + + + Footer 1 + Footer 2 + Footer 3 + Footer 4 + Footer 6 + Footer 7 + + + Cell 1 + Cell 2 + Cell 3 + Cell 5 + Cell 6 + Cell 7 + Cell 8 + Cell 9 + Cell 10 + + + + + + diff --git a/test/fotree/unittests/table/TableRowIterator_no-col_simple.fo b/test/fotree/unittests/table/TableRowIterator_no-col_simple.fo new file mode 100644 index 000000000..dc1c24685 --- /dev/null +++ b/test/fotree/unittests/table/TableRowIterator_no-col_simple.fo @@ -0,0 +1,257 @@ + + + + + + + + + + + + + + + + Cell 1 + Cell 2 + + + + + + + + + Cell 1 + Cell 2 + + + Cell 3 + Cell 4 + + + + + + + + + Cell 1 + Cell 2 + + + + + Cell 3 + Cell 4 + + + + + + + + + Cell 1 + Cell 2 + + + Cell 3 + Cell 4 + + + + + Cell 5 + Cell 6 + + + Cell 7 + Cell 8 + + + Cell 9 + Cell 10 + + + + + + + + + Header 1 + Header 2 + + + + + Cell 1 + Cell 2 + + + + + + + + + Footer 1 + Footer 2 + + + + + Cell 1 + Cell 2 + + + + + + + + + Header 1 + Header 2 + + + + + Footer 1 + Footer 2 + + + + + Cell 1 + Cell 2 + + + + + + + + + Header 1 + Header 2 + + + Header 3 + Header 4 + + + + + Footer 1 + Footer 2 + + + Footer 4 + Footer 5 + + + Footer 5 + Footer 6 + + + + + Cell 1 + Cell 2 + + + Cell 3 + Cell 4 + + + + + + + + + Header 1 + Header 2 + + + Header 3 + Header 4 + + + Header 5 + Header 6 + + + + + Footer 1 + Footer 2 + + + Footer 4 + Footer 5 + + + + + Cell 1 + Cell 2 + + + Cell 3 + Cell 4 + + + + + Cell 5 + Cell 6 + + + + + Cell 7 + Cell 8 + + + Cell 9 + Cell 10 + + + Cell 10 + Cell 11 + + + + + + + diff --git a/test/fotree/unittests/table/TableRowIterator_no-col_spans.fo b/test/fotree/unittests/table/TableRowIterator_no-col_spans.fo new file mode 100644 index 000000000..67d218a02 --- /dev/null +++ b/test/fotree/unittests/table/TableRowIterator_no-col_spans.fo @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + Cell 1 + + + + + + + + + Cell 1 + Cell 2 + + + Cell 4 + + + + + + + + + Cell 1 + Cell 2 + + + Cell 4 + + + Cell 5 + Cell 6 + + + + + + + + + Cell 1 + Cell 2 + + + Cell 3 + Cell 5 + + + Cell 7 + + + + + + + + + Cell 1 + Cell 2 + + + Cell 3 + Cell 4 + + + Cell 5 + + + Cell 8 + + + Cell 9 + Cell 10 + + + + + + + + + Header 1 + Header 2 + + + Header 4 + + + + + Footer 1 + Footer 2 + + + Footer 3 + Footer 4 + + + Footer 6 + + + Footer 7 + + + + + Cell 1 + Cell 2 + + + Cell 3 + + + Cell 5 + Cell 6 + + + Cell 7 + Cell 8 + + + Cell 9 + + + Cell 10 + + + + + + + diff --git a/test/layoutmgr/table/TableRowIterator_no-row_simple.fo b/test/fotree/unittests/table/TableRowIterator_no-row_simple.fo similarity index 100% rename from test/layoutmgr/table/TableRowIterator_no-row_simple.fo rename to test/fotree/unittests/table/TableRowIterator_no-row_simple.fo diff --git a/test/layoutmgr/table/TableRowIterator_no-row_spans.fo b/test/fotree/unittests/table/TableRowIterator_no-row_spans.fo similarity index 100% rename from test/layoutmgr/table/TableRowIterator_no-row_spans.fo rename to test/fotree/unittests/table/TableRowIterator_no-row_spans.fo diff --git a/test/layoutmgr/table/TableRowIterator_simple.fo b/test/fotree/unittests/table/TableRowIterator_simple.fo similarity index 100% rename from test/layoutmgr/table/TableRowIterator_simple.fo rename to test/fotree/unittests/table/TableRowIterator_simple.fo diff --git a/test/layoutmgr/table/TableRowIterator_spans.fo b/test/fotree/unittests/table/TableRowIterator_spans.fo similarity index 100% rename from test/layoutmgr/table/TableRowIterator_spans.fo rename to test/fotree/unittests/table/TableRowIterator_spans.fo diff --git a/test/java/org/apache/fop/fo/flow/AbstractTableTestCase.java b/test/java/org/apache/fop/fo/flow/AbstractTableTestCase.java index 40f97055a..bbac7d8a3 100644 --- a/test/java/org/apache/fop/fo/flow/AbstractTableTestCase.java +++ b/test/java/org/apache/fop/fo/flow/AbstractTableTestCase.java @@ -19,6 +19,8 @@ package org.apache.fop.fo.flow; +import java.util.Iterator; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fo.FOEventHandler; import org.apache.fop.fotreetest.FOTreeUnitTester; @@ -49,4 +51,8 @@ abstract class AbstractTableTestCase extends FOTreeUnitTester { protected TableHandler getTableHandler() { return tableHandler; } + + protected Iterator getTableIterator() { + return tableHandler.getTables().iterator(); + } } diff --git a/test/java/org/apache/fop/fo/flow/TableColumnColumnNumberTestCase.java b/test/java/org/apache/fop/fo/flow/TableColumnColumnNumberTestCase.java index 2af11c272..12d05d503 100644 --- a/test/java/org/apache/fop/fo/flow/TableColumnColumnNumberTestCase.java +++ b/test/java/org/apache/fop/fo/flow/TableColumnColumnNumberTestCase.java @@ -63,7 +63,7 @@ public class TableColumnColumnNumberTestCase extends AbstractTableTestCase { public void testColumnNumber() throws Exception { setUp("table/table-column_column-number.fo"); - Iterator tableIter = getTableHandler().getTables().iterator(); + Iterator tableIter = getTableIterator(); Table t = (Table) tableIter.next(); assertEquals(2, t.getNumberOfColumns()); checkColumn(t, 1, false, 1, 2, 100000); @@ -100,7 +100,7 @@ public class TableColumnColumnNumberTestCase extends AbstractTableTestCase { public void testImplicitColumns() throws Exception { setUp("table/implicit_columns_column-number.fo"); percentBaseContext.setUnitaryWidth(100000); - Iterator tableIter = getTableHandler().getTables().iterator(); + Iterator tableIter = getTableIterator(); checkImplicitColumns(tableIter, 2); checkImplicitColumns(tableIter, 2); diff --git a/test/java/org/apache/fop/fo/flow/TableRowIteratorTestCase.java b/test/java/org/apache/fop/fo/flow/TableRowIteratorTestCase.java new file mode 100644 index 000000000..6f0bdad63 --- /dev/null +++ b/test/java/org/apache/fop/fo/flow/TableRowIteratorTestCase.java @@ -0,0 +1,201 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo.flow; + +import java.util.Iterator; +import java.util.List; + +/** + * Tests that TableRowIterator returns, for each part of a table, the expected number of + * row-groups with the expected number or rows in each. + */ +public class TableRowIteratorTestCase extends AbstractTableTestCase { + + public TableRowIteratorTestCase() throws Exception { + super(); + } + + /** + * Prepares the iterators over the tables contained in the given FO file. + * + * @param filename basename of a test FO file + * @throws Exception + */ +// private void setUp(String filename) throws Exception { +// foReader.parse(new File("test/layoutmgr/table/" + filename).toURL().toExternalForm()); +// List tables = tableHandler.getTables(); +// List columnSetups = new LinkedList(); +// tableIterator = tables.iterator(); +// for (Iterator i = tables.iterator(); i.hasNext();) { +// columnSetups.add(new ColumnSetup((Table) i.next())); +// } +// columnSetupIterator = columnSetups.iterator(); +// } + + /** + * Checks that the given iterator will return row groups as expected. More precisely, + * checks that the number of row groups corresponds to the size of the given array, + * and that the number of rows inside each row group is equal to the corresponding + * integer in the array. + * + * @param tri an iterator over a given part of a table (HEADER, FOOTER, BODY) + * @param expectedRowLengths expected lengths of all the row groups of this part of + * the table + */ + private void checkTablePartRowGroups(TableBody body, int[] expectedRowLengths) { + Iterator rowGroupIter = body.getRowGroups().iterator(); + for (int i = 0; i < expectedRowLengths.length; i++) { + assertTrue(rowGroupIter.hasNext()); + List rowGroup = (List) rowGroupIter.next(); + assertEquals(expectedRowLengths[i], rowGroup.size()); + } + assertFalse(rowGroupIter.hasNext()); + } + + /** + * Gets the next table and checks its row-groups. + * @param tableIter TODO + * @param expectedHeaderRowLengths expected row-group sizes for the header. If null + * the table is not expected to have a header + * @param expectedFooterRowLengths expected row-group sizes for the footer. If null + * the table is not expected to have a footer + * @param expectedBodyRowLengths expected row-group sizes for the body(-ies) + */ + private void checkNextTableRowGroups(Iterator tableIter, + int[] expectedHeaderRowLengths, int[] expectedFooterRowLengths, int[][] expectedBodyRowLengths) { + Table table = (Table) tableIter.next(); + if (expectedHeaderRowLengths == null) { + assertNull(table.getTableHeader()); + } else { + checkTablePartRowGroups(table.getTableHeader(), expectedHeaderRowLengths); + } + if (expectedFooterRowLengths == null) { + assertNull(table.getTableFooter()); + } else { + checkTablePartRowGroups(table.getTableFooter(), expectedFooterRowLengths); + } + Iterator bodyIter = table.getChildNodes(); + for (int i = 0; i < expectedBodyRowLengths.length; i++) { + assertTrue(bodyIter.hasNext()); + checkTablePartRowGroups((TableBody) bodyIter.next(), expectedBodyRowLengths[i]); + } + +// ColumnSetup columnSetup = (ColumnSetup) columnSetupIterator.next(); +// TableRowIterator tri; +// if (expectedHeaderRowLengths != null) { +// tri = new TableRowIterator(table, columnSetup, TableRowIterator.HEADER); +// checkTablePartRowGroups(tri, expectedHeaderRowLengths); +// } +// if (expectedFooterRowLengths != null) { +// tri = new TableRowIterator(table, columnSetup, TableRowIterator.FOOTER); +// checkTablePartRowGroups(tri, expectedFooterRowLengths); +// } +// tri = new TableRowIterator(table, columnSetup, TableRowIterator.BODY); +// checkTablePartRowGroups(tri, expectedBodyRowLengths); + } + + public void checkSimple(String filename) throws Exception { + setUp(filename); + Iterator tableIter = getTableIterator(); + + // Table 1: no header, no footer, one body (1 row) + checkNextTableRowGroups(tableIter, null, null, new int[][] {{1}}); + + // Table 2: no header, no footer, one body (2 rows) + checkNextTableRowGroups(tableIter, null, null, new int[][] {{1, 1}}); + + // Table 3: no header, no footer, two bodies (1 row, 1 row) + checkNextTableRowGroups(tableIter, null, null, new int[][] {{1}, {1}}); + + // Table 4: no header, no footer, two bodies (2 rows, 3 rows) + checkNextTableRowGroups(tableIter, null, null, new int[][] {{1, 1}, {1, 1, 1}}); + + // Table 5: one header (1 row), no footer, one body (1 row) + checkNextTableRowGroups(tableIter, new int[] {1}, null, new int[][] {{1}}); + + // Table 6: no header, one footer (1 row), one body (1 row) + checkNextTableRowGroups(tableIter, null, new int[] {1}, new int[][] {{1}}); + + // Table 7: one header (1 row), one footer (1 row), one body (1 row) + checkNextTableRowGroups(tableIter, new int[] {1}, new int[] {1}, new int[][] {{1}}); + + // Table 8: one header (2 rows), one footer (3 rows), one body (2 rows) + checkNextTableRowGroups(tableIter, new int[] {1, 1}, new int[] {1, 1, 1}, new int[][] {{1, 1}}); + + // Table 9: one header (3 rows), one footer (2 rows), three bodies (2 rows, 1 row, 3 rows) + checkNextTableRowGroups(tableIter, new int[] {1, 1, 1}, new int[] {1, 1}, new int[][] {{1, 1}, {1}, {1, 1, 1}}); + } + + public void checkSpans(String filename) throws Exception { + setUp(filename); + Iterator tableIter = getTableIterator(); + + // Table 1: no header, no footer, one body (1 row with column-span) + checkNextTableRowGroups(tableIter, null, null, new int[][] {{1}}); + + // Table 2: no header, no footer, one body (1 row-group of 2 rows) + checkNextTableRowGroups(tableIter, null, null, new int[][] {{2}}); + + // Table 3: no header, no footer, one body (1 row-group of 2 rows, 1 row) + checkNextTableRowGroups(tableIter, null, null, new int[][] {{2, 1}}); + + // Table 4: no header, no footer, one body (1 row, 1 row-group of 2 rows) + checkNextTableRowGroups(tableIter, null, null, new int[][] {{1, 2}}); + + // Table 5: no header, no footer, one body (1 row, 1 row-group of 3 rows, 1 row) + checkNextTableRowGroups(tableIter, null, null, new int[][] {{1, 3, 1}}); + + // Table 6: one header (1 row-group of 2 rows), one footer (1 row, 1 row-group of 3 rows), + // one body (1 row-group of 2 rows, 1 row, 1 row-group of 3 rows) + checkNextTableRowGroups(tableIter, new int[] {2}, new int[] {1, 3}, new int[][] {{2, 1, 3}}); + } + + public void testWithRowsSimple() throws Exception { + checkSimple("table/TableRowIterator_simple.fo"); + } + + public void testWithRowsSpans() throws Exception { + checkSpans("table/TableRowIterator_spans.fo"); + } + + public void testNoRowSimple() throws Exception { + checkSimple("table/TableRowIterator_no-row_simple.fo"); + } + + public void testNoRowSpans() throws Exception { + checkSpans("table/TableRowIterator_no-row_spans.fo"); + } + + public void testNoColWithRowsSimple() throws Exception { + checkSimple("table/TableRowIterator_no-col_simple.fo"); + } + + public void testNoColWithRowsSpans() throws Exception { + checkSpans("table/TableRowIterator_no-col_spans.fo"); + } + + public void testNoColNoRowSimple() throws Exception { + checkSimple("table/TableRowIterator_no-col_no-row_simple.fo"); + } + + public void testNoColNoRowSpans() throws Exception { + checkSpans("table/TableRowIterator_no-col_no-row_spans.fo"); + } +} diff --git a/test/java/org/apache/fop/layoutmgr/table/TableRowIteratorTestCase.java b/test/java/org/apache/fop/layoutmgr/table/TableRowIteratorTestCase.java deleted file mode 100644 index b6959143f..000000000 --- a/test/java/org/apache/fop/layoutmgr/table/TableRowIteratorTestCase.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.layoutmgr.table; - -import java.io.File; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import junit.framework.TestCase; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.Fop; -import org.apache.fop.apps.FopFactory; -import org.apache.fop.fo.flow.Table; -import org.xml.sax.XMLReader; - -/** - * Tests that TableRowIterator returns, for each part of a table, the expected number of - * row-groups with the expected number or rows in each. - */ -public class TableRowIteratorTestCase extends TestCase { - - private XMLReader foReader; - - private TableHandler tableHandler; - - /** Returns Table instances. */ - private Iterator tableIterator; - - /** Returns ColumnSetup instances. */ - private Iterator columnSetupIterator; - - /** - * Creates the SAX parser for the FO file and a FO user agent with an overriden - * FOEventHandler and sets them up. - */ - public void setUp() throws Exception { - SAXParserFactory spf = SAXParserFactory.newInstance(); - spf.setNamespaceAware(true); - spf.setValidating(false); - SAXParser parser; - parser = spf.newSAXParser(); - foReader = parser.getXMLReader(); - - FopFactory fopFactory = FopFactory.newInstance(); - FOUserAgent ua = fopFactory.newFOUserAgent(); - tableHandler = new TableHandler(ua); - ua.setFOEventHandlerOverride(tableHandler); - - Fop fop = fopFactory.newFop(ua); - - foReader.setContentHandler(fop.getDefaultHandler()); - foReader.setDTDHandler(fop.getDefaultHandler()); - foReader.setErrorHandler(fop.getDefaultHandler()); - foReader.setEntityResolver(fop.getDefaultHandler()); - } - - /** - * Prepares the iterators over the tables contained in the given FO file. - * - * @param filename basename of a test FO file - * @throws Exception - */ - private void setUp(String filename) throws Exception { - foReader.parse(new File("test/layoutmgr/table/" + filename).toURL().toExternalForm()); - List tables = tableHandler.getTables(); - List columnSetups = new LinkedList(); - tableIterator = tables.iterator(); - for (Iterator i = tables.iterator(); i.hasNext();) { - columnSetups.add(new ColumnSetup((Table) i.next())); - } - columnSetupIterator = columnSetups.iterator(); - } - - /** - * Checks that the given iterator will return row groups as expected. More precisely, - * checks that the number of row groups corresponds to the size of the given array, - * and that the number of rows inside each row group is equal to the corresponding - * integer in the array. - * - * @param tri an iterator over a given part of a table (HEADER, FOOTER, BODY) - * @param expectedRowLengths expected lengths of all the row groups of this part of - * the table - */ - private void checkTablePartRowGroups(TableRowIterator tri, int[] expectedRowLengths) { - for (int i = 0; i < expectedRowLengths.length; i++) { - EffRow[] row = tri.getNextRowGroup(); - assertTrue(row.length == expectedRowLengths[i]); - } - assertNull(tri.getNextRowGroup()); - } - - /** - * Gets the next table and checks its row-groups. - * - * @param expectedHeaderRowLengths expected row-group sizes for the header. If null - * the table is not expected to have a header - * @param expectedFooterRowLengths expected row-group sizes for the footer. If null - * the table is not expected to have a footer - * @param expectedBodyRowLengths expected row-group sizes for the body(-ies) - */ - private void checkNextTableRowGroups(int[] expectedHeaderRowLengths, - int[] expectedFooterRowLengths, int[] expectedBodyRowLengths) { - Table table = (Table) tableIterator.next(); - ColumnSetup columnSetup = (ColumnSetup) columnSetupIterator.next(); - TableRowIterator tri; - if (expectedHeaderRowLengths != null) { - tri = new TableRowIterator(table, columnSetup, TableRowIterator.HEADER); - checkTablePartRowGroups(tri, expectedHeaderRowLengths); - } - if (expectedFooterRowLengths != null) { - tri = new TableRowIterator(table, columnSetup, TableRowIterator.FOOTER); - checkTablePartRowGroups(tri, expectedFooterRowLengths); - } - tri = new TableRowIterator(table, columnSetup, TableRowIterator.BODY); - checkTablePartRowGroups(tri, expectedBodyRowLengths); - } - - public void checkSimple(String filename) throws Exception { - setUp(filename); - - // Table 1: no header, no footer, one body (1 row) - checkNextTableRowGroups(null, null, new int[] {1}); - - // Table 2: no header, no footer, one body (2 rows) - checkNextTableRowGroups(null, null, new int[] {1, 1}); - - // Table 3: no header, no footer, two bodies (1 row, 1 row) - checkNextTableRowGroups(null, null, new int[] {1, 1}); - - // Table 4: no header, no footer, two bodies (2 rows, 3 rows) - checkNextTableRowGroups(null, null, new int[] {1, 1, 1, 1, 1}); - - // Table 5: one header (1 row), no footer, one body (1 row) - checkNextTableRowGroups(new int[] {1}, null, new int[] {1}); - - // Table 6: no header, one footer (1 row), one body (1 row) - checkNextTableRowGroups(null, new int[] {1}, new int[] {1}); - - // Table 7: one header (1 row), one footer (1 row), one body (1 row) - checkNextTableRowGroups(new int[] {1}, new int[] {1}, new int[] {1}); - - // Table 8: one header (2 rows), one footer (3 rows), one body (2 rows) - checkNextTableRowGroups(new int[] {1, 1}, new int[] {1, 1, 1}, new int[] {1, 1}); - - // Table 9: one header (3 rows), one footer (2 rows), three bodies (2 rows, 1 row, 3 rows) - checkNextTableRowGroups(new int[] {1, 1, 1}, new int[] {1, 1}, new int[] {1, 1, 1, 1, 1, 1}); - } - - public void checkSpans(String filename) throws Exception { - setUp(filename); - - // Table 1: no header, no footer, one body (1 row with column-span) - checkNextTableRowGroups(null, null, new int[] {1}); - - // Table 2: no header, no footer, one body (1 row-group of 2 rows) - checkNextTableRowGroups(null, null, new int[] {2}); - - // Table 3: no header, no footer, one body (1 row-group of 2 rows, 1 row) - checkNextTableRowGroups(null, null, new int[] {2, 1}); - - // Table 4: no header, no footer, one body (1 row, 1 row-group of 2 rows) - checkNextTableRowGroups(null, null, new int[] {1, 2}); - - // Table 5: no header, no footer, one body (1 row, 1 row-group of 3 rows, 1 row) - checkNextTableRowGroups(null, null, new int[] {1, 3, 1}); - - // Table 6: one header (1 row-group of 2 rows), one footer (1 row, 1 row-group of 3 rows), - // one body (1 row-group of 2 rows, 1 row, 1 row-group of 3 rows) - checkNextTableRowGroups(new int[] {2}, new int[] {1, 3}, new int[] {2, 1, 3}); - } - - public void testWithRowsSimple() throws Exception { - checkSimple("TableRowIterator_simple.fo"); - } - - public void testWithRowsSpans() throws Exception { - checkSpans("TableRowIterator_spans.fo"); - } - - public void testNoRowSimple() throws Exception { - checkSimple("TableRowIterator_no-row_simple.fo"); - } - - public void testNoRowSpans() throws Exception { - checkSpans("TableRowIterator_no-row_spans.fo"); - } -} \ No newline at end of file -- 2.39.5