- delegate validation of the fo:wrapper's children to the parent: added static FONode.validateChildNode() - narrow the condition for processing text-childnodes: this is not only constrained to fo:flow and fo:static-content, but the same goes for a fo:wrapper that is a direct descendant of a fo:block-container or fo:inline-container, which only allow block-level content (interpretation) - minor javadoc fixups/improvements git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@604678 13f79535-47bb-0310-9956-ffa450edef68tags/fop-0_95beta
@@ -45,6 +45,7 @@ public abstract class FONode implements Cloneable { | |||
/** the XSL-FO namespace URI */ | |||
protected static final String FO_URI = FOElementMapping.URI; | |||
/** FOP's proprietary extension namespace URI */ | |||
protected static final String FOX_URI = ExtensionElementMapping.URI; | |||
/** Parent FO node */ | |||
@@ -197,11 +198,13 @@ public abstract class FONode implements Cloneable { | |||
/** | |||
* Checks to make sure, during SAX processing of input document, that the | |||
* incoming node is valid for the this (parent) node (e.g., checking to | |||
* see that fo:table is not an immediate child of fo:root) | |||
* called within FObj constructor | |||
* see that <code>fo:table</code> is not an immediate child of <code>fo:root</code>) | |||
* called from {@link FOTreeBuilder#startElement(String, String, String, Attributes)} | |||
* before constructing the child {@link FObj}. | |||
* | |||
* @param loc location in the FO source file | |||
* @param namespaceURI namespace of incoming node | |||
* @param localName (e.g. "table" for "fo:table") | |||
* @param localName name of the incoming node (without namespace prefix) | |||
* @throws ValidationException if incoming node not valid for parent | |||
*/ | |||
protected void validateChildNode(Locator loc, String namespaceURI, String localName) | |||
@@ -209,6 +212,27 @@ public abstract class FONode implements Cloneable { | |||
//nop | |||
} | |||
/** | |||
* Static version of {@link FONode#validateChildNode(Locator, String, String)} that | |||
* can be used by subclasses that need to validate children against a different node | |||
* (for example: <code>fo:wrapper</code> needs to check if the incoming node is a | |||
* valid child to its parent) | |||
* | |||
* @param fo the FONode to validate against | |||
* @param loc location in the source file | |||
* @param namespaceURI namespace of the incoming node | |||
* @param localName name of the incoming node (without namespace prefix) | |||
* @throws ValidationException if the incoming node is not a valid child for the given FO | |||
*/ | |||
protected static void validateChildNode( | |||
FONode fo, | |||
Locator loc, | |||
String namespaceURI, | |||
String localName) | |||
throws ValidationException { | |||
fo.validateChildNode(loc, namespaceURI, localName); | |||
} | |||
/** | |||
* Adds characters (does nothing here) | |||
* @param data array of characters containing text to be added | |||
@@ -572,8 +596,8 @@ public abstract class FONode implements Cloneable { | |||
} | |||
/** | |||
* Returns the Constants class integer value of this node | |||
* @return the integer enumeration of this FO (e.g., FO_ROOT) | |||
* Returns the {@link Constants} class integer value of this node | |||
* @return the integer enumeration of this FO (e.g. FO_ROOT) | |||
* if a formatting object, FO_UNKNOWN_NODE otherwise | |||
*/ | |||
public int getNameId() { | |||
@@ -632,6 +656,14 @@ public abstract class FONode implements Cloneable { | |||
} | |||
} | |||
/** | |||
* This method is used when adding child nodes to a FO that already | |||
* contains at least one child. In this case, the new child becomes a | |||
* sibling to the previous one | |||
* | |||
* @param precedingSibling the previous child | |||
* @param followingSibling the new child | |||
*/ | |||
protected static void attachSiblings(FONode precedingSibling, | |||
FONode followingSibling) { | |||
if (precedingSibling.siblings == null) { | |||
@@ -688,7 +720,7 @@ public abstract class FONode implements Cloneable { | |||
* @return the last node in the list | |||
* @throws NoSuchElementException if the list is empty | |||
*/ | |||
public FONode lastNode(); | |||
public FONode lastNode(); | |||
} | |||
} |
@@ -38,49 +38,43 @@ public class Wrapper extends FObjMixed { | |||
// used for FO validation | |||
private boolean blockOrInlineItemFound = false; | |||
private boolean isFlowChild = false; | |||
private boolean inlineChildrenAllowed = false; | |||
/** | |||
* @param parent FONode that is the parent of this object | |||
*/ | |||
public Wrapper(FONode parent) { | |||
super(parent); | |||
/* Check if the fo:wrapper is a child of an fo:flow or fo:static-content | |||
/* Check if the fo:wrapper is a child of a FO that allows mixed content | |||
* (or a descendant in nested fo:wrapper sequence, the first of which | |||
* is a child of an fo:flow or fo:static-content */ | |||
* is a child of a FO that allows mixed content) */ | |||
FONode ancestor = this.parent; | |||
while (!(ancestor instanceof Flow) | |||
&& ancestor instanceof Wrapper) { | |||
while (ancestor instanceof Wrapper) { | |||
ancestor = ancestor.getParent(); | |||
} | |||
if (ancestor instanceof Flow) { | |||
this.isFlowChild = true; | |||
if (ancestor instanceof FObjMixed ) { | |||
inlineChildrenAllowed = true; | |||
} | |||
} | |||
/** | |||
* {@inheritDoc} | |||
* XSL Content Model: marker* (#PCDATA|%inline;|%block;)* | |||
* Additionally (unimplemented): "An fo:wrapper that is a child of an | |||
* <br>XSL Content Model: marker* (#PCDATA|%inline;|%block;)* | |||
* <br><i>Additionally (unimplemented): "An fo:wrapper that is a child of an | |||
* fo:multi-properties is only permitted to have children that would | |||
* be permitted in place of the fo:multi-properties." | |||
* be permitted in place of the fo:multi-properties."</i> | |||
* | |||
*/ | |||
protected void validateChildNode(Locator loc, String nsURI, String localName) | |||
throws ValidationException { | |||
if (FO_URI.equals(nsURI) && localName.equals("marker")) { | |||
if (FO_URI.equals(nsURI) && "marker".equals(localName)) { | |||
if (blockOrInlineItemFound) { | |||
nodesOutOfOrderError(loc, "fo:marker", | |||
"(#PCDATA|%inline;|%block;)"); | |||
} | |||
} else if (isBlockOrInlineItem(nsURI, localName)) { | |||
if (isFlowChild | |||
&& isInlineItem(nsURI, localName) | |||
&& !isNeutralItem(nsURI, localName)) { | |||
invalidChildError(loc, nsURI, localName, | |||
"fo:" + localName + " not allowed as child of an fo:wrapper " | |||
+ "that is a child of an fo:flow or fo:static-content"); | |||
} | |||
//delegate validation to parent | |||
FONode.validateChildNode(this.parent, loc, nsURI, localName); | |||
blockOrInlineItemFound = true; | |||
} else { | |||
invalidChildError(loc, nsURI, localName); | |||
@@ -94,9 +88,8 @@ public class Wrapper extends FObjMixed { | |||
int end, | |||
PropertyList pList, | |||
Locator locator) throws FOPException { | |||
/* Only add text if the fo:wrapper is not a child of an fo:flow | |||
* or fo:static-content */ | |||
if (!this.isFlowChild) { | |||
/* Only add text if the fo:wrapper's parent allows inline children */ | |||
if (this.inlineChildrenAllowed) { | |||
super.addCharacters(data, start, end, pList, locator); | |||
} | |||
} |