blob: 51ae7441dfc0380070821ebc5163f3adbda712a6 [file] [log] [blame]
/*
* 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.fo.flow;
import java.util.Iterator;
import org.xml.sax.Locator;
import org.apache.fop.apps.FOPException;
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.ValidationException;
import org.apache.fop.fo.XMLObj;
import org.apache.fop.fo.flow.table.Table;
/**
* Abstract base class for the <a href="http://www.w3.org/TR/xsl/#fo_retrieve-marker">
* <code>fo:retrieve-marker</code></a> and
* <a href="http://www.w3.org/TR/xsl/#fo_retrieve-table-marker">
* <code>fo:retrieve-table-marker</code></a> formatting objects.
*/
public abstract class AbstractRetrieveMarker extends FObjMixed {
private PropertyList propertyList;
private String retrieveClassName;
/**
* Create a new AbstractRetrieveMarker instance that
* is a child of the given {@link FONode}
*
* @param parent the parent {@link FONode}
*/
public AbstractRetrieveMarker(FONode parent) {
super(parent);
}
/**
* {@inheritDoc}
* <p>XSL Content Model: empty
*/
protected void validateChildNode(Locator loc, String nsURI, String localName)
throws ValidationException {
if (FO_URI.equals(nsURI)) {
invalidChildError(loc, nsURI, localName);
}
}
/**
* {@inheritDoc}
* Store a reference to the parent {@link PropertyList}
* to be used when the retrieve-marker is resolved.
*/
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
this.retrieveClassName = pList.get(PR_RETRIEVE_CLASS_NAME).getString();
if (retrieveClassName == null || retrieveClassName.equals("")) {
missingPropertyError("retrieve-class-name");
}
this.propertyList = pList.getParentPropertyList();
}
private PropertyList createPropertyListFor(FObj fo, PropertyList parent) {
return getBuilderContext().getPropertyListMaker().make(fo, parent);
}
private void cloneSingleNode(FONode child, FONode newParent,
Marker marker, PropertyList parentPropertyList)
throws FOPException {
if (child != null) {
FONode newChild = child.clone(newParent, true);
if (child instanceof FObj) {
Marker.MarkerPropertyList pList;
PropertyList newPropertyList = createPropertyListFor(
(FObj) newChild, parentPropertyList);
pList = marker.getPropertyListFor(child);
newChild.processNode(
child.getLocalName(),
getLocator(),
pList,
newPropertyList);
addChildTo(newChild, newParent);
if (newChild.getNameId() == FO_TABLE) {
Table t = (Table) child;
cloneSubtree(t.getColumns().iterator(),
newChild, marker, newPropertyList);
cloneSingleNode(t.getTableHeader(),
newChild, marker, newPropertyList);
cloneSingleNode(t.getTableFooter(),
newChild, marker, newPropertyList);
}
cloneSubtree(child.getChildNodes(), newChild,
marker, newPropertyList);
} else if (child instanceof FOText) {
FOText ft = (FOText) newChild;
ft.bind(parentPropertyList);
addChildTo(newChild, newParent);
} else if (child instanceof XMLObj) {
addChildTo(newChild, newParent);
}
// trigger end-of-node white-space handling
// and finalization for table-FOs
newChild.finalizeNode();
}
}
/**
* 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 parentPropertyList the parent PropertyList
* @throws FOPException in case there was an error
*/
private void cloneSubtree(Iterator parentIter, FONode newParent,
Marker marker, PropertyList parentPropertyList)
throws FOPException {
if (parentIter != null) {
FONode child;
while (parentIter.hasNext()) {
child = (FONode) parentIter.next();
cloneSingleNode(child, newParent,
marker, parentPropertyList);
}
}
}
private void cloneFromMarker(Marker marker)
throws FOPException {
cloneSubtree(marker.getChildNodes(), this,
marker, propertyList);
handleWhiteSpaceFor(this, null);
}
/**
* Clone the subtree of the given marker
*
* @param marker the marker that is to be cloned
*/
public void bindMarker(Marker marker) {
// clean up remnants from a possible earlier layout
if (firstChild != null) {
currentTextNode = null;
firstChild = null;
}
if (marker.getChildNodes() != null) {
try {
cloneFromMarker(marker);
} catch (FOPException exc) {
getFOValidationEventProducer().markerCloningFailed(this,
marker.getMarkerClassName(), exc, getLocator());
}
} else if (log.isDebugEnabled()) {
log.debug("Empty marker retrieved...");
}
}
/**
* Return the value for the <code>retrieve-class-name</code>
* property
*
* @return the value for retrieve-class-name
*/
public String getRetrieveClassName() {
return this.retrieveClassName;
}
}