123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- /*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed 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;
-
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.ListIterator;
- import java.util.Map;
- import java.util.Set;
-
- import org.apache.fop.fo.flow.Marker;
- import org.apache.fop.fo.properties.PropertyMaker;
-
- import org.xml.sax.Attributes;
- import org.xml.sax.Locator;
- import org.xml.sax.SAXParseException;
-
- /**
- * Base class for representation of formatting objects and their processing.
- */
- public class FObj extends FONode implements Constants {
- public static PropertyMaker[] propertyListTable = null;
-
- /** The immediate child nodes of this node. */
- public ArrayList childNodes = null;
-
- /** Used to indicate if this FO is either an Out Of Line FO (see rec)
- or a descendant of one. Used during validateChildNode() FO
- validation.
- */
- private boolean isOutOfLineFODescendant = false;
-
- /** Markers added to this element. */
- protected Map markers = null;
-
- /** Dynamic layout dimension. Used to resolve relative lengths. */
- protected Map layoutDimension = null;
-
- /**
- * Create a new formatting object.
- * All formatting object classes extend this class.
- *
- * @param parent the parent node
- * @todo move propertyListTable initialization someplace else?
- */
- public FObj(FONode parent) {
- super(parent);
-
- // determine if isOutOfLineFODescendant should be set
- if (parent != null && parent instanceof FObj) {
- if (((FObj)parent).getIsOutOfLineFODescendant() == true) {
- isOutOfLineFODescendant = true;
- } else {
- int foID = getNameId();
- if (foID == FO_FLOAT || foID == FO_FOOTNOTE
- || foID == FO_FOOTNOTE_BODY) {
- isOutOfLineFODescendant = true;
- }
- }
- }
-
- if (propertyListTable == null) {
- propertyListTable = new PropertyMaker[Constants.PROPERTY_COUNT+1];
- PropertyMaker[] list = FOPropertyMapping.getGenericMappings();
- for (int i = 1; i < list.length; i++) {
- if (list[i] != null)
- propertyListTable[i] = list[i];
- }
- }
- }
-
- /**
- * @see org.apache.fop.fo.FONode#processNode
- */
- public void processNode(String elementName, Locator locator,
- Attributes attlist, PropertyList pList) throws SAXParseException {
- setLocator(locator);
- pList.addAttributesToList(attlist);
- pList.setWritingMode();
- bind(pList);
- }
-
- /**
- * Create a default property list for this element.
- */
- protected PropertyList createPropertyList(PropertyList parent, FOEventHandler foEventHandler) throws SAXParseException {
- return foEventHandler.getPropertyListMaker().make(this, parent);
- }
-
- /**
- * Bind property values from the property list to the FO node.
- * Must be overriden in all FObj subclasses.
- * @param pList the PropertyList where the properties can be found.
- * @throws SAXParseException
- */
- public void bind(PropertyList pList) throws SAXParseException {
- // throw new SAXParseException("Unconverted element " + this, locator);
- }
-
- /**
- * Setup the id for this formatting object.
- * Most formatting objects can have an id that can be referenced.
- * This methods checks that the id isn't already used by another
- * fo and sets the id attribute of this object.
- */
- protected void checkId(String id) throws SAXParseException {
- if (!id.equals("")) {
- Set idrefs = getFOEventHandler().getIDReferences();
- if (!idrefs.contains(id)) {
- idrefs.add(id);
- } else {
- throw new SAXParseException("Property id \"" + id +
- "\" previously used; id values must be unique" +
- " in document.", locator);
- }
- }
- }
-
- /**
- * Returns Out Of Line FO Descendant indicator.
- * @return true if Out of Line FO or Out Of Line descendant, false otherwise
- */
- public boolean getIsOutOfLineFODescendant() {
- return isOutOfLineFODescendant;
- }
-
- /**
- * @see org.apache.fop.fo.FONode#addChildNode(FONode)
- */
- protected void addChildNode(FONode child) throws SAXParseException {
- if (PropertySets.canHaveMarkers(getNameId()) &&
- child.getNameId() == FO_MARKER) {
- addMarker((Marker) child);
- } else {
- if (childNodes == null) {
- childNodes = new ArrayList();
- }
- childNodes.add(child);
- }
- }
-
- /**
- * Find the nearest parent, grandparent, etc. FONode that is also an FObj
- * @return FObj the nearest ancestor FONode that is an FObj
- */
- public FObj findNearestAncestorFObj() {
- FONode par = parent;
- while (par != null && !(par instanceof FObj)) {
- par = par.parent;
- }
- return (FObj) par;
- }
-
- /* This section is the implemenation of the property context. */
-
- /**
- * Assign the size of a layout dimension to the key.
- * @param key the Layout dimension, from PercentBase.
- * @param dimension The layout length.
- */
- public void setLayoutDimension(Integer key, int dimension) {
- if (layoutDimension == null){
- layoutDimension = new HashMap();
- }
- layoutDimension.put(key, new Integer(dimension));
- }
-
- /**
- * Assign the size of a layout dimension to the key.
- * @param key the Layout dimension, from PercentBase.
- * @param dimension The layout length.
- */
- public void setLayoutDimension(Integer key, float dimension) {
- if (layoutDimension == null){
- layoutDimension = new HashMap();
- }
- layoutDimension.put(key, new Float(dimension));
- }
-
- /**
- * Return the size associated with the key.
- * @param key The layout dimension key.
- * @return the length.
- */
- public Number getLayoutDimension(Integer key) {
- if (layoutDimension != null) {
- Number result = (Number) layoutDimension.get(key);
- if (result != null) {
- return result;
- }
- }
- if (parent != null) {
- return ((FObj) parent).getLayoutDimension(key);
- }
- return new Integer(0);
- }
-
- /**
- * Check if this formatting object generates reference areas.
- * @return true if generates reference areas
- * @todo see if needed
- */
- public boolean generatesReferenceAreas() {
- return false;
- }
-
- /**
- * @see org.apache.fop.fo.FONode#getChildNodes()
- */
- public ListIterator getChildNodes() {
- if (childNodes != null) {
- return childNodes.listIterator();
- }
- return null;
- }
-
- /**
- * Return an iterator over the object's childNodes starting
- * at the passed-in node.
- * @param childNode First node in the iterator
- * @return A ListIterator or null if childNode isn't a child of
- * this FObj.
- */
- public ListIterator getChildNodes(FONode childNode) {
- if (childNodes != null) {
- int i = childNodes.indexOf(childNode);
- if (i >= 0) {
- return childNodes.listIterator(i);
- }
- }
- return null;
- }
-
- /**
- * Add the marker to this formatting object.
- * If this object can contain markers it checks that the marker
- * has a unique class-name for this object and that it is
- * the first child.
- * @param marker Marker to add.
- */
- protected void addMarker(Marker marker) {
- String mcname = marker.getMarkerClassName();
- if (childNodes != null) {
- // check for empty childNodes
- for (Iterator iter = childNodes.iterator(); iter.hasNext();) {
- FONode node = (FONode)iter.next();
- if (node instanceof FOText) {
- FOText text = (FOText)node;
- if (text.willCreateArea()) {
- getLogger().error("fo:marker must be an initial child: " + mcname);
- return;
- } else {
- iter.remove();
- }
- } else {
- getLogger().error("fo:marker must be an initial child: " + mcname);
- return;
- }
- }
- }
- if (markers == null) {
- markers = new HashMap();
- }
- if (!markers.containsKey(mcname)) {
- markers.put(mcname, marker);
- } else {
- getLogger().error("fo:marker 'marker-class-name' "
- + "must be unique for same parent: " + mcname);
- }
- }
-
- /**
- * @return true if there are any Markers attached to this object
- */
- public boolean hasMarkers() {
- return markers != null && !markers.isEmpty();
- }
-
- /**
- * @return th collection of Markers attached to this object
- */
- public Map getMarkers() {
- return markers;
- }
-
- /*
- * Return a string representation of the fo element.
- * Deactivated in order to see precise ID of each fo element created
- * (helpful for debugging)
- */
- /* public String toString() {
- return getName() + " at line " + line + ":" + column;
- }
- */
-
- /**
- * Convenience method for validity checking. Checks if the
- * incoming node is a member of the "%block;" parameter entity
- * as defined in Sect. 6.2 of the XSL 1.0 & 1.1 Recommendations
- * @param nsURI namespace URI of incoming node
- * @param lName local name (i.e., no prefix) of incoming node
- * @return true if a member, false if not
- */
- protected boolean isBlockItem(String nsURI, String lName) {
- return (nsURI == FO_URI &&
- (lName.equals("block")
- || lName.equals("table")
- || lName.equals("table-and-caption")
- || lName.equals("block-container")
- || lName.equals("list-block")
- || lName.equals("float")
- || isNeutralItem(nsURI, lName)));
- }
-
- /**
- * Convenience method for validity checking. Checks if the
- * incoming node is a member of the "%inline;" parameter entity
- * as defined in Sect. 6.2 of the XSL 1.0 & 1.1 Recommendations
- * @param nsURI namespace URI of incoming node
- * @param lName local name (i.e., no prefix) of incoming node
- * @return true if a member, false if not
- */
- protected boolean isInlineItem(String nsURI, String lName) {
- return (nsURI == FO_URI &&
- (lName.equals("bidi-override")
- || lName.equals("character")
- || lName.equals("external-graphic")
- || lName.equals("instream-foreign-object")
- || lName.equals("inline")
- || lName.equals("inline-container")
- || lName.equals("leader")
- || lName.equals("page-number")
- || lName.equals("page-number-citation")
- || lName.equals("basic-link")
- || (lName.equals("multi-toggle")
- && (getNameId() == FO_MULTI_CASE || findAncestor(FO_MULTI_CASE) > 0))
- || (lName.equals("footnote") && !isOutOfLineFODescendant)
- || isNeutralItem(nsURI, lName)));
- }
-
- /**
- * Convenience method for validity checking. Checks if the
- * incoming node is a member of the "%block;" parameter entity
- * or "%inline;" parameter entity
- * @param nsURI namespace URI of incoming node
- * @param lName local name (i.e., no prefix) of incoming node
- * @return true if a member, false if not
- */
- protected boolean isBlockOrInlineItem(String nsURI, String lName) {
- return (isBlockItem(nsURI, lName) || isInlineItem(nsURI, lName));
- }
-
- /**
- * Convenience method for validity checking. Checks if the
- * incoming node is a member of the neutral item list
- * as defined in Sect. 6.2 of the XSL 1.0 & 1.1 Recommendations
- * @param nsURI namespace URI of incoming node
- * @param lName local name (i.e., no prefix) of incoming node
- * @return true if a member, false if not
- */
- protected boolean isNeutralItem(String nsURI, String lName) {
- return (nsURI == FO_URI &&
- (lName.equals("multi-switch")
- || lName.equals("multi-properties")
- || lName.equals("wrapper")
- || (!isOutOfLineFODescendant && lName.equals("float"))
- || lName.equals("retrieve-marker")));
- }
-
- /**
- * Convenience method for validity checking. Checks if the
- * current node has an ancestor of a given name.
- * @param ancestorID -- Constants ID of node name to check for (e.g., FO_ROOT)
- * @return number of levels above FO where ancestor exists,
- * -1 if not found
- */
- protected int findAncestor(int ancestorID) {
- int found = 1;
- FONode temp = getParent();
- while (temp != null) {
- if (temp.getNameId() == ancestorID) {
- return found;
- }
- found += 1;
- temp = temp.getParent();
- }
- return -1;
- }
- }
|