001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: Root.java 535883 2007-05-07 14:30:23Z jeremias $ */
019:
020: package org.apache.fop.fo.pagination;
021:
022: // java
023: import java.util.List;
024:
025: import org.xml.sax.Locator;
026:
027: import org.apache.fop.apps.FOPException;
028: import org.apache.fop.fo.FOEventHandler;
029: import org.apache.fop.fo.FONode;
030: import org.apache.fop.fo.FObj;
031: import org.apache.fop.fo.PropertyList;
032: import org.apache.fop.fo.ValidationException;
033: import org.apache.fop.fo.pagination.bookmarks.BookmarkTree;
034: import org.apache.fop.fo.extensions.destination.Destination;
035:
036: /**
037: * The fo:root formatting object. Contains page masters, page-sequences.
038: */
039: public class Root extends FObj {
040: // The value of properties relevant for fo:root.
041: private int mediaUsage;
042: // End of property values
043:
044: private LayoutMasterSet layoutMasterSet;
045: private Declarations declarations;
046: private BookmarkTree bookmarkTree = null;
047: private List destinationList;
048: private List pageSequences;
049:
050: // temporary until above list populated
051: private boolean pageSequenceFound = false;
052:
053: /**
054: * Keeps count of page number from over PageSequence instances
055: */
056: private int endingPageNumberOfPreviousSequence = 0;
057: private int totalPagesGenerated = 0;
058:
059: /**
060: * FOEventHandler object for this FO Tree
061: */
062: private FOEventHandler foEventHandler = null;
063:
064: /**
065: * @see org.apache.fop.fo.FONode#FONode(FONode)
066: */
067: public Root(FONode parent) {
068: super (parent);
069: pageSequences = new java.util.ArrayList();
070: if (parent != null) {
071: //throw new FOPException("root must be root element");
072: }
073: }
074:
075: /**
076: * @see org.apache.fop.fo.FObj#bind(PropertyList)
077: */
078: public void bind(PropertyList pList) throws FOPException {
079: mediaUsage = pList.get(PR_MEDIA_USAGE).getEnum();
080: }
081:
082: /**
083: * Signal end of this xml element.
084: */
085: protected void endOfNode() throws FOPException {
086: if (!pageSequenceFound || layoutMasterSet == null) {
087: missingChildElementError("(layout-master-set, declarations?, "
088: + "bookmark-tree?, page-sequence+)");
089: }
090: }
091:
092: /**
093: * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
094: XSL 1.0 Spec: (layout-master-set,declarations?,page-sequence+)
095: FOP: (layout-master-set, declarations?, fox:bookmarks?, page-sequence+)
096: */
097: protected void validateChildNode(Locator loc, String nsURI,
098: String localName) throws ValidationException {
099: if (FO_URI.equals(nsURI)) {
100: if (localName.equals("layout-master-set")) {
101: if (layoutMasterSet != null) {
102: tooManyNodesError(loc, "fo:layout-master-set");
103: }
104: } else if (localName.equals("declarations")) {
105: if (layoutMasterSet == null) {
106: nodesOutOfOrderError(loc, "fo:layout-master-set",
107: "fo:declarations");
108: } else if (declarations != null) {
109: tooManyNodesError(loc, "fo:declarations");
110: } else if (bookmarkTree != null) {
111: nodesOutOfOrderError(loc, "fo:declarations",
112: "fo:bookmark-tree");
113: } else if (pageSequenceFound) {
114: nodesOutOfOrderError(loc, "fo:declarations",
115: "fo:page-sequence");
116: }
117: } else if (localName.equals("bookmark-tree")) {
118: if (layoutMasterSet == null) {
119: nodesOutOfOrderError(loc, "fo:layout-master-set",
120: "fo:bookmark-tree");
121: } else if (bookmarkTree != null) {
122: tooManyNodesError(loc, "fo:bookmark-tree");
123: } else if (pageSequenceFound) {
124: nodesOutOfOrderError(loc, "fo:bookmark-tree",
125: "fo:page-sequence");
126: }
127: } else if (localName.equals("page-sequence")) {
128: if (layoutMasterSet == null) {
129: nodesOutOfOrderError(loc, "fo:layout-master-set",
130: "fo:page-sequence");
131: } else {
132: pageSequenceFound = true;
133: }
134: } else {
135: invalidChildError(loc, nsURI, localName);
136: }
137: } else {
138: invalidChildError(loc, nsURI, localName);
139: }
140: }
141:
142: /**
143: * Sets the FOEventHandler object that this Root is attached to
144: * @param foEventHandler the FOEventHandler object
145: */
146: public void setFOEventHandler(FOEventHandler foEventHandler) {
147: this .foEventHandler = foEventHandler;
148: }
149:
150: /**
151: * This method overrides the FONode version. The FONode version calls the
152: * method by the same name for the parent object. Since Root is at the top
153: * of the tree, it returns the actual FOEventHandler object. Thus, any FONode
154: * can use this chain to find which FOEventHandler it is being built for.
155: * @return the FOEventHandler implementation that this Root is attached to
156: */
157: public FOEventHandler getFOEventHandler() {
158: return foEventHandler;
159: }
160:
161: /**
162: * Gets the last page number generated by the previous page-sequence
163: * @return the last page number, 0 if no page sequences yet generated
164: */
165: public int getEndingPageNumberOfPreviousSequence() {
166: return endingPageNumberOfPreviousSequence;
167: }
168:
169: /**
170: * Returns the total number of pages generated by FOP
171: * (May not equal endingPageNumberOfPreviousSequence due to
172: * initial-page-number property on fo:page-sequences.)
173: * @return the last page number, 0 if no page sequences yet generated
174: */
175: public int getTotalPagesGenerated() {
176: return totalPagesGenerated;
177: }
178:
179: /**
180: * Notify additional pages generated to increase the totalPagesGenerated counter
181: * @param lastPageNumber the last page number generated by the sequence
182: * @param additionalPages the total pages generated by the sequence (for statistics)
183: * @throws IllegalArgumentException for negative additional page counts
184: */
185: public void notifyPageSequenceFinished(int lastPageNumber,
186: int additionalPages) {
187:
188: if (additionalPages >= 0) {
189: totalPagesGenerated += additionalPages;
190: endingPageNumberOfPreviousSequence = lastPageNumber;
191: } else {
192: throw new IllegalArgumentException(
193: "Number of additional pages must be zero or greater.");
194: }
195: }
196:
197: /**
198: * Returns the number of PageSequence instances.
199: * @return the number of PageSequence instances
200: */
201: public int getPageSequenceCount() {
202: return pageSequences.size();
203: }
204:
205: /**
206: * Some properties, such as 'force-page-count', require a
207: * page-sequence to know about some properties of the next.
208: * @param current the current PageSequence
209: * @return succeeding PageSequence; null if none
210: */
211: public PageSequence getSucceedingPageSequence(PageSequence current) {
212: int currentIndex = pageSequences.indexOf(current);
213: if (currentIndex == -1) {
214: return null;
215: }
216: if (currentIndex < (pageSequences.size() - 1)) {
217: return (PageSequence) pageSequences.get(currentIndex + 1);
218: } else {
219: return null;
220: }
221: }
222:
223: /**
224: * Returns the associated LayoutMasterSet.
225: * @return the LayoutMasterSet instance
226: */
227: public LayoutMasterSet getLayoutMasterSet() {
228: return this .layoutMasterSet;
229: }
230:
231: /**
232: * Sets the associated LayoutMasterSet.
233: * @param layoutMasterSet the LayoutMasterSet to use
234: */
235: public void setLayoutMasterSet(LayoutMasterSet layoutMasterSet) {
236: this .layoutMasterSet = layoutMasterSet;
237: }
238:
239: /**
240: * Returns the associated Declarations.
241: * @return the Declarations instance
242: */
243: public Declarations getDeclarations() {
244: return this .declarations;
245: }
246:
247: /**
248: * Sets the associated Declarations.
249: * @param declarations the Declarations to use
250: */
251: public void setDeclarations(Declarations declarations) {
252: this .declarations = declarations;
253: }
254:
255: /**
256: * Set the BookmarkTree object for this FO
257: * @param bookmarkTree the BookmarkTree object
258: */
259: public void setBookmarkTree(BookmarkTree bookmarkTree) {
260: this .bookmarkTree = bookmarkTree;
261: }
262:
263: /**
264: * Add a Destination object to this FO
265: * @param destination the Destination object to add
266: */
267: public void addDestination(Destination destination) {
268: if (destinationList == null) {
269: destinationList = new java.util.ArrayList();
270: }
271: destinationList.add(destination);
272: }
273:
274: /**
275: * Public accessor for the list of Destination objects for this FO
276: * @return the Destination object
277: */
278: public List getDestinationList() {
279: return destinationList;
280: }
281:
282: /**
283: * Public accessor for the BookmarkTree object for this FO
284: * @return the BookmarkTree object
285: */
286: public BookmarkTree getBookmarkTree() {
287: return bookmarkTree;
288: }
289:
290: /**
291: * @see org.apache.fop.fo.FONode#getRoot()
292: */
293: public Root getRoot() {
294: return this ;
295: }
296:
297: /** @see org.apache.fop.fo.FONode#getLocalName() */
298: public String getLocalName() {
299: return "root";
300: }
301:
302: /**
303: * @see org.apache.fop.fo.FObj#getNameId()
304: */
305: public int getNameId() {
306: return FO_ROOT;
307: }
308:
309: }
|