Browse Source

Implemented cloning and reparenting of the subtree under a marker to

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
tags/Root_Temp_KnuthStylePageBreaking
Simon Pepping 19 years ago
parent
commit
d5d34b4c18

+ 29
- 1
src/java/org/apache/fop/fo/FONode.java View 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

+ 12
- 0
src/java/org/apache/fop/fo/FObj.java View 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
*/

+ 21
- 36
src/java/org/apache/fop/fo/flow/Marker.java View 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
}

/**

+ 110
- 1
src/java/org/apache/fop/fo/flow/RetrieveMarker.java View File

@@ -18,6 +18,12 @@

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);

+ 1
- 1
src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java View File

@@ -382,7 +382,7 @@ public abstract class AbstractLayoutManager implements LayoutManager, Constants
continue;
}
rm.bindMarker(marker);
foNode = marker;
foNode = rm;
}
foNode.addLayoutManager(newLMs);
}

Loading…
Cancel
Save