]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugzilla 42089: Cleanup and restructuring (suggested by Adrian Cumiskey)
authorAndreas L. Delmelle <adelmelle@apache.org>
Sat, 7 Jul 2007 00:04:25 +0000 (00:04 +0000)
committerAndreas L. Delmelle <adelmelle@apache.org>
Sat, 7 Jul 2007 00:04:25 +0000 (00:04 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@554094 13f79535-47bb-0310-9956-ffa450edef68

42 files changed:
src/java/org/apache/fop/area/AreaTreeHandler.java
src/java/org/apache/fop/area/IDTracker.java [new file with mode: 0644]
src/java/org/apache/fop/area/RenderPagesModel.java
src/java/org/apache/fop/fo/FObj.java
src/java/org/apache/fop/fo/flow/AbstractListItemPart.java
src/java/org/apache/fop/fo/flow/BasicLink.java
src/java/org/apache/fop/fo/flow/Block.java
src/java/org/apache/fop/fo/flow/BlockContainer.java
src/java/org/apache/fop/fo/flow/Character.java
src/java/org/apache/fop/fo/flow/ExternalGraphic.java
src/java/org/apache/fop/fo/flow/InitialPropertySet.java
src/java/org/apache/fop/fo/flow/Inline.java
src/java/org/apache/fop/fo/flow/InlineContainer.java
src/java/org/apache/fop/fo/flow/InlineLevel.java
src/java/org/apache/fop/fo/flow/InstreamForeignObject.java
src/java/org/apache/fop/fo/flow/Leader.java
src/java/org/apache/fop/fo/flow/ListBlock.java
src/java/org/apache/fop/fo/flow/ListItem.java
src/java/org/apache/fop/fo/flow/MultiCase.java
src/java/org/apache/fop/fo/flow/MultiProperties.java
src/java/org/apache/fop/fo/flow/MultiPropertySet.java
src/java/org/apache/fop/fo/flow/MultiSwitch.java
src/java/org/apache/fop/fo/flow/PageNumber.java
src/java/org/apache/fop/fo/flow/PageNumberCitation.java
src/java/org/apache/fop/fo/flow/Table.java
src/java/org/apache/fop/fo/flow/TableAndCaption.java
src/java/org/apache/fop/fo/flow/TableCaption.java
src/java/org/apache/fop/fo/flow/TableCell.java
src/java/org/apache/fop/fo/flow/TableFObj.java
src/java/org/apache/fop/fo/flow/TableRow.java
src/java/org/apache/fop/fo/flow/Wrapper.java
src/java/org/apache/fop/fo/pagination/PageSequence.java
src/java/org/apache/fop/fo/pagination/PageSequenceWrapper.java
src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java
src/java/org/apache/fop/layoutmgr/PageBreaker.java [new file with mode: 0644]
src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
src/java/org/apache/fop/layoutmgr/PageProvider.java [new file with mode: 0644]
src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java
src/java/org/apache/fop/render/rtf/RTFHandler.java
status.xml

index 0104d06881f604fb29c6ab5e02815a3ae66fece2..6903510d0de84eb83238ca3f51a5f4c934425cf4 100644 (file)
@@ -21,12 +21,7 @@ package org.apache.fop.area;
 
 // Java
 import java.io.OutputStream;
-import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Set;
-import java.util.HashSet;
 import java.util.Iterator;
 
 // XML
@@ -65,34 +60,24 @@ import org.apache.fop.fo.extensions.destination.Destination;
  * type of renderer.
  */
 public class AreaTreeHandler extends FOEventHandler {
+    
+    private static Log log = LogFactory.getLog(AreaTreeHandler.class);
 
-    /** debug statistics */
+    // Recorder of debug statistics
     private Statistics statistics = null;
 
-    private static Log log = LogFactory.getLog(AreaTreeHandler.class);
-
-    // the LayoutManager maker
+    // The LayoutManager maker
     private LayoutManagerMaker lmMaker;
 
-    /** AreaTreeModel in use */
+    /** The AreaTreeModel in use */
     protected AreaTreeModel model;
 
+    // Keeps track of all meaningful id references
+    private IDTracker idTracker;
+
     // The fo:root node of the document
     private Root rootFObj;
-
-    // HashMap of ID's whose area is located on one or more consecutive
-    // PageViewports. Each ID has an arraylist of PageViewports that
-    // form the defined area of this ID
-    private Map idLocations = new HashMap();
-
-    // idref's whose target PageViewports have yet to be identified
-    // Each idref has a HashSet of Resolvable objects containing that idref
-    private Map unresolvedIDRefs = new HashMap();
-
-    private Set unfinishedIDs = new HashSet();
-
-    private Set alreadyResolvedIDs = new HashSet();
-
+    
     // The formatting results to be handed back to the caller.
     private FormattingResults results = new FormattingResults();
 
@@ -120,6 +105,8 @@ public class AreaTreeHandler extends FOEventHandler {
             lmMaker = new LayoutManagerMapping();
         }
 
+        idTracker = new IDTracker();
+        
         if (log.isDebugEnabled()) {
             statistics = new Statistics();
         }
@@ -159,137 +146,12 @@ public class AreaTreeHandler extends FOEventHandler {
     }
 
     /**
-     * Tie a PageViewport with an ID found on a child area of the PV. Note that
-     * an area with a given ID may be on more than one PV, hence an ID may have
-     * more than one PV associated with it.
+     * Get the IDTracker for this area tree.
      * 
-     * @param id the property ID of the area
-     * @param pv a page viewport that contains the area with this ID
+     * @return IDTracker used to track reference ids for items in this area tree
      */
-    public void associateIDWithPageViewport(String id, PageViewport pv) {
-        if (log.isDebugEnabled()) {
-            log.debug("associateIDWithPageViewport(" + id + ", " + pv + ")");
-        }
-        List pvList = (List) idLocations.get(id);
-        if (pvList == null) { // first time ID located
-            pvList = new ArrayList();
-            idLocations.put(id, pvList);
-            pvList.add(pv);
-            // signal the PageViewport that it is the first PV to contain this id:
-            pv.setFirstWithID(id);
-            /*
-             * See if this ID is in the unresolved idref list, if so resolve
-             * Resolvable objects tied to it.
-             */
-            if (!unfinishedIDs.contains(id)) {
-                tryIDResolution(id, pv, pvList);
-            }
-        } else {
-            pvList.add(pv);
-        }
-    }
-
-    /**
-     * This method tie an ID to the areaTreeHandler until this one is ready to
-     * be processed. This is used in page-number-citation-last processing so we
-     * know when an id can be resolved.
-     * 
-     * @param id the id of the object being processed
-     */
-    public void signalPendingID(String id) {
-        if (log.isDebugEnabled()) {
-            log.debug("signalPendingID(" + id + ")");
-        }
-        unfinishedIDs.add(id);
-    }
-
-    /**
-     * Signals that all areas for the formatting object with the given ID have
-     * been generated. This is used to determine when page-number-citation-last
-     * ref-ids can be resolved.
-     * 
-     * @param id the id of the formatting object which was just finished
-     */
-    public void signalIDProcessed(String id) {
-        if (log.isDebugEnabled()) {
-            log.debug("signalIDProcessed(" + id + ")");
-        }
-
-        alreadyResolvedIDs.add(id);
-        if (!unfinishedIDs.contains(id)) {
-            return;
-        }
-        unfinishedIDs.remove(id);
-
-        List pvList = (List) idLocations.get(id);
-        Set todo = (Set) unresolvedIDRefs.get(id);
-        if (todo != null) {
-            for (Iterator iter = todo.iterator(); iter.hasNext();) {
-                Resolvable res = (Resolvable) iter.next();
-                res.resolveIDRef(id, pvList);
-            }
-            unresolvedIDRefs.remove(id);
-        }
-    }
-
-    /**
-     * Check if an ID has already been resolved
-     * 
-     * @param id the id to check
-     * @return true if the ID has been resolved
-     */
-    public boolean alreadyResolvedID(String id) {
-        return (alreadyResolvedIDs.contains(id));
-    }
-
-    /**
-     * Tries to resolve all unresolved ID references on the given page.
-     * 
-     * @param id ID to resolve
-     * @param pv page viewport whose ID refs to resolve
-     * @param List of PageViewports
-     */
-    private void tryIDResolution(String id, PageViewport pv, List pvList) {
-        Set todo = (Set) unresolvedIDRefs.get(id);
-        if (todo != null) {
-            for (Iterator iter = todo.iterator(); iter.hasNext();) {
-                Resolvable res = (Resolvable) iter.next();
-                if (!unfinishedIDs.contains(id)) {
-                    res.resolveIDRef(id, pvList);
-                } else {
-                    return;
-                }
-            }
-            alreadyResolvedIDs.add(id);
-            unresolvedIDRefs.remove(id);
-        }
-    }
-
-    /**
-     * Tries to resolve all unresolved ID references on the given page.
-     * 
-     * @param pv page viewport whose ID refs to resolve
-     */
-    public void tryIDResolution(PageViewport pv) {
-        String[] ids = pv.getIDRefs();
-        if (ids != null) {
-            for (int i = 0; i < ids.length; i++) {
-                List pvList = (List) idLocations.get(ids[i]);
-                if (pvList != null) {
-                    tryIDResolution(ids[i], pv, pvList);
-                }
-            }
-        }
-    }
-
-    /**
-     * Get the list of page viewports that have an area with a given id.
-     * 
-     * @param id the id to lookup
-     * @return the list of PageViewports
-     */
-    public List getPageViewportsContainingID(String id) {
-        return (List) idLocations.get(id);
+    public IDTracker getIDTracker() {
+        return idTracker;
     }
 
     /**
@@ -301,22 +163,6 @@ public class AreaTreeHandler extends FOEventHandler {
         return this.results;
     }
 
-    /**
-     * Add an Resolvable object with an unresolved idref
-     * 
-     * @param idref the idref whose target id has not yet been located
-     * @param res the Resolvable object needing the idref to be resolved
-     */
-    public void addUnresolvedIDRef(String idref, Resolvable res) {
-        Set todo = (Set) unresolvedIDRefs.get(idref);
-        if (todo == null) {
-            todo = new HashSet();
-            unresolvedIDRefs.put(idref, todo);
-        }
-        // add Resolvable object to this HashSet
-        todo.add(res);
-    }
-
     /**
      * Prepare AreaTreeHandler for document processing This is called from
      * FOTreeBuilder.startDocument()
@@ -453,12 +299,13 @@ public class AreaTreeHandler extends FOEventHandler {
             Resolvable res = (Resolvable) odi;
             String[] ids = res.getIDRefs();
             for (int count = 0; count < ids.length; count++) {
-                if (idLocations.containsKey(ids[count])) {
-                    res.resolveIDRef(ids[count], (List) idLocations.get(ids[count]));
+                List pageVPList = idTracker.getPageViewportsContainingID(ids[count]);
+                if (pageVPList != null) {
+                    res.resolveIDRef(ids[count], pageVPList);
                 } else {
                     log.warn(odi.getName() + ": Unresolved id reference \""
                             + ids[count] + "\" found.");
-                    addUnresolvedIDRef(ids[count], res);
+                    idTracker.addUnresolvedIDRef(ids[count], res);
                 }
             }
             // check to see if ODI is now fully resolved, if so process it
@@ -481,9 +328,86 @@ public class AreaTreeHandler extends FOEventHandler {
     }
 
     /**
-     * Gather statistics when log is debug
+     * Tie a PageViewport with an ID found on a child area of the PV. Note that
+     * an area with a given ID may be on more than one PV, hence an ID may have
+     * more than one PV associated with it.
+     * 
+     * @param id the property ID of the area
+     * @param pv a page viewport that contains the area with this ID
+     * @deprecated use getIdTracker().associateIDWithPageViewport(id, pv) instead
+     */
+    public void associateIDWithPageViewport(String id, PageViewport pv) {
+        idTracker.associateIDWithPageViewport(id, pv);
+    }
+
+    /**
+     * This method tie an ID to the areaTreeHandler until this one is ready to
+     * be processed. This is used in page-number-citation-last processing so we
+     * know when an id can be resolved.
+     * 
+     * @param id the id of the object being processed
+     * @deprecated use getIdTracker().signalPendingID(id) instead
+     */
+    public void signalPendingID(String id) {
+        idTracker.signalPendingID(id);
+    }
+
+    /**
+     * Signals that all areas for the formatting object with the given ID have
+     * been generated. This is used to determine when page-number-citation-last
+     * ref-ids can be resolved.
+     * 
+     * @param id the id of the formatting object which was just finished
+     * @deprecated use getIdTracker().signalIDProcessed(id) instead
+     */
+    public void signalIDProcessed(String id) {
+        idTracker.signalIDProcessed(id);
+    }
+
+    /**
+     * Check if an ID has already been resolved
+     * 
+     * @param id the id to check
+     * @return true if the ID has been resolved
+     * @deprecated use getIdTracker().alreadyResolvedID(id) instead
+     */
+    public boolean alreadyResolvedID(String id) {
+        return idTracker.alreadyResolvedID(id);
+    }
+
+    /**
+     * Tries to resolve all unresolved ID references on the given page.
+     * 
+     * @param pv page viewport whose ID refs to resolve
+     * @deprecated use getIdTracker().tryIDResolution(pv) instead
+     */
+    public void tryIDResolution(PageViewport pv) {
+        idTracker.tryIDResolution(pv);
+    }
+
+    /**
+     * Get the list of page viewports that have an area with a given id.
+     * 
+     * @param id the id to lookup
+     * @return the list of PageViewports
+     * @deprecated use getIdTracker().getPageViewportsContainingID(id) instead
+     */
+    public List getPageViewportsContainingID(String id) {
+        return idTracker.getPageViewportsContainingID(id);
+    }
+
+    /**
+     * Add an Resolvable object with an unresolved idref
+     * 
+     * @param idref the idref whose target id has not yet been located
+     * @param res the Resolvable object needing the idref to be resolved
+     * @deprecated use getIdTracker().addUnresolvedIDRef(idref, res) instead
      */
-    private final class Statistics {
+    public void addUnresolvedIDRef(String idref, Resolvable res) {
+        idTracker.addUnresolvedIDRef(idref, res);
+    }
+    
+    private class Statistics {
         // for statistics gathering
         private Runtime runtime;
 
@@ -493,21 +417,34 @@ public class AreaTreeHandler extends FOEventHandler {
         // time used in rendering (for statistics)
         private long startTime;
 
-        private Statistics() {
-            runtime = Runtime.getRuntime();
+        /**
+         * Default constructor
+         * @param areaTreeHandler area tree handler
+         */
+        protected Statistics() {
+            this.runtime = Runtime.getRuntime();
         }
 
-        public void start() {
-            initialMemory = runtime.totalMemory() - runtime.freeMemory();
-            startTime = System.currentTimeMillis();
+        /**
+         * starts the area tree handler statistics gathering
+         */
+        protected void start() {
+            this.initialMemory = runtime.totalMemory() - runtime.freeMemory();
+            this.startTime = System.currentTimeMillis();
         }
 
-        public void end() {
+        /**
+         * ends the area tree handler statistics gathering
+         */
+        protected void end() {
             long memoryNow = runtime.totalMemory() - runtime.freeMemory();
             log.debug("Current heap size: " + (memoryNow / 1024L) + "KB");
         }
 
-        public void logResults() {
+        /**
+         * logs the results of the area tree handler statistics gathering
+         */
+        protected void logResults() {
             long memoryNow = runtime.totalMemory() - runtime.freeMemory();
             long memoryUsed = (memoryNow - initialMemory) / 1024L;
             long timeUsed = System.currentTimeMillis() - startTime;
diff --git a/src/java/org/apache/fop/area/IDTracker.java b/src/java/org/apache/fop/area/IDTracker.java
new file mode 100644 (file)
index 0000000..d073bdb
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * 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.area;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Used by the AreaTreeHandler to keep track of ID reference usage
+ * on a PageViewport level.
+ */
+public class IDTracker {
+    
+    private static Log log = LogFactory.getLog(IDTracker.class);
+
+    // HashMap of ID's whose area is located on one or more consecutive
+    // PageViewports. Each ID has an arraylist of PageViewports that
+    // form the defined area of this ID
+    private Map idLocations = new HashMap();
+
+    // idref's whose target PageViewports have yet to be identified
+    // Each idref has a HashSet of Resolvable objects containing that idref
+    private Map unresolvedIDRefs = new HashMap();
+
+    private Set unfinishedIDs = new HashSet();
+
+    private Set alreadyResolvedIDs = new HashSet();
+    
+    /**
+     * Tie a PageViewport with an ID found on a child area of the PV. Note that
+     * an area with a given ID may be on more than one PV, hence an ID may have
+     * more than one PV associated with it.
+     * 
+     * @param id the property ID of the area
+     * @param pv a page viewport that contains the area with this ID
+     */
+    public void associateIDWithPageViewport(String id, PageViewport pv) {
+        if (log.isDebugEnabled()) {
+            log.debug("associateIDWithPageViewport(" + id + ", " + pv + ")");
+        }
+        List pvList = (List) idLocations.get(id);
+        if (pvList == null) { // first time ID located
+            pvList = new ArrayList();
+            idLocations.put(id, pvList);
+            pvList.add(pv);
+            // signal the PageViewport that it is the first PV to contain this id:
+            pv.setFirstWithID(id);
+            /*
+             * See if this ID is in the unresolved idref list, if so resolve
+             * Resolvable objects tied to it.
+             */
+            if (!unfinishedIDs.contains(id)) {
+                tryIDResolution(id, pv, pvList);
+            }
+        } else {
+            pvList.add(pv);
+        }
+    }
+
+    /**
+     * This method tie an ID to the areaTreeHandler until this one is ready to
+     * be processed. This is used in page-number-citation-last processing so we
+     * know when an id can be resolved.
+     * 
+     * @param id the id of the object being processed
+     */
+    public void signalPendingID(String id) {
+        if (log.isDebugEnabled()) {
+            log.debug("signalPendingID(" + id + ")");
+        }
+        unfinishedIDs.add(id);
+    }
+
+    /**
+     * Signals that all areas for the formatting object with the given ID have
+     * been generated. This is used to determine when page-number-citation-last
+     * ref-ids can be resolved.
+     * 
+     * @param id the id of the formatting object which was just finished
+     */
+    public void signalIDProcessed(String id) {
+        if (log.isDebugEnabled()) {
+            log.debug("signalIDProcessed(" + id + ")");
+        }
+
+        alreadyResolvedIDs.add(id);
+        if (!unfinishedIDs.contains(id)) {
+            return;
+        }
+        unfinishedIDs.remove(id);
+
+        List pvList = (List) idLocations.get(id);
+        Set todo = (Set) unresolvedIDRefs.get(id);
+        if (todo != null) {
+            for (Iterator iter = todo.iterator(); iter.hasNext();) {
+                Resolvable res = (Resolvable) iter.next();
+                res.resolveIDRef(id, pvList);
+            }
+            unresolvedIDRefs.remove(id);
+        }
+    }
+    
+    /**
+     * Check if an ID has already been resolved
+     * 
+     * @param id the id to check
+     * @return true if the ID has been resolved
+     */
+    public boolean alreadyResolvedID(String id) {
+        return (alreadyResolvedIDs.contains(id));
+    }
+    
+    /**
+     * Tries to resolve all unresolved ID references on the given page.
+     * 
+     * @param id ID to resolve
+     * @param pv page viewport whose ID refs to resolve
+     * @param List of PageViewports
+     */
+    private void tryIDResolution(String id, PageViewport pv, List pvList) {
+        Set todo = (Set) unresolvedIDRefs.get(id);
+        if (todo != null) {
+            for (Iterator iter = todo.iterator(); iter.hasNext();) {
+                Resolvable res = (Resolvable) iter.next();
+                if (!unfinishedIDs.contains(id)) {
+                    res.resolveIDRef(id, pvList);
+                } else {
+                    return;
+                }
+            }
+            alreadyResolvedIDs.add(id);
+            unresolvedIDRefs.remove(id);
+        }
+    }
+
+    /**
+     * Tries to resolve all unresolved ID references on the given page.
+     * 
+     * @param pv page viewport whose ID refs to resolve
+     */
+    public void tryIDResolution(PageViewport pv) {
+        String[] ids = pv.getIDRefs();
+        if (ids != null) {
+            for (int i = 0; i < ids.length; i++) {
+                List pvList = (List) idLocations.get(ids[i]);
+                if (pvList != null) {
+                    tryIDResolution(ids[i], pv, pvList);
+                }
+            }
+        }
+    }
+    
+    /**
+     * Get the list of page viewports that have an area with a given id.
+     * 
+     * @param id the id to lookup
+     * @return the list of PageViewports
+     */
+    public List getPageViewportsContainingID(String id) {
+        return (List) idLocations.get(id);
+    }
+    
+    /**
+     * Add an Resolvable object with an unresolved idref
+     * 
+     * @param idref the idref whose target id has not yet been located
+     * @param res the Resolvable object needing the idref to be resolved
+     */
+    public void addUnresolvedIDRef(String idref, Resolvable res) {
+        Set todo = (Set) unresolvedIDRefs.get(idref);
+        if (todo == null) {
+            todo = new HashSet();
+            unresolvedIDRefs.put(idref, todo);
+        }
+        // add Resolvable object to this HashSet
+        todo.add(res);
+    }        
+}
index da9305fa1a8092c7f55b26332a6ece3035051f05..ca2d51c8be94d4e6b20d81438f6ab727c6bf8fc0 100644 (file)
@@ -145,27 +145,28 @@ public class RenderPagesModel extends AreaTreeModel {
     /**
      * Check prepared pages
      *
-     * @param newpage the new page being added
+     * @param newPageViewport the new page being added
      * @param renderUnresolved render pages with unresolved idref's
      *          (done at end-of-document processing)
      * @return true if the current page should be rendered
      *         false if the renderer doesn't support out of order
      *         rendering and there are pending pages
      */
-    protected boolean checkPreparedPages(PageViewport newpage, boolean
+    protected boolean checkPreparedPages(PageViewport newPageViewport, boolean
         renderUnresolved) {
         for (Iterator iter = prepared.iterator(); iter.hasNext();) {
-            PageViewport p = (PageViewport)iter.next();
-            if (p.isResolved() || renderUnresolved) {
-                if (!renderer.supportsOutOfOrder() && p.getPageSequence().isFirstPage(p)) {
+            PageViewport pageViewport = (PageViewport)iter.next();
+            if (pageViewport.isResolved() || renderUnresolved) {
+                if (!renderer.supportsOutOfOrder()
+                        && pageViewport.getPageSequence().isFirstPage(pageViewport)) {
                     renderer.startPageSequence(this.currentPageSequence.getTitle());
                 }
                 try {
-                    renderer.renderPage(p);
-                    if (!p.isResolved()) {
-                        String[] idrefs = p.getIDRefs();
+                    renderer.renderPage(pageViewport);
+                    if (!pageViewport.isResolved()) {
+                        String[] idrefs = pageViewport.getIDRefs();
                         for (int count = 0; count < idrefs.length; count++) {
-                            log.warn("Page " + p.getPageNumberString()
+                            log.warn("Page " + pageViewport.getPageNumberString()
                                 + ": Unresolved id reference \"" + idrefs[count] 
                                 + "\" found.");
                         }
@@ -174,7 +175,7 @@ public class RenderPagesModel extends AreaTreeModel {
                     // use error handler to handle this FOP or IO Exception
                     log.error(e);
                 }
-                p.clear();
+                pageViewport.clear();
                 iter.remove();
             } else {
                 // if keeping order then stop at first page not resolved
index 53ba255f848cee211e525f10fb5a9fa6ba00fe9e..75c16ec45fb1321dc8f1a5c7a8b8958b4ff96a7e 100644 (file)
@@ -60,6 +60,10 @@ public abstract class FObj extends FONode implements Constants {
     /** Markers added to this element. */
     private Map markers = null;
     
+    // The value of properties relevant for all fo objects
+    private String id = null;
+    // End of property values
+
     /**
      * Create a new formatting object.
      * All formatting object classes extend this class.
@@ -136,6 +140,17 @@ public abstract class FObj extends FONode implements Constants {
      * @throws FOPException if there is a problem binding the values
      */
     public void bind(PropertyList pList) throws FOPException {
+        id = pList.get(PR_ID).getString();
+    }
+
+    /**
+     * @see org.apache.fop.fo.FONode#startOfNode
+     * @throws FOPException FOP Exception
+     */
+    protected void startOfNode() throws FOPException {
+        if (id != null) {
+            checkId(id);
+        }
     }
 
     /**
@@ -147,7 +162,7 @@ public abstract class FObj extends FONode implements Constants {
      * @throws ValidationException if the ID is already defined elsewhere
      *                              (strict validation only)
      */
-    protected void checkId(String id) throws ValidationException {
+    private void checkId(String id) throws ValidationException {
         if (!inMarker() && !id.equals("")) {
             Set idrefs = getFOEventHandler().getIDReferences();
             if (!idrefs.contains(id)) {
@@ -190,7 +205,7 @@ public abstract class FObj extends FONode implements Constants {
     protected void addChildNode(FONode child) throws FOPException {
         if (canHaveMarkers() && child.getNameId() == FO_MARKER) {
             addMarker((Marker) child);
-        } else {
+        } else { 
             ExtensionAttachment attachment = child.getExtensionAttachment();
             if (attachment != null) {
                 /* This removes the element from the normal children, 
@@ -469,7 +484,16 @@ public abstract class FObj extends FONode implements Constants {
         return -1;
     }
     
+    /** @return the "id" property. */
+    public String getId() {
+        return id;
+    }
     
+    /** @return whether this object has an id set */
+    public boolean hasId() {
+        return id != null && id.length() > 0;
+    }
+
     /** @see org.apache.fop.fo.FONode#getNamespaceURI() */
     public String getNamespaceURI() {
         return FOElementMapping.URI;
index 39efce2cd56d8012fa5f3bb2243f45a58a643b66..2996f5eddeccf1042da4bdd60f7163979039419f 100644 (file)
@@ -34,7 +34,6 @@ import org.apache.fop.fo.properties.KeepProperty;
  */
 public abstract class AbstractListItemPart extends FObj {
     // The value of properties relevant for fo:list-item-label and fo:list-item-body.
-    private String id;
     private KeepProperty keepTogether;
     // Valid properties, commented out for performance:
     //   private CommonAccessibility commonAccessibility;
@@ -54,17 +53,10 @@ public abstract class AbstractListItemPart extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
-        id = pList.get(PR_ID).getString();
+        super.bind(pList);
         keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
     }
 
-    /**
-     * @see org.apache.fop.fo.FONode#startOfNode
-     */
-    protected void startOfNode() throws FOPException {
-        checkId(id);
-    }
-
     /**
      * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
      * XSL Content Model: marker* (%block;)+
@@ -106,11 +98,5 @@ public abstract class AbstractListItemPart extends FObj {
     public KeepProperty getKeepTogether() {
         return keepTogether;
     }
-
-    /** @return the "id" property. */
-    public String getId() {
-        return id;
-    }
-    
 }
 
index c487e54e3067177ddb78c5622172bb6e0763dd6a..c07c3128976ff785681f8949bc41973d4119d6ac 100644 (file)
@@ -128,6 +128,20 @@ public class BasicLink extends Inline {
         return externalDestination;
     }
 
+    /**
+     * @return whether or not this basic link has an internal destination or not
+     */
+    public boolean hasInternalDestination() {
+        return internalDestination != null && internalDestination.length() > 0;
+    }
+
+    /**
+     * @return whether or not this basic link has an external destination or not
+     */
+    public boolean hasExternalDestination() {
+        return externalDestination != null && externalDestination.length() > 0;
+    }
+
     /** @see org.apache.fop.fo.FObj#getLocalName() */
     public String getLocalName() {
         return "basic-link";
index 6beffdfe5cc5771af80397cc8a0b05f80d43ad08..894339b8dceced58f7a6b6643b9513c4bea54ee6 100644 (file)
@@ -32,8 +32,6 @@ import org.apache.fop.fo.FObjMixed;
 import org.apache.fop.fo.NullCharIterator;
 import org.apache.fop.fo.PropertyList;
 import org.apache.fop.fo.ValidationException;
-import org.apache.fop.fo.properties.CommonAccessibility;
-import org.apache.fop.fo.properties.CommonAural;
 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
 import org.apache.fop.fo.properties.CommonFont;
 import org.apache.fop.fo.properties.CommonHyphenation;
@@ -52,8 +50,6 @@ public class Block extends FObjMixed {
     private boolean initialPropertySetFound = false;
 
     // The value of properties relevant for fo:block.
-    private CommonAccessibility commonAccessibility;
-    private CommonAural commonAural;
     private CommonBorderPaddingBackground commonBorderPaddingBackground;
     private CommonFont commonFont;
     private CommonHyphenation commonHyphenation;
@@ -64,7 +60,6 @@ public class Block extends FObjMixed {
     private Color color;
     private int hyphenationKeep;
     private Numeric hyphenationLadderCount;
-    private String id;
     private int intrusionDisplace;
     private KeepProperty keepTogether;
     private KeepProperty keepWithNext;
@@ -84,6 +79,8 @@ public class Block extends FObjMixed {
     private Numeric widows;
     private int wrapOption;
     // Unused but valid items, commented out for performance:
+    //     private CommonAccessibility commonAccessibility;
+    //     private CommonAural commonAural;
     //     private Length textDepth;
     //     private Length textAltitude;
     //     private int visibility;
@@ -101,8 +98,7 @@ public class Block extends FObjMixed {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
-        commonAccessibility = pList.getAccessibilityProps();
-        commonAural = pList.getAuralProps();
+        super.bind(pList);
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         commonFont = pList.getFontProps();
         commonHyphenation = pList.getHyphenationProps();
@@ -114,7 +110,6 @@ public class Block extends FObjMixed {
         color = pList.get(PR_COLOR).getColor(getUserAgent());
         hyphenationKeep = pList.get(PR_HYPHENATION_KEEP).getEnum();
         hyphenationLadderCount = pList.get(PR_HYPHENATION_LADDER_COUNT).getNumeric();
-        id = pList.get(PR_ID).getString();
         intrusionDisplace = pList.get(PR_INTRUSION_DISPLACE).getEnum();
         keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
         keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
@@ -139,7 +134,7 @@ public class Block extends FObjMixed {
      * @see org.apache.fop.fo.FONode#startOfNode
      */
     protected void startOfNode() throws FOPException {
-        checkId(id);
+        super.startOfNode();
         getFOEventHandler().startBlock(this);
     }
 
@@ -231,13 +226,6 @@ public class Block extends FObjMixed {
         return color;
     }
 
-    /**
-     * @return the "id" property.
-     */
-    public String getId() {
-        return id;
-    }
-
     /**
      * @return the "line-height" property.
      */
@@ -347,20 +335,6 @@ public class Block extends FObjMixed {
         return whiteSpaceCollapse;
     }
     
-    /**
-     * @return Returns the commonAccessibility.
-     */
-    public CommonAccessibility getCommonAccessibility() {
-        return this.commonAccessibility;
-    }
-
-    /**
-     * @return Returns the commonAural.
-     */
-    public CommonAural getCommonAural() {
-        return this.commonAural;
-    }
-
     /**
      * @return Returns the commonRelativePosition.
      */
index ea5aee51fd6329ed3fec122ec5f0532aa39abeaa..acffa083f61a00e06896829c53023a09bf6a2606 100644 (file)
@@ -48,7 +48,6 @@ public class BlockContainer extends FObj {
     // private ToBeImplementedProperty clip;
     private int displayAlign;
     private Length height;
-    private String id;
     private LengthRangeProperty inlineProgressionDimension;
     private KeepProperty keepTogether;
     private KeepProperty keepWithNext;
@@ -77,6 +76,7 @@ public class BlockContainer extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
         commonAbsolutePosition = pList.getAbsolutePositionProps();
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         commonMarginBlock = pList.getMarginBlockProps();
@@ -86,7 +86,6 @@ public class BlockContainer extends FObj {
         // clip = pList.get(PR_CLIP);
         displayAlign = pList.get(PR_DISPLAY_ALIGN).getEnum();
         height = pList.get(PR_HEIGHT).getLength();
-        id = pList.get(PR_ID).getString();
         inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange();
         keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
         keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
@@ -102,7 +101,7 @@ public class BlockContainer extends FObj {
      * @see org.apache.fop.fo.FONode#startOfNode
      */
     protected void startOfNode() throws FOPException {
-        checkId(id);
+        super.startOfNode();
         getFOEventHandler().startBlockContainer(this);
     }
 
@@ -203,13 +202,6 @@ public class BlockContainer extends FObj {
         return keepTogether;
     }
 
-    /**
-     * @return the "id" property.
-     */
-    public String getId() {
-        return id;
-    }
-
     /**
      * @return the "inline-progression-dimension" property.
      */
index e83e3711999efacf2c42cf5444495f7d738ce44f..b93ccbea76750fe1a37373752daebafeb820726c 100644 (file)
@@ -68,7 +68,6 @@ public class Character extends FObj {
     private int dominantBaseline;
     // private ToBeImplementedProperty glyphOrientationHorizontal;
     // private ToBeImplementedProperty glyphOrientationVertical;
-    private String id;
     private Property letterSpacing;
     private SpaceProperty lineHeight;
     /** Holds the text decoration values. May be null */
@@ -106,6 +105,7 @@ public class Character extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         commonFont = pList.getFontProps();
         commonHyphenation = pList.getHyphenationProps();
@@ -118,7 +118,6 @@ public class Character extends FObj {
         dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
         // glyphOrientationHorizontal = pList.get(PR_GLYPH_ORIENTATION_HORIZONTAL);
         // glyphOrientationVertical = pList.get(PR_GLYPH_ORIENTATION_VERTICAL);
-        id = pList.get(PR_ID).getString();
         letterSpacing = pList.get(PR_LETTER_SPACING);
         lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
         textDecoration = pList.getTextDecorationProps();
@@ -130,7 +129,7 @@ public class Character extends FObj {
      * @see org.apache.fop.fo.FONode#startOfNode
      */
     protected void startOfNode() throws FOPException {
-        checkId(id);
+        super.startOfNode();
         getFOEventHandler().character(this);
     }
 
@@ -213,13 +212,6 @@ public class Character extends FObj {
         return dominantBaseline;
     }
     
-    /**
-     * @return the "id" property.
-     */
-    public String getId() {
-        return id;
-    }
-
     /**
      * @return the "letter-spacing" property.
      */
index f31c43abfeccce8141d2c1a879ec237aad13e8ba..632812270c86e4c6526729bb90dd113bfea76998 100644 (file)
@@ -83,7 +83,7 @@ public class ExternalGraphic extends AbstractGraphics {
      * @see org.apache.fop.fo.FONode#startOfNode
      */
     protected void startOfNode() throws FOPException {
-        checkId(getId());
+        super.startOfNode();
         getFOEventHandler().image(this);
     }
 
index 9c28d57fb7bf3485c8fa843c3615403309b4fda4..637c5406502a05c5da4d94687c5473997a27172c 100644 (file)
@@ -69,19 +69,12 @@ public class InitialPropertySet extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
-        id = pList.get(PR_ID).getString();
+        super.bind(pList);
         // letterSpacing = pList.get(PR_LETTER_SPACING);
         lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
         // textShadow = pList.get(PR_TEXT_SHADOW);
     }
 
-    /**
-     * @see org.apache.fop.fo.FONode#startOfNode
-     */
-    protected void startOfNode() throws FOPException {
-        checkId(id);
-    }
-
     /**
      * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
      * XSL Content Model: empty
index f4c29508a9bba3503c9e007ae52786278c52caf8..d9ac5136b5ddce33d3f06fced740ded2343a6fa2 100644 (file)
@@ -42,7 +42,6 @@ public class Inline extends InlineLevel {
     private int alignmentBaseline;
     private Length baselineShift;
     private int dominantBaseline;
-    private String id;
     // Unused but valid items, commented out for performance:
     //     private CommonRelativePosition commonRelativePosition;
     //     private LengthRangeProperty blockProgressionDimension;
@@ -74,13 +73,14 @@ public class Inline extends InlineLevel {
         alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
         baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
         dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
-        id = pList.get(PR_ID).getString();
     }
 
     /**
      * @see org.apache.fop.fo.FONode#startOfNode
      */
     protected void startOfNode() throws FOPException {
+       super.startOfNode();
+       
        /* Check to see if this node can have block-level children.
         * See validateChildNode() below.
         */
@@ -99,9 +99,7 @@ public class Inline extends InlineLevel {
            }
        }
 
-        checkId(id);
-        
-        getFOEventHandler().startInline(this);
+       getFOEventHandler().startInline(this);
     }
 
     /**
@@ -140,13 +138,6 @@ public class Inline extends InlineLevel {
         }
     }
 
-    /**
-     * Return the "id" property.
-     */
-    public String getId() {
-        return id;
-    }
-
     /**
      * @return the "alignment-adjust" property
      */
index 85a91c27f11c569f76dbf11070ecf6ada2f54ed1..1d4f621b870274558497e8f8612a8776d27abd9d 100644 (file)
@@ -46,7 +46,6 @@ public class InlineContainer extends FObj {
     private Length baselineShift;
     // private ToBeImplementedProperty clip;
     private int dominantBaseline;
-    private String id;
     private SpaceProperty lineHeight;
     // Unused but valid items, commented out for performance:
     //     private CommonBorderPaddingBackground commonBorderPaddingBackground;
@@ -79,22 +78,15 @@ public class InlineContainer extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
         alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength();
         alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
         baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
         // clip = pList.get(PR_CLIP);
         dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
-        id = pList.get(PR_ID).getString();
         lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
     }
 
-    /**
-     * @see org.apache.fop.fo.FONode#startOfNode
-     */
-    protected void startOfNode() throws FOPException {
-        checkId(id);
-    }
-
     /**
      * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
      * XSL Content Model: marker* (%block;)+
@@ -156,13 +148,6 @@ public class InlineContainer extends FObj {
         return lineHeight;
     }
 
-    /**
-     * @return the "id" property.
-     */
-    public String getId() {
-        return id;
-    }
-
     /** @see org.apache.fop.fo.FONode#getLocalName() */
     public String getLocalName() {
         return "inline-container";
index cae0fac1de51941648858ce0dc9615652322d791..ed9d0abe9d35daf932d012ee30d9761063f1a829 100644 (file)
@@ -60,6 +60,7 @@ public abstract class InlineLevel extends FObjMixed {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         commonAccessibility = pList.getAccessibilityProps();
         commonMarginInline = pList.getMarginInlineProps();
index 43dcd575d5b89c1419a9983fb98dde6d068c299e..fa10b2946e3cb88aa201134c9b6c9d1a10704671 100644 (file)
@@ -49,13 +49,6 @@ public class InstreamForeignObject extends AbstractGraphics {
         super(parent);
     }
 
-    /**
-     * @see org.apache.fop.fo.FONode#startOfNode
-     */
-    protected void startOfNode() throws FOPException {
-        checkId(getId());
-    }
-
     /**
      * Make sure content model satisfied, if so then tell the
      * FOEventHandler that we are at the end of the flow.
index cfc971256a754de72d03f2f143a237e2b186719d..403c6f8a2d4a751e7f443f84d247fb435e6a97e5 100644 (file)
@@ -41,7 +41,6 @@ public class Leader extends InlineLevel {
     private int alignmentBaseline;
     private Length baselineShift;
     private int dominantBaseline;
-    private String id;
     private int leaderAlignment;
     private LengthRangeProperty leaderLength;
     private int leaderPattern;
@@ -75,7 +74,6 @@ public class Leader extends InlineLevel {
         alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
         baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
         dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
-        id = pList.get(PR_ID).getString();
         leaderAlignment = pList.get(PR_LEADER_ALIGNMENT).getEnum();
         leaderLength = pList.get(PR_LEADER_LENGTH).getLengthRange();
         leaderPattern = pList.get(PR_LEADER_PATTERN).getEnum();
@@ -103,21 +101,6 @@ public class Leader extends InlineLevel {
         // textShadow = pList.get(PR_TEXT_SHADOW);
     }
 
-    /**
-     * @see org.apache.fop.fo.FONode#startOfNode
-     */
-    protected void startOfNode() throws FOPException {
-        checkId(id);
-    }
-
-
-    /**
-     * @return the "id" property.
-     */
-    public String getId() {
-        return id;
-    }
-
     /**
      * @return the "rule-style" property.
      */
index 9e0ad1cb9d037ee5b963eb3bfef26bc590c375f1..6c1321024cf0c8fd0a153065dca13d6298bc92b1 100644 (file)
@@ -43,7 +43,6 @@ public class ListBlock extends FObj {
     private CommonMarginBlock commonMarginBlock;
     private int breakAfter;
     private int breakBefore;
-    private String id;
     private KeepProperty keepTogether;
     private KeepProperty keepWithNext;
     private KeepProperty keepWithPrevious;
@@ -74,11 +73,11 @@ public class ListBlock extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         commonMarginBlock = pList.getMarginBlockProps();
         breakAfter = pList.get(PR_BREAK_AFTER).getEnum();
         breakBefore = pList.get(PR_BREAK_BEFORE).getEnum();
-        id = pList.get(PR_ID).getString();
         keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
         keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
         keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep();
@@ -91,7 +90,7 @@ public class ListBlock extends FObj {
      * @see org.apache.fop.fo.FONode#startOfNode
      */
     protected void startOfNode() throws FOPException {
-        checkId(id);
+        super.startOfNode();
         getFOEventHandler().startList(this);
     }
     
@@ -177,11 +176,6 @@ public class ListBlock extends FObj {
         return orphanContentLimit;
     }
 
-    /** @return the "id" property. */
-    public String getId() {
-        return id;
-    }
-
     /** @see org.apache.fop.fo.FONode#getLocalName() */
     public String getLocalName() {
         return "list-block";
index 524ec1b7aa94d8cbcd8b0063d513f58c75bd42ff..35a134571192555e6c55c2896642928002bfa25f 100644 (file)
@@ -42,7 +42,6 @@ public class ListItem extends FObj {
     private CommonMarginBlock commonMarginBlock;
     private int breakAfter;
     private int breakBefore;
-    private String id;
     private KeepProperty keepTogether;
     private KeepProperty keepWithNext;
     private KeepProperty keepWithPrevious;
@@ -68,11 +67,11 @@ public class ListItem extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         commonMarginBlock = pList.getMarginBlockProps();
         breakAfter = pList.get(PR_BREAK_AFTER).getEnum();
         breakBefore = pList.get(PR_BREAK_BEFORE).getEnum();
-        id = pList.get(PR_ID).getString();
         keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
         keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
         keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep();
@@ -82,7 +81,7 @@ public class ListItem extends FObj {
      * @see org.apache.fop.fo.FONode#startOfNode
      */
     protected void startOfNode() throws FOPException {
-        checkId(id);
+        super.startOfNode();
         getFOEventHandler().startListItem(this);
     }
 
@@ -183,13 +182,6 @@ public class ListItem extends FObj {
         return keepTogether;
     }
 
-    /**
-     * @return the "id" property.
-     */
-    public String getId() {
-        return id;
-    }
-
     /**
      * @return the label of the list item
      */
index ee87cfdc65375e3763489d45c7c12f9308216db9..a5528a975be3274f2b5018e36d2a8bf9c4aca693 100644 (file)
@@ -57,19 +57,12 @@ public class MultiCase extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
-        id = pList.get(PR_ID).getString();
+        super.bind(pList);
         startingState = pList.get(PR_STARTING_STATE).getEnum();
         // caseName = pList.get(PR_CASE_NAME);
         // caseTitle = pList.get(PR_CASE_TITLE);
     }
 
-    /**
-     * @see org.apache.fop.fo.FONode#startOfNode
-     */
-    protected void startOfNode() throws FOPException {
-        checkId(id);
-    }
-
     /**
      * Return the "starting-state" property.
      */
index 0443c786f572247947d898f5d4e6215b9ec48323..09b0747c0648477c65541797993f86fdb060c0bf 100644 (file)
@@ -25,7 +25,6 @@ import org.xml.sax.Locator;
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.fo.FONode;
 import org.apache.fop.fo.FObj;
-import org.apache.fop.fo.PropertyList;
 import org.apache.fop.fo.ValidationException;
 import org.apache.fop.fo.properties.CommonAccessibility;
 
@@ -34,7 +33,6 @@ import org.apache.fop.fo.properties.CommonAccessibility;
  */
 public class MultiProperties extends FObj {
     // The value of properties relevant for fo:multi-properties.
-    private String id;
     // Unused but valid items, commented out for performance:
     //     private CommonAccessibility commonAccessibility;
     // End of property values
@@ -57,20 +55,6 @@ public class MultiProperties extends FObj {
         }
     }
 
-    /**
-     * @see org.apache.fop.fo.FObj#bind(PropertyList)
-     */
-    public void bind(PropertyList pList) throws FOPException {
-        id = pList.get(PR_ID).getString();
-    }
-
-    /**
-     * @see org.apache.fop.fo.FONode#startOfNode
-     */
-    protected void startOfNode() throws FOPException {
-        checkId(id);
-    }
-
     /**
      * Make sure content model satisfied, if so then tell the
      * FOEventHandler that we are at the end of the flow.
@@ -104,13 +88,6 @@ public class MultiProperties extends FObj {
                 invalidChildError(loc, nsURI, localName);
             }
     }
-
-    /**
-     * Return the "id" property.
-     */
-    public String getId() {
-        return id;
-    }
     
     /** @see org.apache.fop.fo.FONode#getLocalName() */
     public String getLocalName() {
index d15c6b07f516c7d5e8723d81b4e671ab62346013..29ab868101967e3a1287be2183e42edb7415bbb2 100644 (file)
@@ -33,7 +33,6 @@ import org.apache.fop.fo.ValidationException;
  */
 public class MultiPropertySet extends FObj {
     // The value of properties relevant for fo:multi-property-set.
-    private String id;
     // private ToBeImplementedProperty activeState;
     // End of property values
 
@@ -55,17 +54,10 @@ public class MultiPropertySet extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
-        id = pList.get(PR_ID).getString();
+        super.bind(pList);
         // activeState = pList.get(PR_ACTIVE_STATE);
     }
 
-    /**
-     * @see org.apache.fop.fo.FONode#startOfNode
-     */
-    protected void startOfNode() throws FOPException {
-        checkId(id);
-    }
-
     /**
      * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
      * XSL Content Model: empty
@@ -75,11 +67,6 @@ public class MultiPropertySet extends FObj {
             invalidChildError(loc, nsURI, localName);
     }
 
-    /** @return the "id" property. */
-    public String getId() {
-        return id;
-    }
-
     /** @see org.apache.fop.fo.FONode#getLocalName() */
     public String getLocalName() {
         return "multi-property-set";
index 22ba27e9a2e89d2fd810d9a68d540035703547a1..2293459c7c921173e60223970a35f767c3313d91 100644 (file)
@@ -36,7 +36,6 @@ import org.apache.fop.fo.properties.CommonAccessibility;
 public class MultiSwitch extends FObj {
     // The value of properties relevant for fo:multi-switch.
     // private ToBeImplementedProperty autoRestore;
-    private String id;
     // Unused but valid items, commented out for performance:
     //     private CommonAccessibility commonAccessibility;
     // End of property values
@@ -59,16 +58,10 @@ public class MultiSwitch extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
         // autoRestore = pList.get(PR_AUTO_RESTORE);
-        id = pList.get(PR_ID).getString();
     }
 
-    /**
-     * @see org.apache.fop.fo.FONode#startOfNode
-     */
-    protected void startOfNode() throws FOPException {
-        checkId(id);
-    }
 
     /**
      * Make sure content model satisfied.
@@ -91,11 +84,6 @@ public class MultiSwitch extends FObj {
         }
     }
 
-    /** @return the "id" property. */
-    public String getId() {
-        return id;
-    }
-
     /** @see org.apache.fop.fo.FONode#getLocalName() */
     public String getLocalName() {
         return "multi-switch";
index 49b145871d291be7f7f7c0dd5fb01b12452f948d..989df2f88b384c850899f5e43aa1b1a4d8f9c5b3 100644 (file)
@@ -51,7 +51,6 @@ public class PageNumber extends FObj {
     private int alignmentBaseline;
     private Length baselineShift;
     private int dominantBaseline;
-    private String id;
     // private ToBeImplementedProperty letterSpacing;
     private SpaceProperty lineHeight;
     /** Holds the text decoration values. May be null */
@@ -87,13 +86,13 @@ public class PageNumber extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         commonFont = pList.getFontProps();
         alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength();
         alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
         baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
         dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
-        id = pList.get(PR_ID).getString();
         // letterSpacing = pList.get(PR_LETTER_SPACING);
         lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
         textDecoration = pList.getTextDecorationProps();
@@ -107,7 +106,7 @@ public class PageNumber extends FObj {
      * @see org.apache.fop.fo.FONode#startOfNode
      */
     protected void startOfNode() throws FOPException {
-        checkId(id);
+        super.startOfNode();
         getFOEventHandler().startPageNumber(this);
     }
 
@@ -142,11 +141,6 @@ public class PageNumber extends FObj {
         return commonBorderPaddingBackground;
     }
 
-    /** @return the "id" property. */
-    public String getId() {
-        return id;
-    }
-
     /** @return the "text-decoration" property. */
     public CommonTextDecoration getTextDecoration() {
         return textDecoration; 
index 7a0d2ae9dfb700809af5517228757ec77f4c595a..d72dd604ec1b2cbcb1f0318018c89dd3d8e4a156 100644 (file)
@@ -54,7 +54,6 @@ public class PageNumberCitation extends FObj {
     private int alignmentBaseline;
     private Length baselineShift;
     private int dominantBaseline;
-    private String id;
     // private ToBeImplementedProperty letterSpacing;
     private SpaceProperty lineHeight;
     private String refId;
@@ -91,13 +90,13 @@ public class PageNumberCitation extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         commonFont = pList.getFontProps();
         alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength();
         alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
         baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
         dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
-        id = pList.get(PR_ID).getString();
         // letterSpacing = pList.get(PR_LETTER_SPACING);
         lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
         refId = pList.get(PR_REF_ID).getString();
@@ -112,7 +111,7 @@ public class PageNumberCitation extends FObj {
      * @see org.apache.fop.fo.FONode#startOfNode
      */
     protected void startOfNode() throws FOPException {
-        checkId(id);
+        super.startOfNode();
         if (refId.equals("")) {
             missingPropertyError("ref-id");
         }
@@ -182,11 +181,6 @@ public class PageNumberCitation extends FObj {
         return lineHeight;
     }
     
-    /** @return the "id" property. */
-    public String getId() {
-        return id;
-    }
-
     /** @return the "ref-id" property. */
     public String getRefId() {
         return refId;
index 2fa46a75e20251bbd890d916c0e2495ebc964a69..68fe126cfd753bb9b9cdc10e25e23acb3b9f0c21 100644 (file)
@@ -54,7 +54,6 @@ public class Table extends TableFObj {
     private LengthPairProperty borderSeparation;
     private int breakAfter;
     private int breakBefore;
-    private String id;
     private LengthRangeProperty inlineProgressionDimension;
     private KeepProperty keepTogether;
     private KeepProperty keepWithNext;
@@ -110,6 +109,7 @@ public class Table extends TableFObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         commonMarginBlock = pList.getMarginBlockProps();
         blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange();
@@ -117,7 +117,6 @@ public class Table extends TableFObj {
         borderSeparation = pList.get(PR_BORDER_SEPARATION).getLengthPair();
         breakAfter = pList.get(PR_BREAK_AFTER).getEnum();
         breakBefore = pList.get(PR_BREAK_BEFORE).getEnum();
-        id = pList.get(PR_ID).getString();
         inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange();
         keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
         keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
@@ -125,7 +124,6 @@ public class Table extends TableFObj {
         tableLayout = pList.get(PR_TABLE_LAYOUT).getEnum();
         tableOmitFooterAtBreak = pList.get(PR_TABLE_OMIT_FOOTER_AT_BREAK).getEnum();
         tableOmitHeaderAtBreak = pList.get(PR_TABLE_OMIT_HEADER_AT_BREAK).getEnum();
-        super.bind(pList);
 
         //Bind extension properties
         widowContentLimit = pList.get(PR_X_WIDOW_CONTENT_LIMIT).getLength();
@@ -161,7 +159,7 @@ public class Table extends TableFObj {
      * @see org.apache.fop.fo.FONode#startOfNode
      */
     protected void startOfNode() throws FOPException {
-        checkId(id);
+        super.startOfNode();
         getFOEventHandler().startTable(this);
     }
    
@@ -466,11 +464,6 @@ public class Table extends TableFObj {
         return orphanContentLimit;
     }
 
-    /** @return the "id" property. */
-    public String getId() {
-        return id;
-    }
-
     /** @see org.apache.fop.fo.FONode#getLocalName() */
     public String getLocalName() {
         return "table";
index 748ee0cb30d94671b59110012af26bbc9b1f7104..d71f6530a1e74b54c50c35263ed5a5d9511d9d27 100644 (file)
@@ -40,7 +40,6 @@ import org.apache.fop.fo.properties.KeepProperty;
  */
 public class TableAndCaption extends FObj {
     // The value of properties relevant for fo:table-and-caption.
-    private String id;
     // Unused but valid items, commented out for performance:
     //     private CommonAccessibility commonAccessibility;
     //     private CommonAural commonAural;
@@ -75,20 +74,6 @@ public class TableAndCaption extends FObj {
         }
     }
 
-    /**
-     * @see org.apache.fop.fo.FObj#bind(PropertyList)
-     */
-    public void bind(PropertyList pList) throws FOPException {
-        id = pList.get(PR_ID).getString();
-    }
-
-    /**
-     * @see org.apache.fop.fo.FONode#startOfNode
-     */
-    protected void startOfNode() throws FOPException {
-        checkId(id);
-    }
-
     /**
      * Make sure content model satisfied, if so then tell the
      * FOEventHandler that we are at the end of the flow.
@@ -132,11 +117,6 @@ public class TableAndCaption extends FObj {
         }
     }
 
-    /** @return the "id" property. */
-    public String getId() {
-        return id;
-    }
-
     /** @see org.apache.fop.fo.FONode#getLocalName() */
     public String getLocalName() {
         return "table-and-caption";
index da516060fb430329ad2881e5b0f9822d9e1cf0b8..e0227b9a1dc0ab0e5e3637829123d870d3714afe 100644 (file)
@@ -44,7 +44,6 @@ public class TableCaption extends FObj {
     // The value of properties relevant for fo:table-caption.
     private CommonAccessibility commonAccessibility;
     private CommonBorderPaddingBackground commonBorderPaddingBackground;
-    private String id;
     // Unused but valid items, commented out for performance:
     //     private CommonAural commonAural;
     //     private CommonRelativePosition commonRelativePosition;
@@ -77,16 +76,9 @@ public class TableCaption extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
         commonAccessibility = pList.getAccessibilityProps();
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
-        id = pList.get(PR_ID).getString();
-    }
-
-    /**
-     * @see org.apache.fop.fo.FONode#startOfNode
-     */
-    protected void startOfNode() throws FOPException {
-        checkId(id);
     }
 
     /**
@@ -124,11 +116,6 @@ public class TableCaption extends FObj {
         }
     }
 
-    /** @return the "id" property. */
-    public String getId() {
-        return id;
-    }
-
     /** @see org.apache.fop.fo.FONode#getLocalName() */
     public String getLocalName() {
         return "table-caption";
index 066d6493a15c204844139ffcd01e26d635dc9a4e..8f1b48d54640ae04777f82ed102f9e0dba5ecdfe 100644 (file)
@@ -46,7 +46,6 @@ public class TableCell extends TableFObj {
     private int displayAlign;
     private int emptyCells;
     private int endsRow;
-    private String id;
     private int numberColumnsSpanned;
     private int numberRowsSpanned;
     private int startsRow;
@@ -77,26 +76,24 @@ public class TableCell extends TableFObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange();
         displayAlign = pList.get(PR_DISPLAY_ALIGN).getEnum();
         emptyCells = pList.get(PR_EMPTY_CELLS).getEnum();
         endsRow = pList.get(PR_ENDS_ROW).getEnum();
-        id = pList.get(PR_ID).getString();
         columnNumber = pList.get(PR_COLUMN_NUMBER).getNumeric().getValue();
         numberColumnsSpanned = pList.get(PR_NUMBER_COLUMNS_SPANNED).getNumeric().getValue();
         numberRowsSpanned = pList.get(PR_NUMBER_ROWS_SPANNED).getNumeric().getValue();
         startsRow = pList.get(PR_STARTS_ROW).getEnum();
-        width = pList.get(PR_WIDTH).getLength();
-        
-        super.bind(pList);
+        width = pList.get(PR_WIDTH).getLength();        
     }
 
     /**
      * @see org.apache.fop.fo.FONode#startOfNode
      */
     protected void startOfNode() throws FOPException {
-        checkId(id);
+        super.startOfNode();
         getFOEventHandler().startCell(this);
     }
 
@@ -163,13 +160,6 @@ public class TableCell extends TableFObj {
         return (this.emptyCells == EN_SHOW);
     }
     
-    /**
-     * @return the "id" property.
-     */
-    public String getId() {
-        return id;
-    }
-
     /**
      * @return the "number-columns-spanned" property.
      */
index 359530cdc946d82ba5d63f1c48b6a1dafce417bc..980eaeb7cef95ac068698f5996085dab96420406 100644 (file)
@@ -83,6 +83,7 @@ public abstract class TableFObj extends FObj {
      * @see FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
         borderAfterPrecedence = pList.get(PR_BORDER_AFTER_PRECEDENCE).getNumeric();
         borderBeforePrecedence = pList.get(PR_BORDER_BEFORE_PRECEDENCE).getNumeric();
         borderEndPrecedence = pList.get(PR_BORDER_END_PRECEDENCE).getNumeric();
index 81d71e08b58fa15d2e3e8f84cf63fd9a88db3dcb..1b5c05b05552c5489d27a868e07218bd04d1030b 100644 (file)
@@ -47,7 +47,6 @@ public class TableRow extends TableFObj {
     private int breakAfter;
     private int breakBefore;
     private Length height;
-    private String id;
     private KeepProperty keepTogether;
     private KeepProperty keepWithNext;
     private KeepProperty keepWithPrevious;
@@ -80,7 +79,6 @@ public class TableRow extends TableFObj {
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         breakAfter = pList.get(PR_BREAK_AFTER).getEnum();
         breakBefore = pList.get(PR_BREAK_BEFORE).getEnum();
-        id = pList.get(PR_ID).getString();
         height = pList.get(PR_HEIGHT).getLength();
         keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
         keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
@@ -162,7 +160,7 @@ public class TableRow extends TableFObj {
      * @see org.apache.fop.fo.FONode#startOfNode
      */
     protected void startOfNode() throws FOPException {
-        checkId(id);
+        super.startOfNode();
         getFOEventHandler().startRow(this);
     }
 
@@ -192,13 +190,6 @@ public class TableRow extends TableFObj {
         }
     }    
     
-    /**
-     * @return the "id" property.
-     */
-    public String getId() {
-        return id;
-    }
-
     /** @return the "break-after" property. */
     public int getBreakAfter() {
         return breakAfter;
index 61ec2c8574300c9e4246833b5ea668d0e23a3865..b75ff42cbcb0035cd0d2e98549de5c8a65e8ea13 100644 (file)
@@ -34,7 +34,6 @@ import org.xml.sax.Locator;
  */
 public class Wrapper extends FObjMixed {
     // The value of properties relevant for fo:wrapper.
-    private String id;
     // End of property values
     
     // used for FO validation
@@ -47,20 +46,6 @@ public class Wrapper extends FObjMixed {
         super(parent);
     }
 
-    /**
-     * @see org.apache.fop.fo.FObj#bind(PropertyList)
-     */
-    public void bind(PropertyList pList) throws FOPException {
-        id = pList.get(PR_ID).getString();
-    }
-
-    /**
-     * @see org.apache.fop.fo.FONode#startOfNode
-     */
-    protected void startOfNode() throws FOPException {
-        checkId(id);
-    }
-
     /**
      * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
      * XSL Content Model: marker* (#PCDATA|%inline;|%block;)*
@@ -82,11 +67,6 @@ public class Wrapper extends FObjMixed {
         }
     }
 
-    /** @return the "id" property. */
-    public String getId() {
-        return id;
-    }
-
     /** @see org.apache.fop.fo.FONode#getLocalName() */
     public String getLocalName() {
         return "wrapper";
index b61d3b8b73e558989dd0b6d296942a9bebd91d37..135382800bf73ba8c5ad0389c160b5067cf98a2f 100644 (file)
@@ -43,7 +43,6 @@ public class PageSequence extends FObj {
     private int letterValue;
     private char groupingSeparator;
     private int groupingSize;
-    private String id;
     private Numeric initialPageNumber;
     private int forcePageCount;
     private String masterReference;
@@ -96,13 +95,13 @@ public class PageSequence extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
         country = pList.get(PR_COUNTRY).getString();
         format = pList.get(PR_FORMAT).getString();
         language = pList.get(PR_LANGUAGE).getString();
         letterValue = pList.get(PR_LETTER_VALUE).getEnum();
         groupingSeparator = pList.get(PR_GROUPING_SEPARATOR).getCharacter();
         groupingSize = pList.get(PR_GROUPING_SIZE).getNumber().intValue();
-        id = pList.get(PR_ID).getString();
         initialPageNumber = pList.get(PR_INITIAL_PAGE_NUMBER).getNumeric();
         forcePageCount = pList.get(PR_FORCE_PAGE_COUNT).getEnum();
         masterReference = pList.get(PR_MASTER_REFERENCE).getString();
@@ -116,6 +115,7 @@ public class PageSequence extends FObj {
      * @see org.apache.fop.fo.FONode#startOfNode()
      */
     protected void startOfNode() throws FOPException {
+        super.startOfNode();
         this.root = (Root) parent;
         flowMap = new java.util.HashMap();
 
@@ -133,7 +133,6 @@ public class PageSequence extends FObj {
         this.pageNumberGenerator = new PageNumberGenerator(
                 format, groupingSeparator, groupingSize, letterValue);
 
-        checkId(id);
         getFOEventHandler().startPageSequence(this);
     }
 
@@ -394,11 +393,6 @@ public class PageSequence extends FObj {
         return (StaticContent) flowMap.get(name);
     }
 
-    /** @return the "id" property. */
-    public String getId() {
-        return id;
-    }
-
     /**
      * Accessor method for titleFO
      * @return titleFO for this object
index 3f7cb66d1ec55d3f13225f6abf1b97e6633086c2..b57befaba011f40b40ed8e22861a59711e362719 100644 (file)
@@ -34,7 +34,6 @@ import org.apache.fop.fo.ValidationException;
  */
 public class PageSequenceWrapper extends FObj {
     // The value of properties relevant for this FO
-    private String id;
     private String indexClass;
     private String indexKey;
     // End of property values
@@ -50,18 +49,11 @@ public class PageSequenceWrapper extends FObj {
      * @see org.apache.fop.fo.FObj#bind(PropertyList)
      */
     public void bind(PropertyList pList) throws FOPException {
-        id = pList.get(PR_ID).getString();
+        super.bind(pList);
         indexClass = pList.get(PR_INDEX_CLASS).getString();
         indexKey = pList.get(PR_INDEX_KEY).getString();
     }
 
-    /**
-     * @see org.apache.fop.fo.FONode#startOfNode
-     */
-    protected void startOfNode() throws FOPException {
-        checkId(id);
-    }
-
     /**
      * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
         XSL/FOP: (bookmark+)
@@ -74,11 +66,6 @@ public class PageSequenceWrapper extends FObj {
         }
     }
 
-    /** @return the "id" property. */
-    public String getId() {
-        return id;
-    }
-
     /** @return the "index-class" property. */
     public String getIndexClass() {
         return indexClass;
index 24ee2e4dad6f1b5da695b01a73f2e195b8eb0a5c..f4e9cb633bddc11ea7a6e3a7492d05a23a726ca7 100644 (file)
@@ -192,7 +192,7 @@ public abstract class AbstractBreaker {
      * algorithm.
      * @return the applicable PageProvider, or null if not applicable
      */
-    protected PageSequenceLayoutManager.PageProvider getPageProvider() {
+    protected PageProvider getPageProvider() {
         return null;
     }
     
@@ -214,7 +214,7 @@ public abstract class AbstractBreaker {
 
     /** @return true if there's no content that could be handled. */
     public boolean isEmpty() {
-        return (blockLists.size() == 0);
+        return (this.blockLists.size() == 0);
     }
     
     protected void startPart(BlockSequence list, int breakClass) {
@@ -289,7 +289,7 @@ public abstract class AbstractBreaker {
         childLC.setBPAlignment(alignment);
 
         BlockSequence blockList;
-        blockLists = new java.util.ArrayList();
+        this.blockLists = new java.util.ArrayList();
 
         log.debug("PLM> flow BPD =" + flowBPD);
         
@@ -298,7 +298,7 @@ public abstract class AbstractBreaker {
         while (hasMoreContent()) {
             blockLists.clear();
 
-            nextSequenceStartsOn = getNextBlockList(childLC, nextSequenceStartsOn, blockLists);
+            nextSequenceStartsOn = getNextBlockList(childLC, nextSequenceStartsOn);
 
             //*** Phase 2: Alignment and breaking ***
             log.debug("PLM> blockLists.size() = " + blockLists.size());
@@ -539,19 +539,17 @@ public abstract class AbstractBreaker {
      * Gets the next block list (sequence) and adds it to a list of block lists if it's not empty.
      * @param childLC LayoutContext to use
      * @param nextSequenceStartsOn indicates on what page the next sequence should start
-     * @param blockLists list of block lists (sequences)
      * @return the page on which the next content should appear after a hard break
      */
     protected int getNextBlockList(LayoutContext childLC, 
-            int nextSequenceStartsOn, 
-            List blockLists) {
+            int nextSequenceStartsOn) {
         updateLayoutContext(childLC);
         //Make sure the span change signal is reset
         childLC.signalSpanChange(Constants.NOT_SET);
         
-        LinkedList returnedList;
         BlockSequence blockList;
-        if ((returnedList = getNextKnuthElements(childLC, alignment)) != null) {
+        LinkedList returnedList = getNextKnuthElements(childLC, alignment);
+        if (returnedList != null) {
             if (returnedList.size() == 0) {
                 nextSequenceStartsOn = handleSpanChange(childLC, nextSequenceStartsOn);
                 return nextSequenceStartsOn;
@@ -594,7 +592,7 @@ public abstract class AbstractBreaker {
             BlockSequence seq = null;
             seq = blockList.endBlockSequence(breakPosition);
             if (seq != null) {
-                blockLists.add(seq);
+                this.blockLists.add(seq);
             }
         }
         return nextSequenceStartsOn;
index 57e42aaf61e1520249f5e280fc845aeee5243740..9f3207773e3033e764bf74c6b82a0b2fefe7effc 100644 (file)
@@ -21,7 +21,6 @@ package org.apache.fop.layoutmgr;
 \r
 import org.apache.commons.logging.Log;\r
 import org.apache.commons.logging.LogFactory;\r
-import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener;\r
 import org.apache.fop.traits.MinOptMax;\r
 \r
 /**\r
@@ -37,7 +36,7 @@ public class BalancingColumnBreakingAlgorithm extends PageBreakingAlgorithm {
     private int idealPartLen;\r
     \r
     public BalancingColumnBreakingAlgorithm(LayoutManager topLevelLM,\r
-            PageSequenceLayoutManager.PageProvider pageProvider,\r
+            PageProvider pageProvider,
             PageBreakingLayoutListener layoutListener,\r
             int alignment, int alignmentLast,\r
             MinOptMax footnoteSeparatorLength,\r
diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java
new file mode 100644 (file)
index 0000000..ff3dfef
--- /dev/null
@@ -0,0 +1,542 @@
+/*
+ * 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;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.apache.fop.area.Block;
+import org.apache.fop.area.Footnote;
+import org.apache.fop.area.PageViewport;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.Region;
+import org.apache.fop.fo.pagination.RegionBody;
+import org.apache.fop.fo.pagination.StaticContent;
+import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener;
+import org.apache.fop.traits.MinOptMax;
+
+/**
+ * Handles the breaking of pages in an fo:flow
+ */
+public class PageBreaker extends AbstractBreaker {
+    
+    private PageSequenceLayoutManager pslm;
+    private boolean firstPart = true;
+    private boolean pageBreakHandled;
+    private boolean needColumnBalancing;
+    private PageProvider pageProvider;
+    private Block separatorArea;
+    
+    /**
+     * The FlowLayoutManager object, which processes
+     * the single fo:flow of the fo:page-sequence
+     */
+    private FlowLayoutManager childFLM = null;
+
+    private StaticContentLayoutManager footnoteSeparatorLM = null;
+
+    public PageBreaker(PageSequenceLayoutManager pslm) {
+        this.pslm = pslm;
+        this.pageProvider = pslm.getPageProvider();
+        this.childFLM = pslm.getLayoutManagerMaker().makeFlowLayoutManager(
+                pslm, pslm.getPageSequence().getMainFlow());
+    }
+    
+    /** @see org.apache.fop.layoutmgr.AbstractBreaker */
+    protected void updateLayoutContext(LayoutContext context) {
+        int flowIPD = pslm.getCurrentPV().getCurrentSpan().getColumnWidth();
+        context.setRefIPD(flowIPD);
+    }
+    
+    /** @see org.apache.fop.layoutmgr.AbstractBreaker#getTopLevelLM() */
+    protected LayoutManager getTopLevelLM() {
+        return pslm;
+    }
+    
+    /** @see org.apache.fop.layoutmgr.AbstractBreaker#getPageProvider() */
+    protected PageProvider getPageProvider() {
+        return pslm.getPageProvider();
+    }
+    
+    /**
+     * @see org.apache.fop.layoutmgr.AbstractBreaker#getLayoutListener()
+     */
+    protected PageBreakingLayoutListener getLayoutListener() {
+        return new PageBreakingLayoutListener() {
+
+            public void notifyOverflow(int part, FObj obj) {
+                Page p = pageProvider.getPage(
+                            false, part, PageProvider.RELTO_CURRENT_ELEMENT_LIST);
+                RegionBody body = (RegionBody)p.getSimplePageMaster().getRegion(
+                        Region.FO_REGION_BODY);
+                String err = FONode.decorateWithContextInfo(
+                        "Content of the region-body on page " 
+                        + p.getPageViewport().getPageNumberString() 
+                        + " overflows the available area in block-progression dimension.", 
+                        obj);
+                if (body.getOverflow() == Constants.EN_ERROR_IF_OVERFLOW) {
+                    throw new RuntimeException(err);
+                } else {
+                    log.warn(err);
+                }
+            }
+            
+        };
+    }
+
+    /** @see org.apache.fop.layoutmgr.AbstractBreaker */
+    protected int handleSpanChange(LayoutContext childLC, int nextSequenceStartsOn) {
+        needColumnBalancing = false;
+        if (childLC.getNextSpan() != Constants.NOT_SET) {
+            //Next block list will have a different span.
+            nextSequenceStartsOn = childLC.getNextSpan();
+            needColumnBalancing = (childLC.getNextSpan() == Constants.EN_ALL);
+        }
+        if (needColumnBalancing) {
+            AbstractBreaker.log.debug(
+                    "Column balancing necessary for the next element list!!!");
+        }
+        return nextSequenceStartsOn;
+    }
+
+    /** @see org.apache.fop.layoutmgr.AbstractBreaker */
+    protected int getNextBlockList(LayoutContext childLC, 
+            int nextSequenceStartsOn) {
+        if (!firstPart) {
+            // if this is the first page that will be created by
+            // the current BlockSequence, it could have a break
+            // condition that must be satisfied;
+            // otherwise, we may simply need a new page
+            handleBreakTrait(nextSequenceStartsOn);
+        }
+        firstPart = false;
+        pageBreakHandled = true;
+        pageProvider.setStartOfNextElementList(pslm.getCurrentPageNum(), 
+                pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
+        return super.getNextBlockList(childLC, nextSequenceStartsOn);
+    }
+    
+    /** @see org.apache.fop.layoutmgr.AbstractBreaker */
+    protected LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
+        LinkedList contentList = null;
+        
+        while (!childFLM.isFinished() && contentList == null) {
+            contentList = childFLM.getNextKnuthElements(context, alignment);
+        }
+
+        // scan contentList, searching for footnotes
+        boolean bFootnotesPresent = false;
+        if (contentList != null) {
+            ListIterator contentListIterator = contentList.listIterator();
+            while (contentListIterator.hasNext()) {
+                ListElement element = (ListElement) contentListIterator.next();
+                if (element instanceof KnuthBlockBox
+                    && ((KnuthBlockBox) element).hasAnchors()) {
+                    // element represents a line with footnote citations
+                    bFootnotesPresent = true;
+                    LayoutContext footnoteContext = new LayoutContext(context);
+                    footnoteContext.setStackLimit(context.getStackLimit());
+                    footnoteContext.setRefIPD(pslm.getCurrentPV()
+                            .getRegionReference(Constants.FO_REGION_BODY).getIPD());
+                    LinkedList footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs();
+                    ListIterator footnoteBodyIterator = footnoteBodyLMs.listIterator();
+                    // store the lists of elements representing the footnote bodies
+                    // in the box representing the line containing their references
+                    while (footnoteBodyIterator.hasNext()) {
+                        FootnoteBodyLayoutManager fblm 
+                            = (FootnoteBodyLayoutManager) footnoteBodyIterator.next();
+                        fblm.setParent(childFLM);
+                        fblm.initialize();
+                        ((KnuthBlockBox) element).addElementList(
+                                fblm.getNextKnuthElements(footnoteContext, alignment));
+                    }
+                }
+            }
+        }
+
+        if (bFootnotesPresent) {
+            // handle the footnote separator
+            StaticContent footnoteSeparator;
+            footnoteSeparator = pslm.getPageSequence().getStaticContent("xsl-footnote-separator");
+            if (footnoteSeparator != null) {
+                // the footnote separator can contain page-dependent content such as
+                // page numbers or retrieve markers, so its areas cannot simply be 
+                // obtained now and repeated in each page;
+                // we need to know in advance the separator bpd: the actual separator
+                // could be different from page to page, but its bpd would likely be
+                // always the same
+
+                // create a Block area that will contain the separator areas
+                separatorArea = new Block();
+                separatorArea.setIPD(pslm.getCurrentPV()
+                            .getRegionReference(Constants.FO_REGION_BODY).getIPD());
+                // create a StaticContentLM for the footnote separator
+                footnoteSeparatorLM = (StaticContentLayoutManager)
+                    pslm.getLayoutManagerMaker().makeStaticContentLayoutManager(
+                    pslm, footnoteSeparator, separatorArea);
+                footnoteSeparatorLM.doLayout();
+
+                footnoteSeparatorLength = new MinOptMax(separatorArea.getBPD());
+            }
+        }
+        return contentList;
+    }
+    
+    /**
+     * @return current display alignment
+     */
+    protected int getCurrentDisplayAlign() {
+        return pslm.getCurrentPage().getSimplePageMaster().getRegion(
+                Constants.FO_REGION_BODY).getDisplayAlign();
+    }
+    
+    /**
+     * @return whether or not this flow has more page break opportunities
+     */
+    protected boolean hasMoreContent() {
+        return !childFLM.isFinished();
+    }
+    
+    /**
+     * Adds an area to the flow layout manager
+     * @param posIter the position iterator
+     * @param context the layout context
+     */
+    protected void addAreas(PositionIterator posIter, LayoutContext context) {
+        if (footnoteSeparatorLM != null) {
+            StaticContent footnoteSeparator = pslm.getPageSequence().getStaticContent(
+                    "xsl-footnote-separator");
+            // create a Block area that will contain the separator areas
+            separatorArea = new Block();
+            separatorArea.setIPD(
+                    pslm.getCurrentPV().getRegionReference(Constants.FO_REGION_BODY).getIPD());
+            // create a StaticContentLM for the footnote separator
+            footnoteSeparatorLM = (StaticContentLayoutManager)
+                pslm.getLayoutManagerMaker().makeStaticContentLayoutManager(
+                pslm, footnoteSeparator, separatorArea);
+            footnoteSeparatorLM.doLayout();
+        }
+
+        childFLM.addAreas(posIter, context);    
+    }
+    
+    /**
+     * Performs phase 3 operation
+     * 
+     * @param alg page breaking algorithm
+     * @param partCount part count
+     * @param originalList the block sequence original list
+     * @param effectiveList the block sequence effective list
+     */
+    protected void doPhase3(PageBreakingAlgorithm alg, int partCount, 
+            BlockSequence originalList, BlockSequence effectiveList) {
+        if (needColumnBalancing) {
+            doPhase3WithColumnBalancing(alg, partCount, originalList, effectiveList);
+        } else {
+            if (!hasMoreContent() && pslm.getPageSequence().hasPagePositionLast()) {
+                //last part is reached and we have a "last page" condition
+                doPhase3WithLastPage(alg, partCount, originalList, effectiveList);
+            } else {
+                //Directly add areas after finding the breaks
+                addAreas(alg, partCount, originalList, effectiveList);
+            }
+        }
+    }
+
+    private void doPhase3WithLastPage(PageBreakingAlgorithm alg, int partCount, 
+            BlockSequence originalList, BlockSequence effectiveList) {
+        int newStartPos;
+        int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
+        if (restartPoint > 0) {
+            //Add definitive areas before last page
+            addAreas(alg, restartPoint, originalList, effectiveList);
+            //Get page break from which we restart
+            PageBreakPosition pbp = (PageBreakPosition)
+                    alg.getPageBreaks().get(restartPoint - 1);
+            newStartPos = pbp.getLeafPos();
+            //Handle page break right here to avoid any side-effects
+            if (newStartPos > 0) {
+                handleBreakTrait(Constants.EN_PAGE);
+            }
+        } else {
+            newStartPos = 0;
+        }
+        AbstractBreaker.log.debug("Last page handling now!!!");
+        AbstractBreaker.log.debug("===================================================");
+        AbstractBreaker.log.debug("Restarting at " + restartPoint 
+                + ", new start position: " + newStartPos);
+
+        pageBreakHandled = true;
+        //Update so the available BPD is reported correctly
+        int currentPageNum = pslm.getCurrentPageNum();
+        pageProvider.setStartOfNextElementList(currentPageNum, 
+                pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
+        pageProvider.setLastPageIndex(currentPageNum);
+
+        //Restart last page
+        PageBreakingAlgorithm algRestart = new PageBreakingAlgorithm(
+                getTopLevelLM(),
+                getPageProvider(), getLayoutListener(),
+                alg.getAlignment(), alg.getAlignmentLast(), 
+                footnoteSeparatorLength,
+                isPartOverflowRecoveryActivated(), false, false);
+        //alg.setConstantLineWidth(flowBPD);
+        int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
+                    newStartPos,
+                    1, true, BreakingAlgorithm.ALL_BREAKS);
+        AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
+                + " pageBreaks.size()= " + algRestart.getPageBreaks().size());
+        boolean replaceLastPage 
+                = iOptPageCount <= pslm.getCurrentPV().getBodyRegion().getColumnCount(); 
+        if (replaceLastPage) {
+            //Replace last page
+            pslm.setCurrentPage(pageProvider.getPage(false, currentPageNum));
+            //Make sure we only add the areas we haven't added already
+            effectiveList.ignoreAtStart = newStartPos;
+            addAreas(algRestart, iOptPageCount, originalList, effectiveList);
+        } else {
+            effectiveList.ignoreAtStart = newStartPos;
+            addAreas(alg, restartPoint, partCount - restartPoint, originalList, effectiveList);
+            //Add blank last page
+            pageProvider.setLastPageIndex(currentPageNum + 1);
+            pslm.setCurrentPage(pslm.makeNewPage(true, true));
+        }
+        AbstractBreaker.log.debug("===================================================");
+    }
+
+    private void doPhase3WithColumnBalancing(PageBreakingAlgorithm alg, int partCount, 
+            BlockSequence originalList, BlockSequence effectiveList) {
+        AbstractBreaker.log.debug("Column balancing now!!!");
+        AbstractBreaker.log.debug("===================================================");
+        int newStartPos;
+        int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
+        if (restartPoint > 0) {
+            //Add definitive areas
+            addAreas(alg, restartPoint, originalList, effectiveList);
+            //Get page break from which we restart
+            PageBreakPosition pbp = (PageBreakPosition)
+                    alg.getPageBreaks().get(restartPoint - 1);
+            newStartPos = pbp.getLeafPos();
+            //Handle page break right here to avoid any side-effects
+            if (newStartPos > 0) {
+                handleBreakTrait(Constants.EN_PAGE);
+            }
+        } else {
+            newStartPos = 0;
+        }
+        AbstractBreaker.log.debug("Restarting at " + restartPoint 
+                + ", new start position: " + newStartPos);
+
+        pageBreakHandled = true;
+        //Update so the available BPD is reported correctly
+        pageProvider.setStartOfNextElementList(pslm.getCurrentPageNum(), 
+                pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
+
+        //Restart last page
+        PageBreakingAlgorithm algRestart = new BalancingColumnBreakingAlgorithm(
+                getTopLevelLM(),
+                getPageProvider(), getLayoutListener(),
+                alignment, Constants.EN_START, footnoteSeparatorLength,
+                isPartOverflowRecoveryActivated(),
+                pslm.getCurrentPV().getBodyRegion().getColumnCount());
+        //alg.setConstantLineWidth(flowBPD);
+        int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
+                    newStartPos,
+                    1, true, BreakingAlgorithm.ALL_BREAKS);
+        AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
+                + " pageBreaks.size()= " + algRestart.getPageBreaks().size());
+        if (iOptPageCount > pslm.getCurrentPV().getBodyRegion().getColumnCount()) {
+            AbstractBreaker.log.warn(
+                    "Breaking algorithm produced more columns than are available.");
+            /* reenable when everything works
+            throw new IllegalStateException(
+                    "Breaking algorithm must not produce more columns than available.");
+            */
+        }
+        //Make sure we only add the areas we haven't added already
+        effectiveList.ignoreAtStart = newStartPos;
+        addAreas(algRestart, iOptPageCount, originalList, effectiveList);
+        AbstractBreaker.log.debug("===================================================");
+    }
+    
+    protected void startPart(BlockSequence list, int breakClass) {
+        AbstractBreaker.log.debug("startPart() breakClass=" + breakClass);
+        if (pslm.getCurrentPage() == null) {
+            throw new IllegalStateException("curPage must not be null");
+        }
+        if (!pageBreakHandled) {
+            
+            //firstPart is necessary because we need the first page before we start the 
+            //algorithm so we have a BPD and IPD. This may subject to change later when we
+            //start handling more complex cases.
+            if (!firstPart) {
+                // if this is the first page that will be created by
+                // the current BlockSequence, it could have a break
+                // condition that must be satisfied;
+                // otherwise, we may simply need a new page
+                handleBreakTrait(breakClass);
+            }
+            pageProvider.setStartOfNextElementList(pslm.getCurrentPageNum(), 
+                    pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
+        }
+        pageBreakHandled = false;
+        // add static areas and resolve any new id areas
+        // finish page and add to area tree
+        firstPart = false;
+    }
+    
+    /** @see org.apache.fop.layoutmgr.AbstractBreaker#handleEmptyContent() */
+    protected void handleEmptyContent() {
+        pslm.getCurrentPV().getPage().fakeNonEmpty();
+    }
+    
+    protected void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp) {
+        // add footnote areas
+        if (pbp.footnoteFirstListIndex < pbp.footnoteLastListIndex
+            || pbp.footnoteFirstElementIndex <= pbp.footnoteLastElementIndex) {
+            // call addAreas() for each FootnoteBodyLM
+            for (int i = pbp.footnoteFirstListIndex; i <= pbp.footnoteLastListIndex; i++) {
+                LinkedList elementList = alg.getFootnoteList(i);
+                int firstIndex = (i == pbp.footnoteFirstListIndex 
+                        ? pbp.footnoteFirstElementIndex : 0);
+                int lastIndex = (i == pbp.footnoteLastListIndex 
+                        ? pbp.footnoteLastElementIndex : elementList.size() - 1);
+
+                SpaceResolver.performConditionalsNotification(elementList, 
+                        firstIndex, lastIndex, -1);
+                LayoutContext childLC = new LayoutContext(0);
+                AreaAdditionUtil.addAreas(null, 
+                        new KnuthPossPosIter(elementList, firstIndex, lastIndex + 1), 
+                        childLC);
+            }
+            // set the offset from the top margin
+            Footnote parentArea = (Footnote) pslm.getCurrentPV().getBodyRegion().getFootnote();
+            int topOffset = (int) pslm.getCurrentPV().getBodyRegion().getBPD() - parentArea.getBPD();
+            if (separatorArea != null) {
+                topOffset -= separatorArea.getBPD();
+            }
+            parentArea.setTop(topOffset);
+            parentArea.setSeparator(separatorArea);
+        }
+        pslm.getCurrentPV().getCurrentSpan().notifyFlowsFinished();
+    }
+    
+    /**
+     * @return the current child flow layout manager
+     */
+    protected LayoutManager getCurrentChildLM() {
+        return childFLM;
+    }
+    
+    /** @see org.apache.fop.layoutmgr.AbstractBreaker#observeElementList(java.util.List) */
+    protected void observeElementList(List elementList) {
+        ElementListObserver.observe(elementList, "breaker", 
+                ((PageSequence)pslm.getFObj()).getId());
+    }
+    
+    /**
+     * Depending on the kind of break condition, move to next column
+     * or page. May need to make an empty page if next page would
+     * not have the desired "handedness".
+     * @param breakVal - value of break-before or break-after trait.
+     */
+    private void handleBreakTrait(int breakVal) {
+        Page curPage = pslm.getCurrentPage();
+        if (breakVal == Constants.EN_ALL) {
+            //break due to span change in multi-column layout
+            curPage.getPageViewport().createSpan(true);
+            return;
+        } else if (breakVal == Constants.EN_NONE) {
+            curPage.getPageViewport().createSpan(false);
+            return;
+        } else if (breakVal == Constants.EN_COLUMN || breakVal <= 0) {
+            PageViewport pv = curPage.getPageViewport();
+            
+            //Check if previous page was spanned
+            boolean forceNewPageWithSpan = false;
+            RegionBody rb = (RegionBody)curPage.getSimplePageMaster().getRegion(
+                    Constants.FO_REGION_BODY);
+            if (breakVal < 0 
+                    && rb.getColumnCount() > 1 
+                    && pv.getCurrentSpan().getColumnCount() == 1) {
+                forceNewPageWithSpan = true;
+            }
+            
+            if (forceNewPageWithSpan) {
+                curPage = pslm.makeNewPage(false, false);
+                curPage.getPageViewport().createSpan(true);
+            } else if (pv.getCurrentSpan().hasMoreFlows()) {
+                pv.getCurrentSpan().moveToNextFlow();
+            } else {
+                curPage = pslm.makeNewPage(false, false);
+            }
+            return;
+        }
+        log.debug("handling break-before after page " + pslm.getCurrentPageNum() 
+            + " breakVal=" + breakVal);
+        if (needBlankPageBeforeNew(breakVal)) {
+            curPage = pslm.makeNewPage(true, false);
+        }
+        if (needNewPage(breakVal)) {
+            curPage = pslm.makeNewPage(false, false);
+        }
+    }
+    
+    /**
+     * Check if a blank page is needed to accomodate
+     * desired even or odd page number.
+     * @param breakVal - value of break-before or break-after trait.
+     */
+    private boolean needBlankPageBeforeNew(int breakVal) {
+        if (breakVal == Constants.EN_PAGE || (pslm.getCurrentPage().getPageViewport().getPage().isEmpty())) {
+            // any page is OK or we already have an empty page
+            return false;
+        } else {
+            /* IF we are on the kind of page we need, we'll need a new page. */
+            if (pslm.getCurrentPageNum() % 2 == 0) { // even page
+                return (breakVal == Constants.EN_EVEN_PAGE);
+            } else { // odd page
+                return (breakVal == Constants.EN_ODD_PAGE);
+            }
+        }
+    }
+    
+    /**
+     * See if need to generate a new page
+     * @param breakVal - value of break-before or break-after trait.
+     */
+    private boolean needNewPage(int breakVal) {
+        if (pslm.getCurrentPage().getPageViewport().getPage().isEmpty()) {
+            if (breakVal == Constants.EN_PAGE) {
+                return false;
+            } else if (pslm.getCurrentPageNum() % 2 == 0) { // even page
+                return (breakVal == Constants.EN_ODD_PAGE);
+            } else { // odd page
+                return (breakVal == Constants.EN_EVEN_PAGE);
+            }
+        } else {
+            return true;
+        }
+    }
+}
\ No newline at end of file
index cf12dffb99aa5159ed13da3d2df297f936407096..2c2e96986aadfb59a01e609f7de0c0d5b4f95f03 100644 (file)
@@ -38,7 +38,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
     private static Log log = LogFactory.getLog(PageBreakingAlgorithm.class);
 
     private LayoutManager topLevelLM;
-    private PageSequenceLayoutManager.PageProvider pageProvider;
+    private PageProvider pageProvider;
     private PageBreakingLayoutListener layoutListener;
     /** List of PageBreakPosition elements. */
     private LinkedList pageBreaks = null;
@@ -94,7 +94,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
     private boolean favorSinglePart = false;
     
     public PageBreakingAlgorithm(LayoutManager topLevelLM,
-                                 PageSequenceLayoutManager.PageProvider pageProvider,
+                                 PageProvider pageProvider,
                                  PageBreakingLayoutListener layoutListener,
                                  int alignment, int alignmentLast,
                                  MinOptMax footnoteSeparatorLength,
diff --git a/src/java/org/apache/fop/layoutmgr/PageProvider.java b/src/java/org/apache/fop/layoutmgr/PageProvider.java
new file mode 100644 (file)
index 0000000..94da601
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * 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;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.area.AreaTreeHandler;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.Region;
+import org.apache.fop.fo.pagination.SimplePageMaster;
+
+/**
+ * <p>This class delivers Page instances. It also caches them as necessary.
+ * </p>
+ * <p>Additional functionality makes sure that surplus instances that are requested by the
+ * page breaker are properly discarded, especially in situations where hard breaks cause
+ * blank pages. The reason for that: The page breaker sometimes needs to preallocate 
+ * additional pages since it doesn't know exactly until the end how many pages it really needs.
+ * </p>
+ */
+public class PageProvider implements Constants {
+    
+    private Log log = LogFactory.getLog(PageProvider.class);
+
+    /** Indices are evaluated relative to the first page in the page-sequence. */
+    public static final int RELTO_PAGE_SEQUENCE = 0;
+    /** Indices are evaluated relative to the first page in the current element list. */
+    public static final int RELTO_CURRENT_ELEMENT_LIST = 1;
+    
+    private int startPageOfPageSequence;
+    private int startPageOfCurrentElementList;
+    private int startColumnOfCurrentElementList;
+    private List cachedPages = new java.util.ArrayList();
+    
+    private int lastPageIndex = -1;
+    private int indexOfCachedLastPage = -1;
+    
+    //Cache to optimize getAvailableBPD() calls
+    private int lastRequestedIndex = -1;
+    private int lastReportedBPD = -1;
+
+    /** 
+     * AreaTreeHandler which activates the PSLM and controls
+     * the rendering of its pages.
+     */
+    private AreaTreeHandler areaTreeHandler;
+
+    /** 
+     * fo:page-sequence formatting object being
+     * processed by this class
+     */
+    private PageSequence pageSeq;
+
+    /**
+     * Main constructor.
+     * @param ps The page-sequence the provider operates on
+     */
+    public PageProvider(AreaTreeHandler ath, PageSequence ps) {
+        this.areaTreeHandler = ath;
+        this.pageSeq = ps;
+        this.startPageOfPageSequence = ps.getStartingPageNumber();
+    }
+    
+    /**
+     * The page breaker notifies the provider about the page number an element list starts
+     * on so it can later retrieve PageViewports relative to this first page.
+     * @param startPage the number of the first page for the element list.
+     * @param startColumn the starting column number for the element list. 
+     */
+    public void setStartOfNextElementList(int startPage, int startColumn) {
+        log.debug("start of the next element list is:"
+                + " page=" + startPage + " col=" + startColumn);
+        this.startPageOfCurrentElementList = startPage - startPageOfPageSequence + 1;
+        this.startColumnOfCurrentElementList = startColumn;
+        //Reset Cache
+        this.lastRequestedIndex = -1;
+        this.lastReportedBPD = -1;
+    }
+    
+    /**
+     * Sets the index of the last page. This is done as soon as the position of the last page
+     * is known or assumed.
+     * @param index the index relative to the first page in the page-sequence
+     */
+    public void setLastPageIndex(int index) {
+        this.lastPageIndex = index;
+    }
+    
+    /**
+     * Returns the available BPD for the part/page indicated by the index parameter.
+     * The index is the part/page relative to the start of the current element list.
+     * This method takes multiple columns into account.
+     * @param index zero-based index of the requested part/page
+     * @return the available BPD
+     */
+    public int getAvailableBPD(int index) {
+        //Special optimization: There may be many equal calls by the BreakingAlgorithm
+        if (this.lastRequestedIndex == index) {
+            if (log.isTraceEnabled()) {
+                log.trace("getAvailableBPD(" + index + ") -> (cached) " + lastReportedBPD);
+            }
+            return this.lastReportedBPD;
+        }
+        int c = index;
+        int pageIndex = 0;
+        int colIndex = startColumnOfCurrentElementList;
+        Page page = getPage(
+                false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
+        while (c > 0) {
+            colIndex++;
+            if (colIndex >= page.getPageViewport().getCurrentSpan().getColumnCount()) {
+                colIndex = 0;
+                pageIndex++;
+                page = getPage(
+                        false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
+            }
+            c--;
+        }
+        this.lastRequestedIndex = index;
+        this.lastReportedBPD = page.getPageViewport().getBodyRegion().getRemainingBPD();
+        if (log.isTraceEnabled()) {
+            log.trace("getAvailableBPD(" + index + ") -> " + lastReportedBPD);
+        }
+        return this.lastReportedBPD;
+    }
+    
+    /**
+     * Returns the part index (0<x<partCount) which denotes the first part on the last page 
+     * generated by the current element list.
+     * @param partCount Number of parts determined by the breaking algorithm
+     * @return the requested part index
+     */
+    public int getStartingPartIndexForLastPage(int partCount) {
+        int result = 0;
+        int idx = 0;
+        int pageIndex = 0;
+        int colIndex = startColumnOfCurrentElementList;
+        Page page = getPage(
+                false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
+        while (idx < partCount) {
+            if ((colIndex >= page.getPageViewport().getCurrentSpan().getColumnCount())) {
+                colIndex = 0;
+                pageIndex++;
+                page = getPage(
+                        false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
+                result = idx;
+            }
+            colIndex++;
+            idx++;
+        }
+        return result;
+    }
+
+    /**
+     * Returns a Page.
+     * @param isBlank true if this page is supposed to be blank.
+     * @param index Index of the page (see relativeTo)
+     * @param relativeTo Defines which value the index parameter should be evaluated relative 
+     * to. (One of PageProvider.RELTO_*)
+     * @return the requested Page
+     */
+    public Page getPage(boolean isBlank, int index, int relativeTo) {
+        if (relativeTo == RELTO_PAGE_SEQUENCE) {
+            return getPage(isBlank, index);
+        } else if (relativeTo == RELTO_CURRENT_ELEMENT_LIST) {
+            int effIndex = startPageOfCurrentElementList + index;
+            effIndex += startPageOfPageSequence - 1;
+            return getPage(isBlank, effIndex);
+        } else {
+            throw new IllegalArgumentException(
+                    "Illegal value for relativeTo: " + relativeTo);
+        }
+    }
+    
+    /**
+     * 
+     * @param isBlank
+     * @param index
+     * @return
+     */
+    protected Page getPage(boolean isBlank, int index) {
+        boolean isLastPage = (lastPageIndex >= 0) && (index == lastPageIndex);
+        if (log.isTraceEnabled()) {
+            log.trace("getPage(" + index + " " + (isBlank ? "blank" : "non-blank") 
+                    + (isLastPage ? " <LAST>" : "") + ")");
+        }
+        int intIndex = index - startPageOfPageSequence;
+        if (log.isTraceEnabled()) {
+            if (isBlank) {
+                log.trace("blank page requested: " + index);
+            }
+            if (isLastPage) {
+                log.trace("last page requested: " + index);
+            }
+        }
+        while (intIndex >= cachedPages.size()) {
+            if (log.isTraceEnabled()) {
+                log.trace("Caching " + index);
+            }
+            cacheNextPage(index, isBlank, isLastPage);
+        }
+        Page page = (Page)cachedPages.get(intIndex);
+        boolean replace = false;
+        if (page.getPageViewport().isBlank() != isBlank) {
+            log.debug("blank condition doesn't match. Replacing PageViewport.");
+            replace = true;
+        }
+        if ((isLastPage && indexOfCachedLastPage != intIndex)
+                || (!isLastPage && indexOfCachedLastPage >= 0)) {
+            log.debug("last page condition doesn't match. Replacing PageViewport.");
+            replace = true;
+            indexOfCachedLastPage = (isLastPage ? intIndex : -1);
+        }
+        if (replace) {
+            disardCacheStartingWith(intIndex);
+            page = cacheNextPage(index, isBlank, isLastPage);
+        }
+        return page;
+    }
+
+    private void disardCacheStartingWith(int index) {
+        while (index < cachedPages.size()) {
+            this.cachedPages.remove(cachedPages.size() - 1);
+            if (!pageSeq.goToPreviousSimplePageMaster()) {
+                log.warn("goToPreviousSimplePageMaster() on the first page called!");
+            }
+        }
+    }
+    
+    private Page cacheNextPage(int index, boolean isBlank, boolean isLastPage) {
+        try {
+            String pageNumberString = pageSeq.makeFormattedPageNumber(index);
+            SimplePageMaster spm = pageSeq.getNextSimplePageMaster(
+                    index, (startPageOfPageSequence == index), isLastPage, isBlank);
+                
+            Region body = spm.getRegion(FO_REGION_BODY);
+            if (!pageSeq.getMainFlow().getFlowName().equals(body.getRegionName())) {
+                // this is fine by the XSL Rec (fo:flow's flow-name can be mapped to
+                // any region), but we don't support it yet.
+                throw new FOPException("Flow '" + pageSeq.getMainFlow().getFlowName()
+                    + "' does not map to the region-body in page-master '"
+                    + spm.getMasterName() + "'.  FOP presently "
+                    + "does not support this.");
+            }
+            Page page = new Page(spm, index, pageNumberString, isBlank);
+            //Set unique key obtained from the AreaTreeHandler
+            page.getPageViewport().setKey(areaTreeHandler.generatePageViewportKey());
+            page.getPageViewport().setForeignAttributes(spm.getForeignAttributes());
+            cachedPages.add(page);
+            return page;
+        } catch (FOPException e) {
+            //TODO Maybe improve. It'll mean to propagate this exception up several
+            //methods calls.
+            throw new IllegalStateException(e.getMessage());
+        }
+    }
+    
+}
\ No newline at end of file
index ac13cd3ad8aa055b3efc137f75aac18400892de0..a34ce7956e2d3a67441d35d60649667532695fd0 100644 (file)
@@ -21,39 +21,26 @@ package org.apache.fop.layoutmgr;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.fop.apps.FOPException;
 import org.apache.fop.datatypes.Numeric;
 
 import org.apache.fop.area.AreaTreeHandler;
 import org.apache.fop.area.AreaTreeModel;
-import org.apache.fop.area.Block;
-import org.apache.fop.area.Footnote;
+import org.apache.fop.area.IDTracker;
 import org.apache.fop.area.PageViewport;
 import org.apache.fop.area.LineArea;
 import org.apache.fop.area.Resolvable;
 
 import org.apache.fop.fo.Constants;
-import org.apache.fop.fo.FONode;
-import org.apache.fop.fo.FObj;
 import org.apache.fop.fo.flow.Marker;
 import org.apache.fop.fo.flow.RetrieveMarker;
 
-import org.apache.fop.fo.pagination.Flow;
 import org.apache.fop.fo.pagination.PageSequence;
 import org.apache.fop.fo.pagination.PageSequenceMaster;
-import org.apache.fop.fo.pagination.Region;
-import org.apache.fop.fo.pagination.RegionBody;
 import org.apache.fop.fo.pagination.SideRegion;
-import org.apache.fop.fo.pagination.SimplePageMaster;
 import org.apache.fop.fo.pagination.StaticContent;
-import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener;
 import org.apache.fop.layoutmgr.inline.ContentLayoutManager;
 
-import org.apache.fop.traits.MinOptMax;
-
-import java.util.LinkedList;
 import java.util.List;
-import java.util.ListIterator;
 
 /**
  * LayoutManager for a PageSequence.  This class is instantiated by
@@ -77,23 +64,17 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
     private PageSequence pageSeq;
 
     private PageProvider pageProvider;
-    
+
+    private IDTracker idTracker;
+
     /** 
      * Current page with page-viewport-area being filled by
      * the PSLM.
      */
-    private Page curPage = null;
-
-    /**
-     * The FlowLayoutManager object, which processes
-     * the single fo:flow of the fo:page-sequence
-     */
-    private FlowLayoutManager childFLM = null;
+    private Page curPage;
 
     private int startPageNum = 0;
     private int currentPageNum = 0;
-
-    private Block separatorArea = null;
     
     /**
      * Constructor
@@ -104,8 +85,9 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
     public PageSequenceLayoutManager(AreaTreeHandler ath, PageSequence pseq) {
         super(pseq);
         this.areaTreeHandler = ath;
+        this.idTracker = ath.getIDTracker();
         this.pageSeq = pseq;
-        this.pageProvider = new PageProvider(this.pageSeq);
+        this.pageProvider = new PageProvider(ath, pseq);
     }
 
     /**
@@ -121,6 +103,13 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
         return this.pageProvider;
     }
     
+    /**
+     * @return the PageSequence being managed by this layout manager 
+     */
+    protected PageSequence getPageSequence() {
+        return pageSeq;
+    }
+
     /**
      * Activate the layout of this page sequence.
      * PageViewports corresponding to each page generated by this 
@@ -150,10 +139,6 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
 
         curPage = makeNewPage(false, false);
         
-        Flow mainFlow = pageSeq.getMainFlow();
-        childFLM = getLayoutManagerMaker().
-            makeFlowLayoutManager(this, mainFlow);
-
         PageBreaker breaker = new PageBreaker(this);
         int flowBPD = (int)getCurrentPV().getBodyRegion().getRemainingBPD();
         breaker.doLayout(flowBPD);
@@ -165,8 +150,8 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
      * Finished the page-sequence and notifies everyone about it.
      */
     public void finishPageSequence() {
-        if (!pageSeq.getId().equals("")) {
-            areaTreeHandler.signalIDProcessed(pageSeq.getId());
+        if (pageSeq.hasId()) {
+            idTracker.signalIDProcessed(pageSeq.getId());
         }
 
         pageSeq.getRoot().notifyPageSequenceFinished(currentPageNum,
@@ -188,392 +173,6 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
             log.debug("Ending layout");
         }
     }
-
-
-    private class PageBreaker extends AbstractBreaker {
-        
-        private PageSequenceLayoutManager pslm;
-        private boolean firstPart = true;
-        private boolean pageBreakHandled;
-        private boolean needColumnBalancing;
-        
-        private StaticContentLayoutManager footnoteSeparatorLM = null;
-
-        public PageBreaker(PageSequenceLayoutManager pslm) {
-            this.pslm = pslm;
-        }
-        
-        /** @see org.apache.fop.layoutmgr.AbstractBreaker */
-        protected void updateLayoutContext(LayoutContext context) {
-            int flowIPD = getCurrentPV().getCurrentSpan().getColumnWidth();
-            context.setRefIPD(flowIPD);
-        }
-        
-        /** @see org.apache.fop.layoutmgr.AbstractBreaker#getTopLevelLM() */
-        protected LayoutManager getTopLevelLM() {
-            return pslm;
-        }
-        
-        /** @see org.apache.fop.layoutmgr.AbstractBreaker#getPageProvider() */
-        protected PageSequenceLayoutManager.PageProvider getPageProvider() {
-            return pageProvider;
-        }
-        
-        /**
-         * @see org.apache.fop.layoutmgr.AbstractBreaker#getLayoutListener()
-         */
-        protected PageBreakingLayoutListener getLayoutListener() {
-            return new PageBreakingLayoutListener() {
-
-                public void notifyOverflow(int part, FObj obj) {
-                    Page p = pageProvider.getPage(
-                                false, part, PageProvider.RELTO_CURRENT_ELEMENT_LIST);
-                    RegionBody body = (RegionBody)p.getSimplePageMaster().getRegion(
-                            Region.FO_REGION_BODY);
-                    String err = FONode.decorateWithContextInfo(
-                            "Content of the region-body on page " 
-                            + p.getPageViewport().getPageNumberString() 
-                            + " overflows the available area in block-progression dimension.", 
-                            obj);
-                    if (body.getOverflow() == Constants.EN_ERROR_IF_OVERFLOW) {
-                        throw new RuntimeException(err);
-                    } else {
-                        PageSequenceLayoutManager.log.warn(err);
-                    }
-                }
-                
-            };
-        }
-
-        /** @see org.apache.fop.layoutmgr.AbstractBreaker */
-        protected int handleSpanChange(LayoutContext childLC, int nextSequenceStartsOn) {
-            needColumnBalancing = false;
-            if (childLC.getNextSpan() != Constants.NOT_SET) {
-                //Next block list will have a different span.
-                nextSequenceStartsOn = childLC.getNextSpan();
-                needColumnBalancing = (childLC.getNextSpan() == Constants.EN_ALL);
-            }
-            if (needColumnBalancing) {
-                AbstractBreaker.log.debug(
-                        "Column balancing necessary for the next element list!!!");
-            }
-            return nextSequenceStartsOn;
-        }
-
-        /** @see org.apache.fop.layoutmgr.AbstractBreaker */
-        protected int getNextBlockList(LayoutContext childLC, 
-                int nextSequenceStartsOn, 
-                List blockLists) {
-            if (!firstPart) {
-                // if this is the first page that will be created by
-                // the current BlockSequence, it could have a break
-                // condition that must be satisfied;
-                // otherwise, we may simply need a new page
-                handleBreakTrait(nextSequenceStartsOn);
-            }
-            firstPart = false;
-            pageBreakHandled = true;
-            pageProvider.setStartOfNextElementList(currentPageNum, 
-                    getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
-            return super.getNextBlockList(childLC, nextSequenceStartsOn, blockLists);
-        }
-        
-        /** @see org.apache.fop.layoutmgr.AbstractBreaker */
-        protected LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
-            LinkedList contentList = null;
-            
-            while (!childFLM.isFinished() && contentList == null) {
-                contentList = childFLM.getNextKnuthElements(context, alignment);
-            }
-
-            // scan contentList, searching for footnotes
-            boolean bFootnotesPresent = false;
-            if (contentList != null) {
-                ListIterator contentListIterator = contentList.listIterator();
-                while (contentListIterator.hasNext()) {
-                    ListElement element = (ListElement) contentListIterator.next();
-                    if (element instanceof KnuthBlockBox
-                        && ((KnuthBlockBox) element).hasAnchors()) {
-                        // element represents a line with footnote citations
-                        bFootnotesPresent = true;
-                        LayoutContext footnoteContext = new LayoutContext(context);
-                        footnoteContext.setStackLimit(context.getStackLimit());
-                        footnoteContext.setRefIPD(getCurrentPV()
-                                .getRegionReference(Constants.FO_REGION_BODY).getIPD());
-                        LinkedList footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs();
-                        ListIterator footnoteBodyIterator = footnoteBodyLMs.listIterator();
-                        // store the lists of elements representing the footnote bodies
-                        // in the box representing the line containing their references
-                        while (footnoteBodyIterator.hasNext()) {
-                            FootnoteBodyLayoutManager fblm 
-                                = (FootnoteBodyLayoutManager) footnoteBodyIterator.next();
-                            fblm.setParent(childFLM);
-                            fblm.initialize();
-                            ((KnuthBlockBox) element).addElementList(
-                                    fblm.getNextKnuthElements(footnoteContext, alignment));
-                        }
-                    }
-                }
-            }
-
-            // handle the footnote separator
-            StaticContent footnoteSeparator;
-            if (bFootnotesPresent
-                    && (footnoteSeparator = pageSeq.getStaticContent(
-                                            "xsl-footnote-separator")) != null) {
-                // the footnote separator can contain page-dependent content such as
-                // page numbers or retrieve markers, so its areas cannot simply be 
-                // obtained now and repeated in each page;
-                // we need to know in advance the separator bpd: the actual separator
-                // could be different from page to page, but its bpd would likely be
-                // always the same
-
-                // create a Block area that will contain the separator areas
-                separatorArea = new Block();
-                separatorArea.setIPD(pslm.getCurrentPV()
-                            .getRegionReference(Constants.FO_REGION_BODY).getIPD());
-                // create a StaticContentLM for the footnote separator
-                footnoteSeparatorLM = (StaticContentLayoutManager)
-                    getLayoutManagerMaker().makeStaticContentLayoutManager(
-                    pslm, footnoteSeparator, separatorArea);
-                footnoteSeparatorLM.doLayout();
-
-                footnoteSeparatorLength = new MinOptMax(separatorArea.getBPD());
-            }
-            return contentList;
-        }
-        
-        protected int getCurrentDisplayAlign() {
-            return curPage.getSimplePageMaster().getRegion(
-                    Constants.FO_REGION_BODY).getDisplayAlign();
-        }
-        
-        protected boolean hasMoreContent() {
-            return !childFLM.isFinished();
-        }
-        
-        protected void addAreas(PositionIterator posIter, LayoutContext context) {
-            if (footnoteSeparatorLM != null) {
-                StaticContent footnoteSeparator = pageSeq.getStaticContent(
-                        "xsl-footnote-separator");
-                // create a Block area that will contain the separator areas
-                separatorArea = new Block();
-                separatorArea.setIPD(
-                        getCurrentPV().getRegionReference(Constants.FO_REGION_BODY).getIPD());
-                // create a StaticContentLM for the footnote separator
-                footnoteSeparatorLM = (StaticContentLayoutManager)
-                    getLayoutManagerMaker().makeStaticContentLayoutManager(
-                    pslm, footnoteSeparator, separatorArea);
-                footnoteSeparatorLM.doLayout();
-            }
-
-            childFLM.addAreas(posIter, context);    
-        }
-        
-        protected void doPhase3(PageBreakingAlgorithm alg, int partCount, 
-                BlockSequence originalList, BlockSequence effectiveList) {
-            if (needColumnBalancing) {
-                doPhase3WithColumnBalancing(alg, partCount, originalList, effectiveList);
-            } else {
-                if (!hasMoreContent() && pageSeq.hasPagePositionLast()) {
-                    //last part is reached and we have a "last page" condition
-                    doPhase3WithLastPage(alg, partCount, originalList, effectiveList);
-                } else {
-                    //Directly add areas after finding the breaks
-                    addAreas(alg, partCount, originalList, effectiveList);
-                }
-            }
-        }
-
-        private void doPhase3WithLastPage(PageBreakingAlgorithm alg, int partCount, 
-                BlockSequence originalList, BlockSequence effectiveList) {
-            int newStartPos;
-            int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
-            if (restartPoint > 0) {
-                //Add definitive areas before last page
-                addAreas(alg, restartPoint, originalList, effectiveList);
-                //Get page break from which we restart
-                PageBreakPosition pbp = (PageBreakPosition)
-                        alg.getPageBreaks().get(restartPoint - 1);
-                newStartPos = pbp.getLeafPos();
-                //Handle page break right here to avoid any side-effects
-                if (newStartPos > 0) {
-                    handleBreakTrait(EN_PAGE);
-                }
-            } else {
-                newStartPos = 0;
-            }
-            AbstractBreaker.log.debug("Last page handling now!!!");
-            AbstractBreaker.log.debug("===================================================");
-            AbstractBreaker.log.debug("Restarting at " + restartPoint 
-                    + ", new start position: " + newStartPos);
-
-            pageBreakHandled = true;
-            //Update so the available BPD is reported correctly
-            pageProvider.setStartOfNextElementList(currentPageNum, 
-                    getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
-            pageProvider.setLastPageIndex(currentPageNum);
-
-            //Restart last page
-            PageBreakingAlgorithm algRestart = new PageBreakingAlgorithm(
-                    getTopLevelLM(),
-                    getPageProvider(), getLayoutListener(),
-                    alg.getAlignment(), alg.getAlignmentLast(), 
-                    footnoteSeparatorLength,
-                    isPartOverflowRecoveryActivated(), false, false);
-            //alg.setConstantLineWidth(flowBPD);
-            int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
-                        newStartPos,
-                        1, true, BreakingAlgorithm.ALL_BREAKS);
-            AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
-                    + " pageBreaks.size()= " + algRestart.getPageBreaks().size());
-            boolean replaceLastPage 
-                    = iOptPageCount <= getCurrentPV().getBodyRegion().getColumnCount(); 
-            if (replaceLastPage) {
-
-                //Replace last page
-                pslm.curPage = pageProvider.getPage(false, currentPageNum);
-                //Make sure we only add the areas we haven't added already
-                effectiveList.ignoreAtStart = newStartPos;
-                addAreas(algRestart, iOptPageCount, originalList, effectiveList);
-            } else {
-                effectiveList.ignoreAtStart = newStartPos;
-                addAreas(alg, restartPoint, partCount - restartPoint, originalList, effectiveList);
-                //Add blank last page
-                pageProvider.setLastPageIndex(currentPageNum + 1);
-                pslm.curPage = makeNewPage(true, true);
-            }
-            AbstractBreaker.log.debug("===================================================");
-        }
-
-        private void doPhase3WithColumnBalancing(PageBreakingAlgorithm alg, int partCount, 
-                BlockSequence originalList, BlockSequence effectiveList) {
-            AbstractBreaker.log.debug("Column balancing now!!!");
-            AbstractBreaker.log.debug("===================================================");
-            int newStartPos;
-            int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
-            if (restartPoint > 0) {
-                //Add definitive areas
-                addAreas(alg, restartPoint, originalList, effectiveList);
-                //Get page break from which we restart
-                PageBreakPosition pbp = (PageBreakPosition)
-                        alg.getPageBreaks().get(restartPoint - 1);
-                newStartPos = pbp.getLeafPos();
-                //Handle page break right here to avoid any side-effects
-                if (newStartPos > 0) {
-                    handleBreakTrait(EN_PAGE);
-                }
-            } else {
-                newStartPos = 0;
-            }
-            AbstractBreaker.log.debug("Restarting at " + restartPoint 
-                    + ", new start position: " + newStartPos);
-
-            pageBreakHandled = true;
-            //Update so the available BPD is reported correctly
-            pageProvider.setStartOfNextElementList(currentPageNum, 
-                    getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
-
-            //Restart last page
-            PageBreakingAlgorithm algRestart = new BalancingColumnBreakingAlgorithm(
-                    getTopLevelLM(),
-                    getPageProvider(), getLayoutListener(),
-                    alignment, Constants.EN_START, footnoteSeparatorLength,
-                    isPartOverflowRecoveryActivated(),
-                    getCurrentPV().getBodyRegion().getColumnCount());
-            //alg.setConstantLineWidth(flowBPD);
-            int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
-                        newStartPos,
-                        1, true, BreakingAlgorithm.ALL_BREAKS);
-            AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
-                    + " pageBreaks.size()= " + algRestart.getPageBreaks().size());
-            if (iOptPageCount > getCurrentPV().getBodyRegion().getColumnCount()) {
-                AbstractBreaker.log.warn(
-                        "Breaking algorithm produced more columns than are available.");
-                /* reenable when everything works
-                throw new IllegalStateException(
-                        "Breaking algorithm must not produce more columns than available.");
-                */
-            }
-            //Make sure we only add the areas we haven't added already
-            effectiveList.ignoreAtStart = newStartPos;
-            addAreas(algRestart, iOptPageCount, originalList, effectiveList);
-            AbstractBreaker.log.debug("===================================================");
-        }
-        
-        protected void startPart(BlockSequence list, int breakClass) {
-            AbstractBreaker.log.debug("startPart() breakClass=" + breakClass);
-            if (curPage == null) {
-                throw new IllegalStateException("curPage must not be null");
-            }
-            if (!pageBreakHandled) {
-                
-                //firstPart is necessary because we need the first page before we start the 
-                //algorithm so we have a BPD and IPD. This may subject to change later when we
-                //start handling more complex cases.
-                if (!firstPart) {
-                    // if this is the first page that will be created by
-                    // the current BlockSequence, it could have a break
-                    // condition that must be satisfied;
-                    // otherwise, we may simply need a new page
-                    handleBreakTrait(breakClass);
-                }
-                pageProvider.setStartOfNextElementList(currentPageNum, 
-                        getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
-            }
-            pageBreakHandled = false;
-            // add static areas and resolve any new id areas
-            // finish page and add to area tree
-            firstPart = false;
-        }
-        
-        /** @see org.apache.fop.layoutmgr.AbstractBreaker#handleEmptyContent() */
-        protected void handleEmptyContent() {
-            getCurrentPV().getPage().fakeNonEmpty();
-        }
-        
-        protected void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp) {
-            // add footnote areas
-            if (pbp.footnoteFirstListIndex < pbp.footnoteLastListIndex
-                || pbp.footnoteFirstElementIndex <= pbp.footnoteLastElementIndex) {
-                // call addAreas() for each FootnoteBodyLM
-                for (int i = pbp.footnoteFirstListIndex; i <= pbp.footnoteLastListIndex; i++) {
-                    LinkedList elementList = alg.getFootnoteList(i);
-                    int firstIndex = (i == pbp.footnoteFirstListIndex 
-                            ? pbp.footnoteFirstElementIndex : 0);
-                    int lastIndex = (i == pbp.footnoteLastListIndex 
-                            ? pbp.footnoteLastElementIndex : elementList.size() - 1);
-
-                    SpaceResolver.performConditionalsNotification(elementList, 
-                            firstIndex, lastIndex, -1);
-                    LayoutContext childLC = new LayoutContext(0);
-                    AreaAdditionUtil.addAreas(null, 
-                            new KnuthPossPosIter(elementList, firstIndex, lastIndex + 1), 
-                            childLC);
-                }
-                // set the offset from the top margin
-                Footnote parentArea = (Footnote) getCurrentPV().getBodyRegion().getFootnote();
-                int topOffset = (int) getCurrentPV().getBodyRegion().getBPD() - parentArea.getBPD();
-                if (separatorArea != null) {
-                    topOffset -= separatorArea.getBPD();
-                }
-                parentArea.setTop(topOffset);
-                parentArea.setSeparator(separatorArea);
-            }
-            getCurrentPV().getCurrentSpan().notifyFlowsFinished();
-        }
-        
-        protected LayoutManager getCurrentChildLM() {
-            return childFLM;
-        }
-        
-        /** @see org.apache.fop.layoutmgr.AbstractBreaker#observeElementList(java.util.List) */
-        protected void observeElementList(List elementList) {
-            ElementListObserver.observe(elementList, "breaker", 
-                    ((PageSequence)pslm.getFObj()).getId());
-        }
-        
-    }
     
     /**
      * Provides access to the current page.
@@ -583,6 +182,22 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
         return curPage;
     }
 
+    /**
+     * Provides access for setting the current page.
+     * @param currentPage the new current Page
+     */
+    protected void setCurrentPage(Page currentPage) {
+        this.curPage = currentPage;
+    }
+
+    /**
+     * Provides access to the current page number
+     * @return the current page number
+     */
+    protected int getCurrentPageNum() {
+        return currentPageNum;
+    }
+
     /**
      * Provides access to the current page viewport.
      * @return the current PageViewport
@@ -607,7 +222,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
      * @return the first PageViewport that contains the ID trait
      */
     public PageViewport getFirstPVWithID(String idref) {
-        List list = areaTreeHandler.getPageViewportsContainingID(idref);
+        List list = idTracker.getPageViewportsContainingID(idref);
         if (list != null && list.size() > 0) {
             return (PageViewport) list.get(0);
         }
@@ -622,7 +237,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
      * @return the last PageViewport that contains the ID trait
      */
     public PageViewport getLastPVWithID(String idref) {
-        List list = areaTreeHandler.getPageViewportsContainingID(idref);
+        List list = idTracker.getPageViewportsContainingID(idref);
         if (list != null && list.size() > 0) {
             return (PageViewport) list.get(list.size() - 1);
         }
@@ -639,7 +254,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
      */
     public void addIDToPage(String id) {
         if (id != null && id.length() > 0) {
-            areaTreeHandler.associateIDWithPageViewport(id, curPage.getPageViewport());
+            idTracker.associateIDWithPageViewport(id, curPage.getPageViewport());
         }
     }
     
@@ -654,8 +269,8 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
         if (log.isDebugEnabled()) {
             log.debug("associateLayoutManagerID(" + id + ")");
         }
-        if (!areaTreeHandler.alreadyResolvedID(id)) {
-            areaTreeHandler.signalPendingID(id);
+        if (!idTracker.alreadyResolvedID(id)) {
+            idTracker.signalPendingID(id);
             return false;
         } else {
             return true;
@@ -668,7 +283,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
      * @param id the id for which layout has finished
      */
     public void notifyEndOfLayout(String id) {
-        areaTreeHandler.signalIDProcessed(id);
+        idTracker.signalIDProcessed(id);
     }
     
     /**
@@ -676,7 +291,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
      * resolved, e.g. the internal-destination of an fo:basic-link)
      * for both the AreaTreeHandler and PageViewport object.
      * 
-     * The AreaTreeHandler keeps a document-wide list of idref's
+     * The IDTracker keeps a document-wide list of idref's
      * and the PV's needing them to be resolved.  It uses this to  
      * send notifications to the PV's when an id has been resolved.
      * 
@@ -689,7 +304,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
      */
     public void addUnresolvedArea(String id, Resolvable res) {
         curPage.getPageViewport().addUnresolvedIDRef(id, res);
-        areaTreeHandler.addUnresolvedIDRef(id, curPage.getPageViewport());
+        idTracker.addUnresolvedIDRef(id, curPage.getPageViewport());
     }
 
     /**
@@ -750,7 +365,14 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
         }
     }
 
-    private Page makeNewPage(boolean bIsBlank, boolean bIsLast) {
+    /**
+     * Makes a new page
+     * 
+     * @param bIsBlank whether this page is blank or not
+     * @param bIsLast whether this page is the last page or not
+     * @return a new page
+     */
+    protected Page makeNewPage(boolean bIsBlank, boolean bIsLast) {
         if (curPage != null) {
             finishPage();
         }
@@ -797,7 +419,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
         
         // Try to resolve any unresolved IDs for the current page.
         // 
-        areaTreeHandler.tryIDResolution(curPage.getPageViewport());
+        idTracker.tryIDResolution(curPage.getPageViewport());
         // Queue for ID resolution and rendering
         areaTreeHandler.getAreaTreeModel().addPage(curPage.getPageViewport());
         if (log.isDebugEnabled()) {
@@ -806,320 +428,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
         }
         curPage = null;
     }
-    
-    /**
-     * Depending on the kind of break condition, move to next column
-     * or page. May need to make an empty page if next page would
-     * not have the desired "handedness".
-     * @param breakVal - value of break-before or break-after trait.
-     */
-    private void handleBreakTrait(int breakVal) {
-        if (breakVal == Constants.EN_ALL) {
-            //break due to span change in multi-column layout
-            curPage.getPageViewport().createSpan(true);
-            return;
-        } else if (breakVal == Constants.EN_NONE) {
-            curPage.getPageViewport().createSpan(false);
-            return;
-        } else if (breakVal == Constants.EN_COLUMN || breakVal <= 0) {
-            PageViewport pv = curPage.getPageViewport();
-            
-            //Check if previous page was spanned
-            boolean forceNewPageWithSpan = false;
-            RegionBody rb = (RegionBody)curPage.getSimplePageMaster().getRegion(
-                    Constants.FO_REGION_BODY);
-            if (breakVal < 0 
-                    && rb.getColumnCount() > 1 
-                    && pv.getCurrentSpan().getColumnCount() == 1) {
-                forceNewPageWithSpan = true;
-            }
-            
-            if (forceNewPageWithSpan) {
-                curPage = makeNewPage(false, false);
-                curPage.getPageViewport().createSpan(true);
-            } else if (pv.getCurrentSpan().hasMoreFlows()) {
-                pv.getCurrentSpan().moveToNextFlow();
-            } else {
-                curPage = makeNewPage(false, false);
-            }
-            return;
-        }
-        log.debug("handling break-before after page " + currentPageNum 
-            + " breakVal=" + breakVal);
-        if (needBlankPageBeforeNew(breakVal)) {
-            curPage = makeNewPage(true, false);
-        }
-        if (needNewPage(breakVal)) {
-            curPage = makeNewPage(false, false);
-        }
-    }
-
-    /**
-     * Check if a blank page is needed to accomodate
-     * desired even or odd page number.
-     * @param breakVal - value of break-before or break-after trait.
-     */
-    private boolean needBlankPageBeforeNew(int breakVal) {
-        if (breakVal == Constants.EN_PAGE || (curPage.getPageViewport().getPage().isEmpty())) {
-            // any page is OK or we already have an empty page
-            return false;
-        } else {
-            /* IF we are on the kind of page we need, we'll need a new page. */
-            if (currentPageNum % 2 == 0) { // even page
-                return (breakVal == Constants.EN_EVEN_PAGE);
-            } else { // odd page
-                return (breakVal == Constants.EN_ODD_PAGE);
-            }
-        }
-    }
-
-    /**
-     * See if need to generate a new page
-     * @param breakVal - value of break-before or break-after trait.
-     */
-    private boolean needNewPage(int breakVal) {
-        if (curPage.getPageViewport().getPage().isEmpty()) {
-            if (breakVal == Constants.EN_PAGE) {
-                return false;
-            } else if (currentPageNum % 2 == 0) { // even page
-                return (breakVal == Constants.EN_ODD_PAGE);
-            } else { // odd page
-                return (breakVal == Constants.EN_EVEN_PAGE);
-            }
-        } else {
-            return true;
-        }
-    }
-    
-    
-    /**
-     * <p>This class delivers Page instances. It also caches them as necessary.
-     * </p>
-     * <p>Additional functionality makes sure that surplus instances that are requested by the
-     * page breaker are properly discarded, especially in situations where hard breaks cause
-     * blank pages. The reason for that: The page breaker sometimes needs to preallocate 
-     * additional pages since it doesn't know exactly until the end how many pages it really needs.
-     * </p>
-     */
-    public class PageProvider {
-        
-        private Log log = LogFactory.getLog(PageProvider.class);
-
-        /** Indices are evaluated relative to the first page in the page-sequence. */
-        public static final int RELTO_PAGE_SEQUENCE = 0;
-        /** Indices are evaluated relative to the first page in the current element list. */
-        public static final int RELTO_CURRENT_ELEMENT_LIST = 1;
-        
-        private int startPageOfPageSequence;
-        private int startPageOfCurrentElementList;
-        private int startColumnOfCurrentElementList;
-        private List cachedPages = new java.util.ArrayList();
-        
-        private int lastPageIndex = -1;
-        private int indexOfCachedLastPage = -1;
-        
-        //Cache to optimize getAvailableBPD() calls
-        private int lastRequestedIndex = -1;
-        private int lastReportedBPD = -1;
-        
-        /**
-         * Main constructor.
-         * @param ps The page-sequence the provider operates on
-         */
-        public PageProvider(PageSequence ps) {
-            this.startPageOfPageSequence = ps.getStartingPageNumber();
-        }
-        
-        /**
-         * The page breaker notifies the provider about the page number an element list starts
-         * on so it can later retrieve PageViewports relative to this first page.
-         * @param startPage the number of the first page for the element list.
-         * @param startColumn the starting column number for the element list. 
-         */
-        public void setStartOfNextElementList(int startPage, int startColumn) {
-            log.debug("start of the next element list is:"
-                    + " page=" + startPage + " col=" + startColumn);
-            this.startPageOfCurrentElementList = startPage - startPageOfPageSequence + 1;
-            this.startColumnOfCurrentElementList = startColumn;
-            //Reset Cache
-            this.lastRequestedIndex = -1;
-            this.lastReportedBPD = -1;
-        }
-        
-        /**
-         * Sets the index of the last page. This is done as soon as the position of the last page
-         * is known or assumed.
-         * @param index the index relative to the first page in the page-sequence
-         */
-        public void setLastPageIndex(int index) {
-            this.lastPageIndex = index;
-        }
-        
-        /**
-         * Returns the available BPD for the part/page indicated by the index parameter.
-         * The index is the part/page relative to the start of the current element list.
-         * This method takes multiple columns into account.
-         * @param index zero-based index of the requested part/page
-         * @return the available BPD
-         */
-        public int getAvailableBPD(int index) {
-            //Special optimization: There may be many equal calls by the BreakingAlgorithm
-            if (this.lastRequestedIndex == index) {
-                if (log.isTraceEnabled()) {
-                    log.trace("getAvailableBPD(" + index + ") -> (cached) " + lastReportedBPD);
-                }
-                return this.lastReportedBPD;
-            }
-            int c = index;
-            int pageIndex = 0;
-            int colIndex = startColumnOfCurrentElementList;
-            Page page = getPage(
-                    false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
-            while (c > 0) {
-                colIndex++;
-                if (colIndex >= page.getPageViewport().getCurrentSpan().getColumnCount()) {
-                    colIndex = 0;
-                    pageIndex++;
-                    page = getPage(
-                            false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
-                }
-                c--;
-            }
-            this.lastRequestedIndex = index;
-            this.lastReportedBPD = page.getPageViewport().getBodyRegion().getRemainingBPD();
-            if (log.isTraceEnabled()) {
-                log.trace("getAvailableBPD(" + index + ") -> " + lastReportedBPD);
-            }
-            return this.lastReportedBPD;
-        }
-        
-        /**
-         * Returns the part index (0<x<partCount) which denotes the first part on the last page 
-         * generated by the current element list.
-         * @param partCount Number of parts determined by the breaking algorithm
-         * @return the requested part index
-         */
-        public int getStartingPartIndexForLastPage(int partCount) {
-            int result = 0;
-            int idx = 0;
-            int pageIndex = 0;
-            int colIndex = startColumnOfCurrentElementList;
-            Page page = getPage(
-                    false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
-            while (idx < partCount) {
-                if ((colIndex >= page.getPageViewport().getCurrentSpan().getColumnCount())) {
-                    colIndex = 0;
-                    pageIndex++;
-                    page = getPage(
-                            false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
-                    result = idx;
-                }
-                colIndex++;
-                idx++;
-            }
-            return result;
-        }
-
-        /**
-         * Returns a Page.
-         * @param isBlank true if this page is supposed to be blank.
-         * @param index Index of the page (see relativeTo)
-         * @param relativeTo Defines which value the index parameter should be evaluated relative 
-         * to. (One of PageProvider.RELTO_*)
-         * @return the requested Page
-         */
-        public Page getPage(boolean isBlank, int index, int relativeTo) {
-            if (relativeTo == RELTO_PAGE_SEQUENCE) {
-                return getPage(isBlank, index);
-            } else if (relativeTo == RELTO_CURRENT_ELEMENT_LIST) {
-                int effIndex = startPageOfCurrentElementList + index;
-                effIndex += startPageOfPageSequence - 1;
-                return getPage(isBlank, effIndex);
-            } else {
-                throw new IllegalArgumentException(
-                        "Illegal value for relativeTo: " + relativeTo);
-            }
-        }
         
-        private Page getPage(boolean isBlank, int index) {
-            boolean isLastPage = (lastPageIndex >= 0) && (index == lastPageIndex);
-            if (log.isTraceEnabled()) {
-                log.trace("getPage(" + index + " " + (isBlank ? "blank" : "non-blank") 
-                        + (isLastPage ? " <LAST>" : "") + ")");
-            }
-            int intIndex = index - startPageOfPageSequence;
-            if (log.isTraceEnabled()) {
-                if (isBlank) {
-                    log.trace("blank page requested: " + index);
-                }
-                if (isLastPage) {
-                    log.trace("last page requested: " + index);
-                }
-            }
-            while (intIndex >= cachedPages.size()) {
-                if (log.isTraceEnabled()) {
-                    log.trace("Caching " + index);
-                }
-                cacheNextPage(index, isBlank, isLastPage);
-            }
-            Page page = (Page)cachedPages.get(intIndex);
-            boolean replace = false;
-            if (page.getPageViewport().isBlank() != isBlank) {
-                log.debug("blank condition doesn't match. Replacing PageViewport.");
-                replace = true;
-            }
-            if ((isLastPage && indexOfCachedLastPage != intIndex)
-                    || (!isLastPage && indexOfCachedLastPage >= 0)) {
-                log.debug("last page condition doesn't match. Replacing PageViewport.");
-                replace = true;
-                indexOfCachedLastPage = (isLastPage ? intIndex : -1);
-            }
-            if (replace) {
-                disardCacheStartingWith(intIndex);
-                page = cacheNextPage(index, isBlank, isLastPage);
-            }
-            return page;
-        }
-
-        private void disardCacheStartingWith(int index) {
-            while (index < cachedPages.size()) {
-                this.cachedPages.remove(cachedPages.size() - 1);
-                if (!pageSeq.goToPreviousSimplePageMaster()) {
-                    log.warn("goToPreviousSimplePageMaster() on the first page called!");
-                }
-            }
-        }
-        
-        private Page cacheNextPage(int index, boolean isBlank, boolean isLastPage) {
-            try {
-                String pageNumberString = pageSeq.makeFormattedPageNumber(index);
-                SimplePageMaster spm = pageSeq.getNextSimplePageMaster(
-                        index, (startPageOfPageSequence == index), isLastPage, isBlank);
-                    
-                Region body = spm.getRegion(FO_REGION_BODY);
-                if (!pageSeq.getMainFlow().getFlowName().equals(body.getRegionName())) {
-                    // this is fine by the XSL Rec (fo:flow's flow-name can be mapped to
-                    // any region), but we don't support it yet.
-                    throw new FOPException("Flow '" + pageSeq.getMainFlow().getFlowName()
-                        + "' does not map to the region-body in page-master '"
-                        + spm.getMasterName() + "'.  FOP presently "
-                        + "does not support this.");
-                }
-                Page page = new Page(spm, index, pageNumberString, isBlank);
-                //Set unique key obtained from the AreaTreeHandler
-                page.getPageViewport().setKey(areaTreeHandler.generatePageViewportKey());
-                page.getPageViewport().setForeignAttributes(spm.getForeignAttributes());
-                cachedPages.add(page);
-                return page;
-            } catch (FOPException e) {
-                //TODO Maybe improve. It'll mean to propagate this exception up several
-                //methods calls.
-                throw new IllegalStateException(e.getMessage());
-            }
-        }
-        
-    }
-
     /**
      * Act upon the force-page-count trait,
      * in relation to the initial-page-number trait of the following page-sequence.
index 7e261d07439b3196ba6c6aa3d06f82a987559a34..e60e38870e5cd7ba4e6c17db5270a5323774052a 100644 (file)
@@ -58,8 +58,8 @@ public class BasicLinkLayoutManager extends InlineLayoutManager {
      */
     private void setupBasicLinkArea(LayoutManager parentLM, InlineArea area) {
         // internal destinations take precedence:
-        String idref = fobj.getInternalDestination();
-        if (idref != null && idref.length() > 0) {
+        if (fobj.hasInternalDestination()) {
+            String idref = fobj.getInternalDestination();
             PageSequenceLayoutManager pslm = getPSLM();
             // the INTERNAL_LINK trait is added by the LinkResolver
             // if and when the link is resolved:
@@ -68,13 +68,10 @@ public class BasicLinkLayoutManager extends InlineLayoutManager {
             if (!res.isResolved()) {
                 pslm.addUnresolvedArea(idref, res);
             }
-        } else {
-            String extdest = fobj.getExternalDestination();
-            if (extdest != null) {
-                String url = URISpecification.getURL(extdest);
-                if (url.length() > 0) {
-                    area.addTrait(Trait.EXTERNAL_LINK, url);
-                }
+        } else if (fobj.hasExternalDestination()) {
+            String url = URISpecification.getURL(fobj.getExternalDestination());
+            if (url.length() > 0) {
+                area.addTrait(Trait.EXTERNAL_LINK, url);
             }
         }
     }
index ac0363cb2662414cfd50ec440646e9f9314bb8e0..4a142cffefb8959b485426f1474155910b29621e 100644 (file)
@@ -1093,7 +1093,7 @@ public class RTFHandler extends FOEventHandler {
 
             RtfHyperLink link = textrun.addHyperlink(new RtfAttributes());
 
-            if (basicLink.getExternalDestination() != null) {
+            if (basicLink.hasExternalDestination()) {
                 link.setExternalURL(basicLink.getExternalDestination());
             } else {
                 link.setInternalURL(basicLink.getInternalDestination());
index ff79d4998b9f44e0ac175ad27753e19dfa5463e1..24df14c8881ea8e77d1f1c01e1484d6be56f259b 100644 (file)
 
   <changes>
     <release version="FOP Trunk">
+      <action context="code" dev="AD" type="update" fixes-bug="42089" due-to="Adrian Cumiskey">
+        Code cleanup and restructuring.
+      </action>
+      <action context="Code" dev="AD" type="add">
+        Slight improvement of relative font-weight handling in the properties
+        package.
+      </action>
       <action context="Code" dev="JM" type="update">
         Updated PDF/A-1b support according to ISO-19005-1:2005/Cor.1:2007.
       </action>