aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/fo/flow/table
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org/apache/fop/fo/flow/table')
-rw-r--r--src/java/org/apache/fop/fo/flow/table/BorderResolver.java56
-rw-r--r--src/java/org/apache/fop/fo/flow/table/BorderSpecification.java71
-rw-r--r--src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java169
-rw-r--r--src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java148
-rw-r--r--src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java98
-rw-r--r--src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java44
-rw-r--r--src/java/org/apache/fop/fo/flow/table/Table.java48
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableBody.java67
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableCell.java19
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableCellContainer.java7
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableColumn.java24
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableFObj.java60
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableFooter.java10
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableHeader.java5
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableRow.java23
-rw-r--r--src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java82
16 files changed, 772 insertions, 159 deletions
diff --git a/src/java/org/apache/fop/fo/flow/table/BorderResolver.java b/src/java/org/apache/fop/fo/flow/table/BorderResolver.java
new file mode 100644
index 000000000..0a8f3d39e
--- /dev/null
+++ b/src/java/org/apache/fop/fo/flow/table/BorderResolver.java
@@ -0,0 +1,56 @@
+/*
+ * 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.table;
+
+import java.util.List;
+
+/**
+ * A class dedicated to the resolution of borders in tables. It receives a series of
+ * events as the table is parsed and performs border resolution accordingly.
+ */
+interface BorderResolver {
+
+ /**
+ * Receives notification of the end of a row.
+ *
+ * @param row the row that has just been finished
+ * @param container the FO element holding the given row
+ */
+ void endRow(List/*<GridUnit>*/ row, TableCellContainer container);
+
+ /**
+ * Receives notification of the start of a table-header/footer/body.
+ *
+ * @param part the part that has started
+ */
+ void startPart(TableBody part);
+
+ /**
+ * Receives notification of the end of a table-header/footer/body.
+ *
+ * @param part the part that has ended
+ */
+ void endPart(TableBody part);
+
+ /**
+ * Receives notification of the end of the table.
+ */
+ void endTable();
+}
diff --git a/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java b/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java
new file mode 100644
index 000000000..214f9be07
--- /dev/null
+++ b/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java
@@ -0,0 +1,71 @@
+/*
+ * 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.table;
+
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
+
+/**
+ * A border's informations, along with the FO element which declared it. Used for border
+ * resolution in the collapsing-border model.
+ */
+public/*TODO*/ class BorderSpecification {
+
+ private BorderInfo borderInfo;
+
+ private int holder;
+
+ /**
+ * Creates a new border specification.
+ *
+ * @param borderInfo the border's informations
+ * @param holder the FO element declaring this border
+ */
+ public/*TODO*/ BorderSpecification(BorderInfo borderInfo, int holder) {
+ this.borderInfo = borderInfo;
+ this.holder = holder;
+ }
+
+ /**
+ * Returns this border's informations.
+ *
+ * @return this border's informations
+ */
+ public/*TODO*/ BorderInfo getBorderInfo() {
+ return borderInfo;
+ }
+
+ /**
+ * Returns the FO element declaring this border.
+ *
+ * @return one of {@link Constants#FO_TABLE}, {@link Constants#FO_TABLE_COLUMN},
+ * {@link Constants#FO_TABLE_HEADER}, {@link Constants#FO_TABLE_FOOTER},
+ * {@link Constants#FO_TABLE_BODY}, {@link Constants#FO_TABLE_ROW},
+ * {@link Constants#FO_TABLE_CELL}
+ */
+ public/*TODO*/ int getHolder() {
+ return holder;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "{" + borderInfo + ", " + holder + "}";
+ }
+}
diff --git a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java
new file mode 100644
index 000000000..732acb6be
--- /dev/null
+++ b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java
@@ -0,0 +1,169 @@
+/*
+ * 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.table;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
+import org.apache.fop.layoutmgr.table.GridUnit;
+
+/**
+ * A class that implements the border-collapsing model.
+ */
+class CollapsingBorderResolver implements BorderResolver {
+
+ private Table table;
+
+ private List previousRow;
+
+ /**
+ * The flow of rows is interrupted by the table-footer. Save the header's last row (if
+ * any) for resolution between it and the body's first row.
+ */
+ private List previousRowSave;
+
+ private TableBody currentTablePart;
+
+ private boolean firstInTable;
+
+ private boolean firstInPart;
+
+ private List footerFirstRow;
+
+ private List footerLastRow;
+
+ private boolean inFooter;
+
+ CollapsingBorderResolver(Table table) {
+ this.table = table;
+ firstInTable = true;
+ }
+
+ /** {@inheritDoc} */
+ public void endRow(List row, TableCellContainer container) {
+ // Resolve before- and after-borders for the table-row
+ if (container instanceof TableRow) {
+ TableRow tableRow = (TableRow) container;
+ for (Iterator iter = row.iterator(); iter.hasNext();) {
+ GridUnit gu = (GridUnit) iter.next();
+ if (gu.getRowSpanIndex() == 0) {
+ gu.resolveBorder(CommonBorderPaddingBackground.BEFORE, tableRow);
+ }
+ if (gu.isLastGridUnitRowSpan()) {
+ gu.resolveBorder(CommonBorderPaddingBackground.AFTER, tableRow);
+ }
+ }
+ }
+ if (inFooter) {
+ if (footerFirstRow == null) {
+ footerFirstRow = row;
+ }
+ footerLastRow = row;
+ } else if (firstInTable) {
+ // Resolve border-before for the first row in the table
+ for (int i = 0; i < row.size(); i++) {
+ TableColumn column = table.getColumn(i);
+ ((GridUnit) row.get(i)).resolveBorder(CommonBorderPaddingBackground.BEFORE, column);
+ }
+ firstInTable = false;
+ }
+ if (firstInPart) {
+ // Resolve border-before for the first row in the part
+ for (int i = 0; i < row.size(); i++) {
+ ((GridUnit) row.get(i)).resolveBorder(CommonBorderPaddingBackground.BEFORE,
+ currentTablePart);
+ }
+ firstInPart = false;
+ }
+ if (previousRow != null) {
+ // Resolve after/before borders between rows
+ for (int i = 0; i < row.size(); i++) {
+ GridUnit gu = (GridUnit) row.get(i);
+ if (gu.getRowSpanIndex() == 0) {
+ GridUnit beforeGU = (GridUnit) previousRow.get(i);
+ gu.resolveBorder(beforeGU, CommonBorderPaddingBackground.BEFORE);
+ }
+ }
+ }
+ // Resolve start/end borders in the row
+ Iterator guIter = row.iterator();
+ GridUnit gu = (GridUnit) guIter.next();
+ gu.resolveBorder(CommonBorderPaddingBackground.START, container);
+ while (guIter.hasNext()) {
+ GridUnit guEnd = (GridUnit) guIter.next();
+ if (gu.isLastGridUnitColSpan()) {
+ gu.resolveBorder(guEnd, CommonBorderPaddingBackground.END);
+ }
+ gu = guEnd;
+ }
+ gu.resolveBorder(CommonBorderPaddingBackground.END, container);
+
+ previousRow = row;
+ }
+
+ /** {@inheritDoc} */
+ public void startPart(TableBody part) {
+ firstInPart = true;
+ currentTablePart = part;
+ if (part.isTableFooter()) {
+ inFooter = true;
+ previousRowSave = previousRow;
+ previousRow = null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endPart(TableBody part) {
+ // Resolve border-after for the last row in the part
+ for (int i = 0; i < previousRow.size(); i++) {
+ ((GridUnit) previousRow.get(i))
+ .resolveBorder(CommonBorderPaddingBackground.AFTER, part);
+ }
+ if (inFooter) {
+ inFooter = false;
+ previousRow = previousRowSave;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endTable() {
+ if (footerFirstRow != null) {
+ // Resolve after/before border between the last row of table-body and the
+ // first row of table-footer
+ for (int i = 0; i < footerFirstRow.size(); i++) {
+ GridUnit gu = (GridUnit) footerFirstRow.get(i);
+ GridUnit beforeGU = (GridUnit) previousRow.get(i);
+ gu.resolveBorder(beforeGU, CommonBorderPaddingBackground.BEFORE);
+ }
+ }
+ List lastRow;
+ if (footerLastRow != null) {
+ lastRow = footerLastRow;
+ } else {
+ lastRow = previousRow;
+ }
+ // Resolve border-after for the last row of the table
+ for (int i = 0; i < lastRow.size(); i++) {
+ TableColumn column = table.getColumn(i);
+ ((GridUnit) lastRow.get(i)).resolveBorder(CommonBorderPaddingBackground.AFTER, column);
+ }
+ }
+}
diff --git a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
index 22e5c02b8..602ae84a6 100644
--- a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
+++ b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
@@ -19,6 +19,15 @@
package org.apache.fop.fo.flow.table;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.apache.fop.fo.ValidationException;
+import org.apache.fop.layoutmgr.table.EmptyGridUnit;
+import org.apache.fop.layoutmgr.table.GridUnit;
+import org.apache.fop.layoutmgr.table.PrimaryGridUnit;
+
/**
* A row group builder optimised for a fixed number of columns, known before the parsing
@@ -26,10 +35,149 @@ package org.apache.fop.fo.flow.table;
*/
class FixedColRowGroupBuilder extends RowGroupBuilder {
+ /** Number of columns in the corresponding table. */
+ private int numberOfColumns;
+
+ /** 0-based, index in the row group. */
+ private int currentRowIndex;
+
+ /** The rows belonging to this row group. List of List of {@link GridUnit}s. */
+ private List/*<List<GridUnit>>*/ rows;
+
+ private boolean firstInTable = true;
+
+ private boolean firstInPart = true;
+
+ /** The last encountered row. This is the last row of the table if it has no footer. */
+ private List lastRow;
+
+ private BorderResolver borderResolver;
+
+ private boolean inFooter;
+
+ private List lastFooterRow;
FixedColRowGroupBuilder(Table t) {
super(t);
numberOfColumns = t.getNumberOfColumns();
+ if (t.isSeparateBorderModel()) {
+ borderResolver = new SeparateBorderResolver();
+ } else {
+ borderResolver = new CollapsingBorderResolver(t);
+ }
+ initialize();
+ }
+
+ /**
+ * Prepares this builder for creating a new row group.
+ */
+ private void initialize() {
+ rows = new ArrayList();
+ currentRowIndex = 0;
}
+ /** {@inheritDoc} */
+ 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);
+ // TODO
+ GridUnit[] cellRow = new GridUnit[cell.getNumberColumnsSpanned()];
+ cellRow[0] = pgu;
+ for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) {
+ GridUnit gu = new GridUnit(pgu, table.getColumn(columnIndex + j),
+ columnIndex + j, j, 0);
+ row.set(columnIndex + j, gu);
+ cellRow[j] = gu;
+ }
+ pgu.addRow(cellRow);
+ for (int i = 1; i < cell.getNumberRowsSpanned(); i++) {
+ row = (List) rows.get(currentRowIndex + i);
+ cellRow = new GridUnit[cell.getNumberColumnsSpanned()];
+ for (int j = 0; j < cell.getNumberColumnsSpanned(); j++) {
+ GridUnit gu = new GridUnit(pgu, table.getColumn(columnIndex + j),
+ columnIndex + j, j, i);
+ row.set(columnIndex + j, gu);
+ cellRow[j] = gu;
+ }
+ pgu.addRow(cellRow);
+ }
+ }
+
+ private static void setFlagForCols(int flag, List row) {
+ for (ListIterator iter = row.listIterator(); iter.hasNext();) {
+ ((GridUnit) iter.next()).setFlag(flag);
+ }
+ }
+
+ /** {@inheritDoc} */
+ void endRow(TableCellContainer container) {
+ List currentRow = (List) rows.get(currentRowIndex);
+ lastRow = currentRow;
+ // Fill gaps with empty grid units
+ for (int i = 0; i < numberOfColumns; i++) {
+ if (currentRow.get(i) == null) {
+ currentRow.set(i, new EmptyGridUnit(table, currentRowIndex, i));
+ }
+ }
+ borderResolver.endRow(currentRow, container);
+ ((GridUnit) currentRow.get(0)).setFlag(GridUnit.IN_FIRST_COLUMN);
+ ((GridUnit) currentRow.get(numberOfColumns - 1)).setFlag(GridUnit.IN_LAST_COLUMN);
+ if (inFooter) {
+ lastFooterRow = currentRow;
+ } else if (firstInTable) {
+ setFlagForCols(GridUnit.FIRST_IN_TABLE, currentRow);
+ firstInTable = false;
+ }
+ if (firstInPart) {
+ setFlagForCols(GridUnit.FIRST_IN_PART, currentRow);
+ firstInPart = false;
+ }
+ if (currentRowIndex == rows.size() - 1) {
+ // Means that the current row has no cell spanning over following rows
+ container.getTablePart().addRowGroup(rows);
+ initialize();
+ } else {
+ currentRowIndex++;
+ }
+ }
+
+ /** {@inheritDoc} */
+ void startTablePart(TableBody part) {
+ firstInPart = true;
+ inFooter = part.isTableFooter();
+ borderResolver.startPart(part);
+ }
+
+ /** {@inheritDoc} */
+ void endTablePart(TableBody tableBody) throws ValidationException {
+ if (rows.size() > 0) {
+ throw new ValidationException(
+ "A table-cell is spanning more rows than available in its parent element.");
+ }
+ setFlagForCols(GridUnit.LAST_IN_PART, lastRow);
+ borderResolver.endPart(tableBody);
+ inFooter = false;
+ }
+
+ /** {@inheritDoc} */
+ void endTable(TableBody lastTablePart) {
+ List lastTableRow;
+ if (lastFooterRow != null) {
+ lastTableRow = lastFooterRow;
+ } else {
+ lastTableRow = lastRow;
+ }
+ setFlagForCols(GridUnit.LAST_IN_TABLE, lastTableRow);
+ borderResolver.endTable();
+ }
}
diff --git a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
index 2f9a009c2..7f09f7d46 100644
--- a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
+++ b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
@@ -19,12 +19,8 @@
package org.apache.fop.fo.flow.table;
-import java.util.ArrayList;
-import java.util.List;
-
import org.apache.fop.fo.ValidationException;
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
@@ -34,16 +30,7 @@ import org.apache.fop.layoutmgr.table.PrimaryGridUnit;
*/
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;
+ protected Table table;
/**
* Creates and initialises a new builder for the given table.
@@ -52,81 +39,48 @@ abstract class RowGroupBuilder {
*/
protected RowGroupBuilder(Table t) {
table = t;
- initialize();
}
+
/**
- * Prepares this builder for creating a new row group.
+ * Adds a table-cell to the current row-group, creating {@link GridUnit}s accordingly.
+ *
+ * @param cell the cell to add
*/
- private void initialize() {
- rows = new ArrayList();
- currentRowIndex = 0;
- }
+ abstract void addTableCell(TableCell cell);
/**
- * Adds a table-cell to the row-group, creating {@link GridUnit}s accordingly.
+ * Receives notification of the end of the current row. If the current row finishes
+ * the row group, the {@link TableBody#addRowGroup(List)} method of the parent table
+ * part (i.e., the given container itself or its parent if this is a table-row) will
+ * be called
*
- * @param cell
+ * @param container the parent element of the current row
*/
- 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));
- }
- }
-
- }
+ abstract void endRow(TableCellContainer container);
/**
- * Signals that a table row has just ended, potentially finishing the current row
- * group.
+ * Receives notification of the start of a table-header/footer/body.
*
- * @param body the table-body containing the row. Its
- * {@link TableBody#addRowGroup(List)} method will be called if the current row group
- * is finished.
+ * @param part the part being started
*/
- void signalRowEnd(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++;
- }
- }
+ abstract void startTablePart(TableBody part);
/**
- * Signals that the end of a table-header/footer/body has been reached. The current
+ * Receives notification of the end of a table-header/footer/body. The current
* row-group is checked for emptiness. This row group builder is reset for handling
* further possible table parts.
*
- * @param tableBody the table part being finished
- * @throws ValidationException if a cell is spanning further than the given table part
+ * @param tableBody the table part being ended
+ * @throws ValidationException if a row-spanning cell overflows the given table part
*/
- void signalEndOfPart(TableBody tableBody) throws ValidationException {
- if (rows.size() > 0) {
- throw new ValidationException(
- "A table-cell is spanning more rows than available in its parent element.");
- }
- initialize();
- }
+ abstract void endTablePart(TableBody tableBody) throws ValidationException;
+ /**
+ * Receives notification of the end of the table.
+ *
+ * @param lastTablePart the last part of the table
+ * @throws ValidationException if a row-spanning cell overflows one of the table's parts
+ */
+ abstract void endTable(TableBody lastTablePart) throws ValidationException;
}
diff --git a/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java
new file mode 100644
index 000000000..37e3cb6e8
--- /dev/null
+++ b/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java
@@ -0,0 +1,44 @@
+/*
+ * 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.table;
+
+import java.util.List;
+
+/**
+ * A resolver for the separate-border model. Basically this class does nothing.
+ */
+class SeparateBorderResolver implements BorderResolver {
+
+ /** {@inheritDoc} */
+ public void endRow(List row, TableCellContainer container) {
+ }
+
+ /** {@inheritDoc} */
+ public void startPart(TableBody part) {
+ }
+
+ /** {@inheritDoc} */
+ public void endPart(TableBody part) {
+ }
+
+ /** {@inheritDoc} */
+ public void endTable() {
+ }
+}
diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java
index 07fc95f7e..b2f240c72 100644
--- a/src/java/org/apache/fop/fo/flow/table/Table.java
+++ b/src/java/org/apache/fop/fo/flow/table/Table.java
@@ -20,7 +20,6 @@
package org.apache.fop.fo.flow.table;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
import org.apache.fop.apps.FOPException;
@@ -154,7 +153,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
/**
* {@inheritDoc}
*/
- protected void startOfNode() throws FOPException {
+ public void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startTable(this);
}
@@ -211,7 +210,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
/**
* {@inheritDoc}
*/
- protected void endOfNode() throws FOPException {
+ public void endOfNode() throws FOPException {
if (!tableBodyFound) {
missingChildElementError(
@@ -219,6 +218,11 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
+ ",table-body+)");
}
if (!inMarker()) {
+ if (tableFooter != null) {
+ rowGroupBuilder.endTable(tableFooter);
+ } else {
+ rowGroupBuilder.endTable((TableBody) getChildNodes().lastNode());
+ }
/* clean up */
for (int i = columns.size(); --i >= 0;) {
TableColumn col = (TableColumn) columns.get(i);
@@ -278,6 +282,13 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
}
}
+ protected void setCollapsedBorders() {
+ createBorder(CommonBorderPaddingBackground.START);
+ createBorder(CommonBorderPaddingBackground.END);
+ createBorder(CommonBorderPaddingBackground.BEFORE);
+ createBorder(CommonBorderPaddingBackground.AFTER);
+ }
+
private void finalizeColumns() throws FOPException {
for (int i = 0; i < columns.size(); i++) {
if (columns.get(i) == null) {
@@ -305,32 +316,6 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
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)
@@ -342,6 +327,9 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
implicitColumn.bind(pList);
implicitColumn.setColumnWidth(new TableColLength(1.0, implicitColumn));
implicitColumn.setColumnNumber(colNumber);
+ if (!isSeparateBorderModel()) {
+ implicitColumn.setCollapsedBorders(collapsingBorderModel); // TODO
+ }
return implicitColumn;
}
@@ -399,7 +387,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
* @param index index of the column to be retrieved, 0-based
* @return the corresponding column (may be an implicitly created column)
*/
- TableColumn getColumn(int index) {
+ public/*TODO*/ TableColumn getColumn(int index) {
return (TableColumn) columns.get(index);
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java
index 7e4ee2fb0..ece1f0049 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableBody.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java
@@ -50,15 +50,15 @@ public class TableBody extends TableCellContainer {
protected boolean tableRowsFound = false;
protected boolean tableCellsFound = false;
- /**
- * used for initial values of column-number property
- */
private boolean firstRow = true;
private boolean rowsStarted = false;
private boolean lastCellEndsRow = true;
+ /** The last encountered table-row. */
+ private TableRow lastRow;
+
private List rowGroups = new LinkedList();
/**
@@ -101,14 +101,15 @@ public class TableBody extends TableCellContainer {
/**
* {@inheritDoc}
*/
- protected void startOfNode() throws FOPException {
+ public void startOfNode() throws FOPException {
+ super.startOfNode();
getFOEventHandler().startBody(this);
}
/**
* {@inheritDoc}
*/
- protected void endOfNode() throws FOPException {
+ public void endOfNode() throws FOPException {
if (!inMarker()) {
pendingSpans = null;
@@ -130,16 +131,25 @@ public class TableBody extends TableCellContainer {
}
}
+ /** {@inheritDoc} */
+ TableBody getTablePart() {
+ return this;
+ }
+
protected void finishLastRowGroup() throws ValidationException {
- RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder();
- if (tableRowsFound || !lastCellEndsRow) {
- rowGroupBuilder.signalRowEnd(this);
- }
- try {
- rowGroupBuilder.signalEndOfPart(this);
- } catch (ValidationException e) {
- e.setLocator(locator);
- throw e;
+ if (!inMarker()) {
+ RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder();
+ if (tableRowsFound) {
+ rowGroupBuilder.endRow(lastRow);
+ } else if (!lastCellEndsRow) {
+ rowGroupBuilder.endRow(this);
+ }
+ try {
+ rowGroupBuilder.endTablePart(this);
+ } catch (ValidationException e) {
+ e.setLocator(locator);
+ throw e;
+ }
}
}
@@ -184,13 +194,19 @@ public class TableBody extends TableCellContainer {
if (!inMarker()) {
switch (child.getNameId()) {
case FO_TABLE_ROW:
- if (rowsStarted) {
+ if (!rowsStarted) {
+ getTable().getRowGroupBuilder().startTablePart(this);
+ } else {
columnNumberManager.prepareForNextRow(pendingSpans);
- getTable().getRowGroupBuilder().signalRowEnd(this);
+ getTable().getRowGroupBuilder().endRow(lastRow);
}
rowsStarted = true;
+ lastRow = (TableRow) child;
break;
case FO_TABLE_CELL:
+ if (!rowsStarted) {
+ getTable().getRowGroupBuilder().startTablePart(this);
+ }
rowsStarted = true;
TableCell cell = (TableCell) child;
addTableCellChild(cell, firstRow);
@@ -198,7 +214,7 @@ public class TableBody extends TableCellContainer {
if (lastCellEndsRow) {
firstRow = false;
columnNumberManager.prepareForNextRow(pendingSpans);
- getTable().getRowGroupBuilder().signalRowEnd(this);
+ getTable().getRowGroupBuilder().endRow(this);
}
break;
default:
@@ -208,11 +224,20 @@ public class TableBody extends TableCellContainer {
super.addChildNode(child);
}
+ /** {inheritDoc} */
+ protected void setCollapsedBorders() {
+ Table table = (Table) parent;
+ createBorder(CommonBorderPaddingBackground.START, table);
+ createBorder(CommonBorderPaddingBackground.END, table);
+ createBorder(CommonBorderPaddingBackground.BEFORE);
+ createBorder(CommonBorderPaddingBackground.AFTER);
+ }
+
void addRowGroup(List rowGroup) {
rowGroups.add(rowGroup);
}
- List getRowGroups() {
+ public List getRowGroups() {
return rowGroups;
}
@@ -235,6 +260,10 @@ public class TableBody extends TableCellContainer {
return FO_TABLE_BODY;
}
+ protected boolean isTableFooter() {
+ return false;
+ }
+
/**
* @param obj table row in question
* @return true if the given table row is the first row of this body.
@@ -249,7 +278,7 @@ public class TableBody extends TableCellContainer {
firstRow = false;
if (!lastCellEndsRow) {
columnNumberManager.prepareForNextRow(pendingSpans);
- getTable().getRowGroupBuilder().signalRowEnd(this);
+ getTable().getRowGroupBuilder().endRow(this);
}
}
rowsStarted = true;
diff --git a/src/java/org/apache/fop/fo/flow/table/TableCell.java b/src/java/org/apache/fop/fo/flow/table/TableCell.java
index 34c6266a7..f85d0e97e 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableCell.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableCell.java
@@ -90,7 +90,7 @@ public class TableCell extends TableFObj {
/**
* {@inheritDoc}
*/
- protected void startOfNode() throws FOPException {
+ public void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startCell(this);
}
@@ -100,7 +100,7 @@ public class TableCell extends TableFObj {
* FOEventHandler that we are at the end of the flow.
* {@inheritDoc}
*/
- protected void endOfNode() throws FOPException {
+ public void endOfNode() throws FOPException {
if (!blockItemFound) {
if (getUserAgent().validateStrictly()) {
missingChildElementError("marker* (%block;)+");
@@ -135,6 +135,21 @@ public class TableCell extends TableFObj {
}
/** {@inheritDoc} */
+ protected void setCollapsedBorders() {
+ createBorder(CommonBorderPaddingBackground.BEFORE);
+ createBorder(CommonBorderPaddingBackground.AFTER);
+ Table table = getTable();
+ if (table.hasExplicitColumns()) {
+ TableColumn col = table.getColumn(getColumnNumber() - 1);
+ createBorder(CommonBorderPaddingBackground.START, col);
+ createBorder(CommonBorderPaddingBackground.END, col);
+ } else {
+ createBorder(CommonBorderPaddingBackground.START);
+ createBorder(CommonBorderPaddingBackground.END);
+ }
+ }
+
+ /** {@inheritDoc} */
public boolean generatesReferenceAreas() {
return true;
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java b/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
index ebb066c5c..7c91be351 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
@@ -93,6 +93,13 @@ public abstract class TableCellContainer extends TableFObj implements ColumnNumb
}
}
+ /**
+ * Returns the enclosing table-header/footer/body of this container.
+ *
+ * @return <code>this</code> for TableBody, or the parent element for TableRow
+ */
+ abstract TableBody getTablePart();
+
/** {@inheritDoc} */
public ColumnNumberManager getColumnNumberManager() {
return columnNumberManager;
diff --git a/src/java/org/apache/fop/fo/flow/table/TableColumn.java b/src/java/org/apache/fop/fo/flow/table/TableColumn.java
index aa2dfcb0a..aeb401893 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableColumn.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableColumn.java
@@ -31,6 +31,7 @@ import org.apache.fop.fo.expr.PropertyException;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.Property;
import org.apache.fop.fo.properties.TableColLength;
+import org.apache.fop.layoutmgr.table.CollapsingBorderModel;
/**
* Class modelling the fo:table-column object.
@@ -114,14 +115,27 @@ public class TableColumn extends TableFObj {
/**
* {@inheritDoc}
*/
- protected void startOfNode() throws FOPException {
+ public void startOfNode() throws FOPException {
+ super.startOfNode();
getFOEventHandler().startColumn(this);
}
- /**
- * {@inheritDoc}
- */
- protected void endOfNode() throws FOPException {
+ void setCollapsedBorders(CollapsingBorderModel collapsingBorderModel) {
+ this.collapsingBorderModel = collapsingBorderModel;
+ setCollapsedBorders();
+ }
+
+ /** {@inheritDoc} */
+ protected void setCollapsedBorders() {
+ Table table = (Table) parent;
+ createBorder(CommonBorderPaddingBackground.BEFORE, table);
+ createBorder(CommonBorderPaddingBackground.AFTER, table);
+ createBorder(CommonBorderPaddingBackground.START);
+ createBorder(CommonBorderPaddingBackground.END);
+ }
+
+ /** {@inheritDoc} */
+ public void endOfNode() throws FOPException {
getFOEventHandler().endColumn(this);
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java
index 53995464b..984f242f2 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java
@@ -30,6 +30,7 @@ import org.apache.fop.fo.expr.PropertyException;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.NumberProperty;
import org.apache.fop.fo.properties.Property;
+import org.apache.fop.layoutmgr.table.CollapsingBorderModel;
/**
* Common base class for table-related FOs
@@ -41,6 +42,10 @@ public abstract class TableFObj extends FObj {
private Numeric borderEndPrecedence;
private Numeric borderStartPrecedence;
+ public/*TODO*/ BorderSpecification[] resolvedBorders = new BorderSpecification[4]; // TODO
+
+ CollapsingBorderModel collapsingBorderModel;
+
/**
* Main constructor
*
@@ -122,9 +127,7 @@ public abstract class TableFObj extends FObj {
super(propId);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public Property make(PropertyList propertyList)
throws PropertyException {
FObj fo = propertyList.getFObj();
@@ -189,4 +192,55 @@ public abstract class TableFObj extends FObj {
return p;
}
}
+
+ /** {@inheritDoc} */
+ public void startOfNode() throws FOPException {
+ super.startOfNode();
+ Table table = getTable();
+ if (!inMarker() && !table.isSeparateBorderModel()) {
+ collapsingBorderModel = CollapsingBorderModel.getBorderModelFor(table
+ .getBorderCollapse());
+ resolvedBorders = new BorderSpecification[4];
+ setCollapsedBorders();
+ }
+ }
+
+ /*
+ * TODO made public so that RetrieveMarker can access it.
+ */
+ /** {@inheritDoc} */
+ public void endOfNode() throws FOPException {
+ super.endOfNode();
+ }
+
+ /**
+ * Prepares the borders of this element if the collapsing-border model is in use.
+ * Conflict resolution with parent elements is done where applicable.
+ */
+ protected abstract void setCollapsedBorders();
+
+ /**
+ * Creates a BorderSpecification from the border set on the given side. If no border
+ * is set, a BorderSpecification with border-style none is created.
+ *
+ * @param side one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END
+ */
+ protected void createBorder(int side) {
+ resolvedBorders[side] = new BorderSpecification(getCommonBorderPaddingBackground()
+ .getBorderInfo(side), getNameId());
+ }
+
+ /**
+ * Creates a BorderSpecification from the border set on the given side, performing
+ * conflict resolution with the same border on the given object.
+ *
+ * @param side one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END
+ * @param competitor a parent table element whose side coincides with the given side
+ * on this element
+ */
+ protected void createBorder(int side, TableFObj competitor) {
+ createBorder(side);
+ resolvedBorders[side] = collapsingBorderModel.determineWinner(resolvedBorders[side],
+ competitor.resolvedBorders[side]);
+ }
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableFooter.java b/src/java/org/apache/fop/fo/flow/table/TableFooter.java
index a7ee21406..e886d2ee1 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableFooter.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableFooter.java
@@ -39,14 +39,15 @@ public class TableFooter extends TableBody {
/**
* {@inheritDoc}
*/
- protected void startOfNode() throws FOPException {
+ public void startOfNode() throws FOPException {
+ super.startOfNode();
//getFOEventHandler().startBody(this);
}
/**
* {@inheritDoc}
*/
- protected void endOfNode() throws FOPException {
+ public void endOfNode() throws FOPException {
// getFOEventHandler().endFooter(this);
if (!(tableRowsFound || tableCellsFound)) {
missingChildElementError("marker* (table-row+|table-cell+)");
@@ -65,4 +66,9 @@ public class TableFooter extends TableBody {
public int getNameId() {
return FO_TABLE_FOOTER;
}
+
+ /** {@inheritDoc} */
+ protected boolean isTableFooter() {
+ return true;
+ }
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableHeader.java b/src/java/org/apache/fop/fo/flow/table/TableHeader.java
index bc9d88952..01ada2aa7 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableHeader.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableHeader.java
@@ -39,14 +39,15 @@ public class TableHeader extends TableBody {
/**
* {@inheritDoc}
*/
- protected void startOfNode() throws FOPException {
+ public void startOfNode() throws FOPException {
+ super.startOfNode();
//getFOEventHandler().startHeader(this);
}
/**
* {@inheritDoc}
*/
- protected void endOfNode() throws FOPException {
+ public void endOfNode() throws FOPException {
// getFOEventHandler().endHeader(this);
if (!(tableRowsFound || tableCellsFound)) {
missingChildElementError("marker* (table-row+|table-cell+)");
diff --git a/src/java/org/apache/fop/fo/flow/table/TableRow.java b/src/java/org/apache/fop/fo/flow/table/TableRow.java
index edc8d13df..a025f92fd 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableRow.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableRow.java
@@ -97,7 +97,7 @@ public class TableRow extends TableCellContainer {
/**
* {@inheritDoc}
*/
- protected void startOfNode() throws FOPException {
+ public void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startRow(this);
}
@@ -105,7 +105,7 @@ public class TableRow extends TableCellContainer {
/**
* {@inheritDoc}
*/
- protected void endOfNode() throws FOPException {
+ public void endOfNode() throws FOPException {
if (firstChild == null) {
missingChildElementError("(table-cell+)");
}
@@ -128,6 +128,25 @@ public class TableRow extends TableCellContainer {
}
}
+ /** {@inheritDoc} */
+ TableBody getTablePart() {
+ return (TableBody) parent;
+ }
+
+ /** {@inheritDoc} */
+ boolean isTableRow() {
+ return true;
+ }
+
+ /** {inheritDoc} */
+ protected void setCollapsedBorders() {
+ TableBody body = (TableBody) parent;
+ createBorder(CommonBorderPaddingBackground.START, body);
+ createBorder(CommonBorderPaddingBackground.END, body);
+ createBorder(CommonBorderPaddingBackground.BEFORE);
+ createBorder(CommonBorderPaddingBackground.AFTER);
+ }
+
/** @return the "break-after" property. */
public int getBreakAfter() {
return breakAfter;
diff --git a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
index 53b7bfca1..e35ad5c27 100644
--- a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
+++ b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
@@ -19,9 +19,12 @@
package org.apache.fop.fo.flow.table;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
-import org.apache.fop.layoutmgr.table.EmptyGridUnit;
+import org.apache.fop.fo.ValidationException;
+
/**
* A row group builder accommodating a variable number of columns. More flexible, but less
@@ -31,34 +34,69 @@ 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
+ * Each event is recorded and will be played once the table is finished, and the final
+ * number of columns known.
*/
- 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));
+ private static interface Event {
+ /**
+ * Plays this event
+ *
+ * @param rowGroupBuilder the delegate builder which will actually create the row
+ * groups
+ * @throws ValidationException if a row-spanning cell overflows its parent body
+ */
+ void play(RowGroupBuilder rowGroupBuilder) throws ValidationException;
+ }
+
+ /** The queue of events sent to this builder. */
+ private List events = new LinkedList();
+
+ /** {@inheritDoc} */
+ void addTableCell(final TableCell cell) {
+ events.add(new Event() {
+ public void play(RowGroupBuilder rowGroupBuilder) {
+ rowGroupBuilder.addTableCell(cell);
}
- }
+ });
}
- /**
- * 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);
+ /** {@inheritDoc} */
+ void endRow(final TableCellContainer container) {
+ events.add(new Event() {
+ public void play(RowGroupBuilder rowGroupBuilder) {
+ rowGroupBuilder.endRow(container);
+ }
+ });
}
+ /** {@inheritDoc} */
+ void startTablePart(final TableBody part) {
+ events.add(new Event() {
+ public void play(RowGroupBuilder rowGroupBuilder) {
+ rowGroupBuilder.startTablePart(part);
+ }
+ });
+ }
+
+ /** {@inheritDoc} */
+ void endTablePart(final TableBody tableBody) throws ValidationException {
+ // TODO catch the ValidationException sooner?
+ events.add(new Event() {
+ public void play(RowGroupBuilder rowGroupBuilder) throws ValidationException {
+ rowGroupBuilder.endTablePart(tableBody);
+ }
+ });
+ }
+
+ /** {@inheritDoc} */
+ void endTable(final TableBody lastTablePart) throws ValidationException {
+ RowGroupBuilder delegate = new FixedColRowGroupBuilder(table);
+ for (Iterator eventIter = events.iterator(); eventIter.hasNext();) {
+ ((Event) eventIter.next()).play(delegate);
+ }
+ delegate.endTable(lastTablePart);
+ }
}