Revision: 12786
http://sourceforge.net/p/foray/code/12786
Author: victormote
Date: 2022-12-06 01:27:53 +0000 (Tue, 06 Dec 2022)
Log Message:
-----------
Move error handling in Namespace to an interface implemented by FoTreeParser4a.
Modified Paths:
--------------
trunk/foray/foray-fotree/src/main/java/org/foray/fotree/FoTreeParser4a.java
trunk/foray/foray-fotree/src/main/java/org/foray/fotree/Namespace.java
Modified: trunk/foray/foray-fotree/src/main/java/org/foray/fotree/FoTreeParser4a.java
===================================================================
--- trunk/foray/foray-fotree/src/main/java/org/foray/fotree/FoTreeParser4a.java 2022-12-05 22:16:45 UTC (rev 12785)
+++ trunk/foray/foray-fotree/src/main/java/org/foray/fotree/FoTreeParser4a.java 2022-12-06 01:27:53 UTC (rev 12786)
@@ -52,12 +52,18 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.xml.namespace.QName;
+
/**
* SAX Handler that builds the formatting object tree.
*/
-public class FoTreeParser4a extends SaxParser<FoTree4a> implements FoTreeParser {
+public class FoTreeParser4a extends SaxParser<FoTree4a> implements FoTreeParser, Namespace.ErrorHandler {
/** The initial size of the text buffer for accumulating text. */
private static final int INITIAL_TEXT_BUFFER_SIZE = 4096;
@@ -101,6 +107,10 @@
/** The strategy to use for storing text. */
private TextStrategy textStrategy = TextStrategy.WORD;
+ /** Map whose key is a {@link Namespace} instance, and whose value is the set of elements that were parsed in that
+ * namespace that could not be converted to FO Objects. */
+ private Map<Namespace, Set<String>> invalidElementsMap = new HashMap<Namespace, Set<String>>();
+
/**
* Constructor.
* @param server The parent server.
@@ -476,4 +486,23 @@
return this;
}
+ @Override
+ public void processUnknownElement(final Namespace namespace, final String unknownElementName) {
+ Set<String> unknownElements = this.invalidElementsMap.get(namespace);
+ if (unknownElements == null) {
+ unknownElements = new HashSet<String>();
+ this.invalidElementsMap.put(namespace, unknownElements);
+ }
+ if (unknownElements.contains(unknownElementName)) {
+ /* We have already logged the error. No need to do it again. */
+ return;
+ }
+ unknownElements.add(unknownElementName);
+ final QName qname = namespace.getQname(unknownElementName);
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Unsupported element: ");
+ builder.append(qname.toString());
+ this.errorMessage(getLocator(), builder.toString());
+ }
+
}
Modified: trunk/foray/foray-fotree/src/main/java/org/foray/fotree/Namespace.java
===================================================================
--- trunk/foray/foray-fotree/src/main/java/org/foray/fotree/Namespace.java 2022-12-05 22:16:45 UTC (rev 12785)
+++ trunk/foray/foray-fotree/src/main/java/org/foray/fotree/Namespace.java 2022-12-06 01:27:53 UTC (rev 12786)
@@ -33,27 +33,27 @@
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
-import java.util.HashSet;
-import java.util.Set;
+import javax.xml.namespace.QName;
/**
- * Abstract class for handling namespaces. Subclasses should know how to
- * convert SAX element and attribute input into Objects and Properties for
- * their namespace.
+ * Abstract class for handling namespaces.
+ * Subclasses should know how to convert SAX element and attribute input into Objects and Properties for their
+ * namespace.
*/
public abstract class Namespace {
- /** The set of names of formatting objects encountered but unknown. */
- private Set<String> unknownFOs = new HashSet<String>();
+ /**
+ * Implementations (usually FO Tree parsers) receive events when the {@link Namespace} instance encounters errors.
+ */
+ public interface ErrorHandler {
- /** The number of items designated to this namespace that are unknown to
- * it. */
- private int errorCount = 0;
+ /**
+ * Process an unknown element that was encountered in this namespace.
+ * @param namespace The Namespace instance that encountered the error.
+ * @param unknownElementName The name of the unknown element encountered by {@code namespace}.
+ */
+ void processUnknownElement(Namespace namespace, String unknownElementName);
- /**
- * Constructor.
- */
- public Namespace() {
}
/**
@@ -63,8 +63,8 @@
public abstract String getNamespaceURI();
/**
- * Returns the typical prefix for this namespace, minus the ":". For
- * example, the SVG namespace should return "svg".
+ * Returns the typical prefix for this namespace, minus the ":".
+ * For example, the SVG namespace should return "svg".
* @return The typical prefix for this namespace.
*/
public abstract String getTypicalPrefix();
@@ -73,23 +73,20 @@
* Parse an element in this namespace.
* @param foTree The parent FO Tree.
* @param localName The local name of the element.
- * @param currentFObj The current FoObj, that is, the parent of the one
- * being parsed.
- * @param list The property list into which properties for the new FoObj
- * should be placed.
+ * @param currentFObj The current FoObj, that is, the parent of the one being parsed.
+ * @param list The property list into which properties for the new FoObj should be placed.
* @param locator The SAX locator.
- * @param builder The FO Tree builder.
+ * @param errorHandler Object that wants to be notified if an element unknown to this Namespace is encountered.
* @return The newly-created FoObj instance.
* @throws FoTreeException For parsing errors.
*/
- public FoObj parseElement(final FoTree4a foTree, final String localName,
- final FoObj currentFObj, final PropertyList list,
- final Locator locator,
- final FoTreeParser4a builder) throws FoTreeException {
- final FoObj fobj = parseElementForNS(foTree, localName, currentFObj,
- list, locator);
- if (fobj == null) {
- checkUnknownElement(builder, localName, locator);
+ public FoObj parseElement(final FoTree4a foTree, final String localName, final FoObj currentFObj,
+ final PropertyList list, final Locator locator, final ErrorHandler errorHandler)
+ throws FoTreeException {
+ final FoObj fobj = parseElementForNS(foTree, localName, currentFObj, list, locator);
+ if (fobj == null
+ && errorHandler != null) {
+ errorHandler.processUnknownElement(this, localName);
}
return fobj;
}
@@ -98,78 +95,18 @@
* The namespace-specific logic for parsing an element.
* @param foTree The parent FO Tree.
* @param localName The local name of the element.
- * @param currentFObj The current FoObj, that is, the parent of the one
- * being parsed.
- * @param list The property list into which properties for the new FoObj
- * should be placed.
+ * @param currentFObj The current FoObj, that is, the parent of the one being parsed.
+ * @param list The property list into which properties for the new FoObj should be placed.
* @param locator The SAX locator.
* @return The newly-created FoObj instance.
* @throws FoTreeException For parsing errors.
*/
- protected abstract FoObj parseElementForNS(FoTree4a foTree,
- String localName, FoObj currentFObj, PropertyList list,
+ protected abstract FoObj parseElementForNS(FoTree4a foTree, String localName, FoObj currentFObj, PropertyList list,
Locator locator) throws FoTreeException;
/**
- * For the first occurrence of an element that has already been established
- * as being foreign to this namespace, this method logs an error.
- * @param builder The FoTreeBuilder using this namespace.
- * @param localName The local name of the element to be checked and logged.
- * @param locator The Locator instance indicating the source of the foreign
- * element.
- */
- private void checkUnknownElement(final FoTreeParser4a builder,
- final String localName, final Locator locator) {
- if (this.unknownFOs.contains(localName)) {
- return;
- }
- this.unknownFOs.add(localName);
- final StringBuilder sb = new StringBuilder(128);
- sb.append("Unsupported element ");
- sb.append(this.getTypicalPrefix());
- sb.append(":");
- sb.append(localName);
- sb.append(". Context: ");
- if (locator != null) {
- sb.append(formatLocator(locator));
- } else {
- sb.append("unavailable");
- }
- if (this.errorCount == 0) {
- builder.errorMessage(sb.toString());
- }
- this.errorCount++;
- }
-
- /**
- * Turns a current SAX locator into a usable user message.
- * @param locator The SAX locator containing the location information.
- * @return A formatted user message.
- */
- public String formatLocator(final Locator locator) {
- if (locator == null) {
- return "";
- }
- final StringBuilder sb = new StringBuilder();
- if (locator.getSystemId() != null) {
- sb.append(locator.getSystemId());
- } else if (locator.getPublicId() != null) {
- sb.append(locator.getPublicId());
- } else {
- sb.append("Unknown source");
- }
- sb.append(" (line: ");
- sb.append(locator.getLineNumber());
- sb.append(", col: ");
- sb.append(locator.getColumnNumber());
- sb.append(")");
- return sb.toString();
- }
-
- /**
* Parse the attributes for an element in this namespace.
- * @param list The property list into which the parsed values should be
- * placed.
+ * @param list The property list into which the parsed values should be placed.
* @param attlist The unparsed SAX attributes.
* @param currentFObj The FoObj instance to whom the attributes belong.
* @param locator The SAX locator.
@@ -181,19 +118,17 @@
FoTreeParser4a builder) throws FoTreeException;
/**
- * Reads through the list of attributes and returns an array that contains
- * the order in which they should be processed. The routine currently
- * sorts the attributes alphabetically. The purpose of this is to ensure
- * that any short forms of compound properties are processed before their
- * completer forms are processed. For example, downstream processing is
- * simplified if we know that property "leader-length" was processed before
+ * Reads through the list of attributes and returns an array that contains the order in which they should be
+ * processed.
+ * The routine currently sorts the attributes alphabetically.
+ * The purpose of this is to ensure that any short forms of compound properties are processed before their more
+ * complete forms are processed.
+ * For example, downstream processing is simplified if we know that property "leader-length" was processed before
* property "leader-length.minimum".
- * @param attlist The Attributes instance that contains the attributes to
- * be sorted
- * @return An int array containing the order in which the attributes should
- * be processed. If element 0 contains an 8 and element 1 contains a 3,
- * then element 8 of Attributes should be processed first, and element 3
- * should be processed second.
+ * @param attlist The Attributes instance that contains the attributes to be sorted
+ * @return An int array containing the order in which the attributes should be processed.
+ * If element 0 contains an 8 and element 1 contains a 3, then element 8 of Attributes should be processed first,
+ * and element 3 should be processed second.
*/
protected int[] sortAttributes(final Attributes attlist) {
final int[] sorted = new int[attlist.getLength()];
@@ -206,14 +141,11 @@
while (numChanges > 0) {
numChanges = 0;
// Read through each item
- for (int sortedIndex = 0; sortedIndex < sorted.length - 1;
- sortedIndex++) {
+ for (int sortedIndex = 0; sortedIndex < sorted.length - 1; sortedIndex++) {
// Compare the two local names
// TODO: This might need to handle namespaces.
- final String localName1 = attlist.getLocalName(
- sorted[sortedIndex]);
- final String localName2 = attlist.getLocalName(
- sorted[sortedIndex + 1]);
+ final String localName1 = attlist.getLocalName(sorted[sortedIndex]);
+ final String localName2 = attlist.getLocalName(sorted[sortedIndex + 1]);
/*
* If i's local name is greater than i + 1's, switch their
* pointers.
@@ -240,12 +172,9 @@
* @return The parsed property.
* @throws PropertyException For errors during parsing.
*/
- public Property parseAttribute(final Attributes attributes,
- final String attributeName, final String attributeValue,
- final FoObj fobj, final Locator locator,
- final FoTreeParser4a builder) throws PropertyException {
- final Property property = parseAttributeForNS(attributes, attributeName,
- attributeValue, fobj, locator);
+ public Property parseAttribute(final Attributes attributes, final String attributeName, final String attributeValue,
+ final FoObj fobj, final Locator locator, final FoTreeParser4a builder) throws PropertyException {
+ final Property property = parseAttributeForNS(attributes, attributeName, attributeValue, fobj, locator);
return property;
}
@@ -259,28 +188,22 @@
* @return The parsed property.
* @throws PropertyException For errors during parsing.
*/
- public abstract Property parseAttributeForNS(Attributes attributes,
- String attributeName, String attributeValue, FoObj fobj,
- Locator locator) throws PropertyException;
+ public abstract Property parseAttributeForNS(Attributes attributes, String attributeName, String attributeValue,
+ FoObj fobj, Locator locator) throws PropertyException;
/**
- * Parses the attributes for an object in a pre-specified order, building
- * the PropertyList from them.
- * @param propertyList The property list into which the parsed values should
- * be placed.
+ * Parses the attributes for an object in a pre-specified order, building the PropertyList from them.
+ * @param propertyList The property list into which the parsed values should be placed.
* @param attributes The unparsed SAX attributes.
* @param parentFO The parent FO.
- * @param attributeSort The order in which the various attributes should be
- * parsed, so that compound values are handled properly.
+ * @param attributeSort The order in which the various attributes should be parsed, so that compound values are
+ * handled properly.
* @param locator The SAX locator.
* @param builder The FO Tree builder.
* @throws PropertyException For errors during parsing.
*/
- protected void makeList(final PropertyList propertyList,
- final Attributes attributes, final FoObj parentFO,
- final int[] attributeSort, final Locator locator,
- final FoTreeParser4a builder) throws PropertyException {
-
+ protected void makeList(final PropertyList propertyList, final Attributes attributes, final FoObj parentFO,
+ final int[] attributeSort, final Locator locator, final FoTreeParser4a builder) throws PropertyException {
for (int j = 0; j < attributeSort.length; j++) {
/* We are reading through the attributes elements in attributeSort
* order. */
@@ -310,11 +233,9 @@
namespace = treeServer.getNamespace(namespaceURI);
}
if (namespace == null) {
- throw new PropertyException("Unknown namespace: "
- + namespaceURI);
+ throw new PropertyException("Unknown namespace: " + namespaceURI);
}
- final Property property = namespace.parseAttribute(attributes,
- localName, attributeValue, parentFO, locator,
+ final Property property = namespace.parseAttribute(attributes, localName, attributeValue, parentFO, locator,
builder);
if (property != null) {
propertyList.addProperty(parentFO, property);
@@ -323,19 +244,19 @@
}
/**
- * Resets the error count for this namespace.
+ * Return a newly-created appropriate PropertyList for this namespace.
+ * @param attlist The attributes that will become the properties in the list.
+ * @return The newly-created property list.
*/
- public void reset() {
- this.errorCount = 0;
- }
+ protected abstract PropertyList createNewPropertyList(Attributes attlist);
/**
- * Return a newly-created appropriate PropertyList for this namespace.
- * @param attlist The attributes that will become the properties in the
- * list.
- * @return The newly-created property list.
+ * Returns a fully-qualified name for a given element in this namespace.
+ * @param elementName The name of the element for which a QName is needed.
+ * @return The QName for {@code elementName} in this namespace.
*/
- protected abstract PropertyList createNewPropertyList(
- Attributes attlist);
+ public QName getQname(final String elementName) {
+ return new QName(this.getNamespaceURI(), elementName);
+ }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|