001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: RetrieveMarker.java 554104 2007-07-07 01:07:10Z adelmelle $ */
019:
020: package org.apache.fop.fo.flow;
021:
022: import java.util.Iterator;
023:
024: import org.apache.fop.apps.FOPException;
025: import org.apache.fop.fo.FONode;
026: import org.apache.fop.fo.FObj;
027: import org.apache.fop.fo.FObjMixed;
028: import org.apache.fop.fo.FOText;
029: import org.apache.fop.fo.PropertyList;
030: import org.apache.fop.fo.ValidationException;
031: import org.xml.sax.Locator;
032:
033: /**
034: * The retrieve-marker formatting object.
035: * This will create a layout manager that will retrieve
036: * a marker based on the information.
037: */
038: public class RetrieveMarker extends FObjMixed {
039: // The value of properties relevant for fo:retrieve-marker.
040: private String retrieveClassName;
041: private int retrievePosition;
042: private int retrieveBoundary;
043: // End of property values
044:
045: private PropertyList propertyList;
046:
047: /**
048: * Create a retrieve marker object.
049: *
050: * @see org.apache.fop.fo.FONode#FONode(FONode)
051: */
052: public RetrieveMarker(FONode parent) {
053: super (parent);
054: }
055:
056: /**
057: * @see org.apache.fop.fo.FObj#bind(PropertyList)
058: */
059: public void bind(PropertyList pList) throws FOPException {
060: if (findAncestor(FO_STATIC_CONTENT) < 0) {
061: invalidChildError(locator, FO_URI, "retrieve-marker",
062: "An fo:retrieve-marker is permitted only as the "
063: + " descendant of an fo:static-content.");
064: }
065:
066: retrieveClassName = pList.get(PR_RETRIEVE_CLASS_NAME)
067: .getString();
068: retrievePosition = pList.get(PR_RETRIEVE_POSITION).getEnum();
069: retrieveBoundary = pList.get(PR_RETRIEVE_BOUNDARY).getEnum();
070:
071: if (retrieveClassName == null || retrieveClassName.equals("")) {
072: missingPropertyError("retrieve-class-name");
073: }
074:
075: propertyList = pList.getParentPropertyList();
076: }
077:
078: /**
079: * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
080: * XSL Content Model: empty
081: */
082: protected void validateChildNode(Locator loc, String nsURI,
083: String localName) throws ValidationException {
084: invalidChildError(loc, nsURI, localName);
085: }
086:
087: /**
088: * @return the "retrieve-class-name" property.
089: */
090: public String getRetrieveClassName() {
091: return retrieveClassName;
092: }
093:
094: /**
095: * @return the "retrieve-position" property (enum value).
096: */
097: public int getRetrievePosition() {
098: return retrievePosition;
099: }
100:
101: /**
102: * @return the "retrieve-boundary" property (enum value).
103: */
104: public int getRetrieveBoundary() {
105: return retrieveBoundary;
106: }
107:
108: private PropertyList createPropertyListFor(FObj fo,
109: PropertyList parent) {
110: return getFOEventHandler().getPropertyListMaker().make(fo,
111: parent);
112: }
113:
114: private void cloneSingleNode(FONode child, FONode newParent,
115: Marker marker, PropertyList parentPropertyList)
116: throws FOPException {
117:
118: if (child != null) {
119: FONode newChild = child.clone(newParent, true);
120: if (child instanceof FObj) {
121: Marker.MarkerPropertyList pList;
122: PropertyList newPropertyList = createPropertyListFor(
123: (FObj) newChild, parentPropertyList);
124:
125: pList = marker.getPropertyListFor(child);
126: newChild.processNode(child.getLocalName(),
127: getLocator(), pList, newPropertyList);
128: if (newChild.getNameId() == FO_TABLE) {
129: Table t = (Table) child;
130: cloneSubtree(t.getColumns().listIterator(),
131: newChild, marker, newPropertyList);
132: cloneSingleNode(t.getTableHeader(), newChild,
133: marker, newPropertyList);
134: cloneSingleNode(t.getTableFooter(), newChild,
135: marker, newPropertyList);
136: }
137: cloneSubtree(child.getChildNodes(), newChild, marker,
138: newPropertyList);
139: } else if (child instanceof FOText) {
140: FOText ft = (FOText) newChild;
141: ft.bind(parentPropertyList);
142: }
143: addChildTo(newChild, (FObj) newParent);
144: if (newChild instanceof FObjMixed) {
145: handleWhiteSpaceFor((FObjMixed) newChild);
146: }
147: }
148: }
149:
150: /**
151: * Clone the FO nodes in the parent iterator,
152: * attach the new nodes to the new parent,
153: * and map the new nodes to the existing property lists.
154: * FOText nodes are also in the new map, with a null value.
155: * Clone the subtree by a recursive call to this method.
156: * @param parentIter the iterator over the children of the old parent
157: * @param newParent the new parent for the cloned nodes
158: * @param marker the marker that contains the old property list mapping
159: * @param descPLists the map of the new nodes to property lists
160: */
161: private void cloneSubtree(Iterator parentIter, FONode newParent,
162: Marker marker, PropertyList parentPropertyList)
163: throws FOPException {
164: if (parentIter != null) {
165: FONode child;
166: while (parentIter.hasNext()) {
167: child = (FONode) parentIter.next();
168: cloneSingleNode(child, newParent, marker,
169: parentPropertyList);
170: }
171: }
172: }
173:
174: private void cloneFromMarker(Marker marker) throws FOPException {
175: // clean up remnants from a possible earlier layout
176: if (firstChild != null) {
177: currentTextNode = null;
178: firstChild = null;
179: }
180: cloneSubtree(marker.getChildNodes(), this , marker, propertyList);
181: }
182:
183: /**
184: * Clone the subtree of the given marker
185: *
186: * @param marker the marker that is to be cloned
187: */
188: public void bindMarker(Marker marker) {
189: if (marker.getChildNodes() != null) {
190: try {
191: cloneFromMarker(marker);
192: } catch (FOPException exc) {
193: log.error("fo:retrieve-marker unable to clone "
194: + "subtree of fo:marker (marker-class-name="
195: + marker.getMarkerClassName() + ")", exc);
196: return;
197: }
198: } else if (log.isInfoEnabled()) {
199: log.info("Empty marker retrieved...");
200: }
201: return;
202: }
203:
204: /** @see org.apache.fop.fo.FONode#getLocalName() */
205: public String getLocalName() {
206: return "retrieve-marker";
207: }
208:
209: /**
210: * @see org.apache.fop.fo.FObj#getNameId()
211: */
212: public int getNameId() {
213: return FO_RETRIEVE_MARKER;
214: }
215: }
|