You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TablePart.java 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  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. /* $Id$ */
  18. package org.apache.fop.fo.flow.table;
  19. import java.util.ArrayList;
  20. import java.util.LinkedList;
  21. import java.util.List;
  22. import org.xml.sax.Attributes;
  23. import org.xml.sax.Locator;
  24. import org.apache.fop.apps.FOPException;
  25. import org.apache.fop.fo.FONode;
  26. import org.apache.fop.fo.PropertyList;
  27. import org.apache.fop.fo.ValidationException;
  28. import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
  29. /**
  30. * An abstract base class modelling a TablePart
  31. * (i.e. fo:table-header, fo:table-footer and fo:table-body).
  32. */
  33. public abstract class TablePart extends TableCellContainer {
  34. // The value of properties relevant for fo:table-body.
  35. private CommonBorderPaddingBackground commonBorderPaddingBackground;
  36. // Unused but valid items, commented out for performance:
  37. // private CommonAccessibility commonAccessibility;
  38. // private CommonAural commonAural;
  39. // private CommonRelativePosition commonRelativePosition;
  40. // private int visibility;
  41. // End of property values
  42. /** table rows found */
  43. protected boolean tableRowsFound = false;
  44. /** table cells found */
  45. protected boolean tableCellsFound = false;
  46. private boolean firstRow = true;
  47. private boolean rowsStarted = false;
  48. private boolean lastCellEndsRow = true;
  49. private List rowGroups = new LinkedList();
  50. /**
  51. * Create a TablePart instance with the given {@link FONode}
  52. * as parent.
  53. * @param parent FONode that is the parent of the object
  54. */
  55. public TablePart(FONode parent) {
  56. super(parent);
  57. }
  58. /** {@inheritDoc} */
  59. protected Object clone() {
  60. TablePart clone = (TablePart) super.clone();
  61. clone.rowGroups = new LinkedList(rowGroups);
  62. return clone;
  63. }
  64. /** {@inheritDoc} */
  65. public void bind(PropertyList pList) throws FOPException {
  66. commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
  67. super.bind(pList);
  68. }
  69. /** {@inheritDoc} */
  70. public void processNode(String elementName, Locator locator,
  71. Attributes attlist, PropertyList pList)
  72. throws FOPException {
  73. super.processNode(elementName, locator, attlist, pList);
  74. if (!inMarker()) {
  75. Table t = getTable();
  76. if (t.hasExplicitColumns()) {
  77. int size = t.getNumberOfColumns();
  78. pendingSpans = new ArrayList(size);
  79. for (int i = 0; i < size; i++) {
  80. pendingSpans.add(null);
  81. }
  82. } else {
  83. pendingSpans = new ArrayList();
  84. }
  85. columnNumberManager = new ColumnNumberManager();
  86. }
  87. }
  88. /** {@inheritDoc} */
  89. public void finalizeNode() throws FOPException {
  90. if (!inMarker()) {
  91. pendingSpans = null;
  92. columnNumberManager = null;
  93. }
  94. if (!(tableRowsFound || tableCellsFound)) {
  95. missingChildElementError("marker* (table-row+|table-cell+)", true);
  96. getParent().removeChild(this);
  97. } else {
  98. finishLastRowGroup();
  99. }
  100. }
  101. /** {@inheritDoc} */
  102. TablePart getTablePart() {
  103. return this;
  104. }
  105. /**
  106. * Finish last row group.
  107. * @throws ValidationException if content validation exception
  108. */
  109. protected void finishLastRowGroup() throws ValidationException {
  110. if (!inMarker()) {
  111. RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder();
  112. if (tableRowsFound) {
  113. rowGroupBuilder.endTableRow();
  114. } else if (!lastCellEndsRow) {
  115. rowGroupBuilder.endRow(this);
  116. }
  117. try {
  118. rowGroupBuilder.endTablePart();
  119. } catch (ValidationException e) {
  120. e.setLocator(locator);
  121. throw e;
  122. }
  123. }
  124. }
  125. /**
  126. * {@inheritDoc}
  127. * <br>XSL Content Model: marker* (table-row+|table-cell+)
  128. */
  129. protected void validateChildNode(Locator loc, String nsURI, String localName)
  130. throws ValidationException {
  131. if (FO_URI.equals(nsURI)) {
  132. if (localName.equals("marker")) {
  133. if (tableRowsFound || tableCellsFound) {
  134. nodesOutOfOrderError(loc, "fo:marker", "(table-row+|table-cell+)");
  135. }
  136. } else if (localName.equals("table-row")) {
  137. tableRowsFound = true;
  138. if (tableCellsFound) {
  139. TableEventProducer eventProducer = TableEventProducer.Provider.get(
  140. getUserAgent().getEventBroadcaster());
  141. eventProducer.noMixRowsAndCells(this, getName(), getLocator());
  142. }
  143. } else if (localName.equals("table-cell")) {
  144. tableCellsFound = true;
  145. if (tableRowsFound) {
  146. TableEventProducer eventProducer = TableEventProducer.Provider.get(
  147. getUserAgent().getEventBroadcaster());
  148. eventProducer.noMixRowsAndCells(this, getName(), getLocator());
  149. }
  150. } else if (localName.equals("retrieve-table-marker")) {
  151. notSupportedChildError(loc, nsURI, localName);
  152. } else {
  153. invalidChildError(loc, nsURI, localName);
  154. }
  155. }
  156. }
  157. /** {@inheritDoc} */
  158. protected void addChildNode(FONode child) throws FOPException {
  159. if (!inMarker()) {
  160. switch (child.getNameId()) {
  161. case FO_TABLE_ROW:
  162. if (!rowsStarted) {
  163. getTable().getRowGroupBuilder().startTablePart(this);
  164. } else {
  165. columnNumberManager.prepareForNextRow(pendingSpans);
  166. getTable().getRowGroupBuilder().endTableRow();
  167. }
  168. rowsStarted = true;
  169. getTable().getRowGroupBuilder().startTableRow((TableRow)child);
  170. break;
  171. case FO_TABLE_CELL:
  172. if (!rowsStarted) {
  173. getTable().getRowGroupBuilder().startTablePart(this);
  174. }
  175. rowsStarted = true;
  176. TableCell cell = (TableCell) child;
  177. addTableCellChild(cell, firstRow);
  178. lastCellEndsRow = cell.endsRow();
  179. if (lastCellEndsRow) {
  180. firstRow = false;
  181. columnNumberManager.prepareForNextRow(pendingSpans);
  182. getTable().getRowGroupBuilder().endRow(this);
  183. }
  184. break;
  185. default:
  186. //nop
  187. }
  188. }
  189. //TODO: possible performance problems in case of large tables...
  190. //If the number of children grows significantly large, the default
  191. //implementation in FObj will get slower and slower...
  192. super.addChildNode(child);
  193. }
  194. void addRowGroup(List rowGroup) {
  195. rowGroups.add(rowGroup);
  196. }
  197. /** @return list of row groups */
  198. public List getRowGroups() {
  199. return rowGroups;
  200. }
  201. /**
  202. * Get the {@link CommonBorderPaddingBackground} instance attached
  203. * to this TableBody.
  204. * @return the {@link CommonBorderPaddingBackground} instance.
  205. */
  206. public CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
  207. return commonBorderPaddingBackground;
  208. }
  209. /**
  210. * @param obj table row in question
  211. * @return true if the given table row is the first row of this body.
  212. */
  213. public boolean isFirst(TableRow obj) {
  214. return (firstChild == null
  215. || firstChild == obj);
  216. }
  217. void signalNewRow() {
  218. if (rowsStarted) {
  219. firstRow = false;
  220. if (!lastCellEndsRow) {
  221. columnNumberManager.prepareForNextRow(pendingSpans);
  222. getTable().getRowGroupBuilder().endRow(this);
  223. }
  224. }
  225. }
  226. }