]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Implemented cloning and reparenting of the subtree under a marker to
authorSimon Pepping <spepping@apache.org>
Tue, 21 Dec 2004 11:28:05 +0000 (11:28 +0000)
committerSimon Pepping <spepping@apache.org>
Tue, 21 Dec 2004 11:28:05 +0000 (11:28 +0000)
the retrieving retrieve-marker. The FO nodes are cloned. The new
subtree is attached to the RetrieveMarker object. The property
lists are not cloned. The subtree of property lists is attached to the
property list of the RetrieveMarker object. This is only needed for
the binding of the FO nodes. After that a subsequent retrieve-marker
may reparent the property lists.

Removed Marker's reference to its property list. In Marker.endOfNode()
the parent of the property lists of the direct children of marker is
reset to null. FOText nodes are not mapped to the Marker's property
list in Marker. This allows the Marker's property list and its
ancestors to be GC'ed.

FOText nodes use the parent FO node's property list or the
RetrieveMarker's property list for binding.

TODO: Block.handleWhiteSpace is not applied to text in retrieve-marker.
TODO: White space treatment around retrieve-marker is incorrect.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@198204 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/fo/FONode.java
src/java/org/apache/fop/fo/FObj.java
src/java/org/apache/fop/fo/flow/Marker.java
src/java/org/apache/fop/fo/flow/RetrieveMarker.java
src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java

index d128454beb232c238649de3b5bcebb8f354a48e4..ed8959813c8395d65b85c11bb47a44dc7a76b28a 100644 (file)
@@ -37,7 +37,7 @@ import org.apache.fop.util.CharUtilities;
 /**
  * base class for nodes in the XML tree
  */
-public abstract class FONode {
+public abstract class FONode implements Cloneable {
 
     protected static String FO_URI = FOElementMapping.URI;
 
@@ -62,6 +62,34 @@ public abstract class FONode {
         this.parent = parent;
     }
 
+    /**
+     * Perform a shallow cloning operation,
+     * set its parent, and optionally clean the list of child nodes
+     * @param parent the intended parent of the clone
+     * @param removeChildren if true, clean the list of child nodes
+     * @return the cloned FO node
+     */
+    public FONode clone(FONode parent, boolean removeChildren)
+        throws FOPException {
+        FONode foNode = (FONode) clone();
+        foNode.parent = parent;
+        parent.addChildNode(foNode);
+        return foNode;
+    }
+
+    /**
+     * Perform a shallow cloning operation
+     * 
+     * @see java.lang.Object#clone()
+     * @return the cloned object
+     */
+    protected Object clone() {
+        try {
+            return super.clone();
+        } catch (CloneNotSupportedException e) { }
+        return null;
+    }
+
     /**
      * Set the location information for this element
      * @param locator the org.xml.sax.Locator object
index 87f989c02f5d3dc9b485eae447356cd97db59a76..7820f9acdb3f7b600c7acf52571f7ffc7ef94377 100644 (file)
@@ -85,6 +85,18 @@ public class FObj extends FONode implements Constants {
         }
     }
 
+    /**
+     * @see org.apache.fop.fo.FONode#clone(FONode, boolean)
+     */
+    public FONode clone(FONode parent, boolean removeChildren)
+        throws FOPException {
+        FObj fobj = (FObj) super.clone(parent, removeChildren);
+        if (removeChildren) {
+            fobj.childNodes = null;
+        }
+        return fobj;
+    }
+
     /**
      * @see org.apache.fop.fo.FONode#processNode
      */
index 8ac8b1345f6c0046cb7a6d7b842691d3d6e8c092..b8395d0747c0a92d4a04abebe14528e037299f27 100644 (file)
@@ -45,9 +45,8 @@ public class Marker extends FObjMixed {
     private String markerClassName;
     // End of property values
 
-    private MarkerPropertyList propertyList;
     private PropertyListMaker savePropertyListMaker;
-    private HashMap children = new HashMap();
+    private HashMap descPLists = new HashMap();
 
     /**
      * Create a marker fo.
@@ -65,27 +64,16 @@ public class Marker extends FObjMixed {
     }
     
     /**
-     * Rebind the marker and all the children using the specified 
-     * parentPropertyList which comes from the fo:retrieve-marker element.
-     * @param parentPropertyList The property list from fo:retrieve-marker.
+     * retrieve the property list of foNode
+     * @param foNode the FO node whose property list is requested
+     * @return the MarkerPropertyList of foNode
      */
-    public void rebind(PropertyList parentPropertyList) throws FOPException {
-        // Set a new parent property list and bind all the children again.
-        propertyList.setParentPropertyList(parentPropertyList);
-        for (Iterator i = children.keySet().iterator(); i.hasNext(); ) {
-            FONode child = (FONode) i.next();
-            PropertyList childList = (PropertyList) children.get(child);
-            if (child instanceof FObj) {
-                ((FObj) child).bind(childList);
-            } else if (child instanceof FOText) {
-                ((FOText) child).bind(childList);
-            }
-        }
+    protected MarkerPropertyList getPList(FONode foNode) {
+        return (MarkerPropertyList) descPLists.get(foNode);
     }
 
     protected PropertyList createPropertyList(PropertyList parent, FOEventHandler foEventHandler) throws FOPException {
-        propertyList = new MarkerPropertyList(this, parent);
-        return propertyList;
+        return new MarkerPropertyList(this, parent);
     }
 
     protected void startOfNode() {
@@ -95,23 +83,28 @@ public class Marker extends FObjMixed {
         foEventHandler.setPropertyListMaker(new PropertyListMaker() {
             public PropertyList make(FObj fobj, PropertyList parentPropertyList) {
                 PropertyList pList = new MarkerPropertyList(fobj, parentPropertyList);
-                children.put(fobj, pList);
+                descPLists.put(fobj, pList);
                 return pList;
             }
         });
     }
 
-    protected void addChildNode(FONode child) throws FOPException {
-        if (!children.containsKey(child)) {
-            children.put(child, propertyList);
-        }
-        super.addChildNode(child);
-    }
-
     protected void endOfNode() {
         // Pop the MarkerPropertyList maker.
         getFOEventHandler().setPropertyListMaker(savePropertyListMaker);
         savePropertyListMaker = null;
+        // unparent the child property lists
+        Iterator iter = getChildNodes();
+        if (iter != null) {
+            while (iter.hasNext()) {
+                FONode child = (FONode) iter.next();
+                MarkerPropertyList pList
+                    = (MarkerPropertyList) descPLists.get(child);
+                if (pList != null) {
+                    pList.setParentPropertyList(null);
+                }
+            }
+        }
     }
 
     /**
@@ -131,17 +124,9 @@ public class Marker extends FObjMixed {
 
     /**
      * @see org.apache.fop.fo.FONode#addLayoutManager(List)
-     * @todo remove null check when vCN() & endOfNode() implemented
      */
     public void addLayoutManager(List list) {
-        ListIterator baseIter = getChildNodes();
-        if (baseIter == null) {
-            return;
-        }
-        while (baseIter.hasNext()) {
-            FONode child = (FONode) baseIter.next();
-            child.addLayoutManager(list);
-        }
+        // no layout manager
     }
 
     /**
index 2ac17aaf1c988952db44cc31dabdb2c34a640eac..f9d5fd95b76e05d29fb311f06d68c84cdc0c3c49 100644 (file)
 
 package org.apache.fop.fo.flow;
 
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.xml.sax.Locator;
 
 import org.apache.commons.logging.Log;
@@ -25,6 +31,8 @@ import org.apache.commons.logging.Log;
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.fo.FOEventHandler;
 import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FOText;
+import org.apache.fop.fo.FObj;
 import org.apache.fop.fo.FObjMixed;
 import org.apache.fop.fo.PropertyList;
 import org.apache.fop.fo.StaticPropertyList;
@@ -72,6 +80,21 @@ public class RetrieveMarker extends FObjMixed {
             invalidChildError(loc, nsURI, localName);
     }
 
+    /**
+     * @see org.apache.fop.fo.FONode#addLayoutManager(List)
+     * @todo remove null check when vCN() & endOfNode() implemented
+     */
+    public void addLayoutManager(List list) {
+        Iterator baseIter = getChildNodes();
+        if (baseIter == null) {
+            return;
+        }
+        while (baseIter.hasNext()) {
+            FONode child = (FONode) baseIter.next();
+            child.addLayoutManager(list);
+        }
+    }
+
     protected PropertyList createPropertyList(PropertyList parent, 
             FOEventHandler foEventHandler) throws FOPException {
         // TODO: A special RetrieveMarkerPropertyList would be more memory
@@ -106,10 +129,96 @@ public class RetrieveMarker extends FObjMixed {
         return retrieveBoundary;
     }
 
+    /**
+     * Clone the FO nodes in the parent iterator,
+     * attach the new nodes to the new parent,
+     * and map the new nodes to the existing property lists.
+     * FOText nodes are also in the new map, with a null value.
+     * Clone the subtree by a recursive call to this method.
+     * @param parentIter the iterator over the children of the old parent
+     * @param newParent the new parent for the cloned nodes
+     * @param marker the marker that contains the old property list mapping
+     * @param descPLists the map of the new nodes to property lists
+     */
+    private void cloneSubtree(Iterator parentIter, FONode newParent,
+                              Marker marker, Map descPLists)
+        throws FOPException {
+        if (parentIter == null) return;
+        while (parentIter.hasNext()) {
+            FONode child = (FONode) parentIter.next();
+            FONode newChild = child.clone(newParent, true);
+            descPLists.put(newChild, marker.getPList(child));
+            cloneSubtree(child.getChildNodes(), newChild, marker, descPLists);
+        }
+    }
+
+    /**
+     * Clone the subtree of marker,
+     * attach the new subtree to this node,
+     * reparent the property lists of the direct children
+     * to the property list of this node.
+     * @param marker the marker that is to be cloned
+     * @param descPLists the map of the new nodes to property lists
+     */
+    private void cloneFromMarker(Marker marker, Map descPLists)
+        throws FOPException {
+        // release child nodes from a possible earlier layout
+        childNodes = new ArrayList();
+        Iterator markerIter = marker.getChildNodes();
+        cloneSubtree(markerIter, this, marker, descPLists);
+        // reparent the property lists of the direct children
+        for (Iterator iter = getChildNodes(); iter.hasNext(); ) {
+            FONode child = (FONode) iter.next();
+            Marker.MarkerPropertyList pList
+                = (Marker.MarkerPropertyList) descPLists.get(child);
+            if (pList != null) {
+                pList.setParentPropertyList(propertyList);
+            }
+        }
+    }
+
+    /**
+     * Bind the new nodes to the property values in this context
+     * @param descPLists the map of the new nodes to property lists
+     */
+    private void bindChildren(Map descPLists) throws FOPException {
+        for (Iterator i = descPLists.keySet().iterator(); i.hasNext(); ) {
+            FONode desc = (FONode) i.next();
+            PropertyList descPList;
+            if (desc instanceof FObj) {
+                descPList = (PropertyList) descPLists.get(desc);
+                ((FObj) desc).bind(descPList);
+            } else if (desc instanceof FOText) {
+                descPList = (PropertyList) descPLists.get(desc.getParent());
+                if (descPList == null) {
+                    descPList = propertyList;
+                }
+                ((FOText) desc).bind(descPList);
+            }
+        }
+    }
+
+    /**
+     * Clone the subtree of marker
+     * and bind the nodes to the property values in this context
+     * @param marker the marker that is to be cloned
+     */
     public void bindMarker(Marker marker) {
         // assert(marker != null);
+        // catch empty marker
+        if (marker.getChildNodes() == null) {
+            return;
+        }
+        HashMap descPLists = new HashMap();
+        try {
+            cloneFromMarker(marker, descPLists);
+        } catch (FOPException exc) {
+            Log log = getLogger();
+            log.error("fo:retrieve-marker unable to clone subtree of fo:marker", exc);
+            return;
+        }
         try {
-            marker.rebind(getPropertyList());
+            bindChildren(descPLists);
         } catch (FOPException exc) {
             Log log = getLogger();
             log.error("fo:retrieve-marker unable to rebind property values", exc);
index 8906e024e46a682b6a27f2924ac20468af1548b1..09edee56f065d7453292d0bc747856beb6ad061b 100644 (file)
@@ -382,7 +382,7 @@ public abstract class AbstractLayoutManager implements LayoutManager, Constants
                         continue;
                     }
                     rm.bindMarker(marker);
-                    foNode = marker;
+                    foNode = rm;
                 }
                 foNode.addLayoutManager(newLMs);
             }