You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by sk...@apache.org on 2005/02/04 02:51:54 UTC

svn commit: r151287 [3/7] - in jakarta/commons/proper/digester/branches/digester2: ./ src/ src/conf/ src/examples/ src/examples/api/ src/examples/api/addressbook/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/commons/ src/java/org/apache/commons/digester2/ src/java/org/apache/commons/digester2/actions/ src/java/org/apache/commons/digester2/factory/ src/media/ src/test/ src/test/org/ src/test/org/apache/ src/test/org/apache/commons/ src/test/org/apache/commons/digester2/ xdocs/ xdocs/dtds/ xdocs/images/ xdocs/style/

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/Digester.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/Digester.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/Digester.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/Digester.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,688 @@
+/* $Id: $
+ *
+ * Copyright 2001-2005 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.
+ */
+
+package org.apache.commons.digester2;
+
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.xml.sax.SAXException;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+
+/**
+ * <p>A <strong>Digester</strong> processes an XML input stream by matching a
+ * series of element nesting patterns to execute Actions that have been added
+ * prior to the start of parsing.</p>
+ *
+ * <p>This class is the one that users interact with to configure the
+ * parsing rules and initiate the parse. It is mostly just a user-friendly
+ * facade over the SAXHandler class.</p>
+ *
+ * <p>See the <a href="package-summary.html#package_description">Digester
+ * Developer Guide</a> for more information.</p>
+ *
+ * <p><strong>IMPLEMENTATION NOTES</strong>
+ * <ul>
+ * <li> A single Digester instance may only be used within the context of a
+ *  single thread at a time, and a call to <code>parse()</code> must be
+ *  completed before another can be initiated even from the same thread.</li>
+ * <li> This class requires that JAXP1.1 and a SAX2-compliant xml parser be
+ *  present in the classpath. Versions of java prior to 1.4 include neither
+ *  JAXP nor a parser, so simply including a modern xml parser plus a JAXP1.1
+ *  implementation in the classpath solves this requirement. Most xml parsers
+ *  provide a suitable implementation as a companion jar to the main download
+ *  (eg xml-apis.jar for the Apache Xerces parser). The 1.4 version of java
+ *  includes JAXP1.1, and bundles an xml parser. While the JAXP apis included
+ *  are fine, the xml parser bundled with this version of java is not adequate
+ *  for most tasks, and it is recommended that a better one be provided in the
+ *  classpath. Using the latest Apache Xerces release can be tricky, however,
+ *  as Sun's bundled parser is xerces, with package names unchanged, and
+ *  classes in the runtime libraries override classes in the classpath by
+ *  default. See documentation on the java "endorsed override" feature for
+ *  solutions, or the apache xerces website.
+ *  Versions of java from 1.5 onward provide xml parsers that are fine for
+ *  most purposes.</li>
+ * </ul>
+ */
+
+public class Digester {
+
+    // --------------------------------------------------------- Constructors
+
+    /**
+     * Construct a new Digester with default properties.
+     */
+    public Digester() {
+        this.saxHandler = new SAXHandler();
+    }
+
+    /**
+     * This method allows customisation of the way that sax events are
+     * handled, by allowing a modified subclass of SAXHandler to be
+     * specified as the target for parsing events.
+     */
+    public Digester(SAXHandler saxHandler) {
+        this.saxHandler = saxHandler;
+    }
+
+    // --------------------------------------------------- Instance Variables
+
+    /**
+     * The object used to handle event callbacks from the SAX parser as
+     * the input xml is being processed. There is a 1:1 relation between
+     * a Digester and a SAXHandler.
+     */
+    private SAXHandler saxHandler;
+
+    /**
+     * The reader object used to generate SAX events representing the input.
+     * Normally, the object does this by parsing input text, but alternatives
+     * (like walking a DOM tree and generating appropriate events) are also
+     * possible. In any case, it's not relevant to this app how the sax
+     * events are generated.
+     */
+    private XMLReader reader = null;
+
+    /**
+     * See {@link #setValidating}.
+     */
+    private boolean validating = false;
+
+    // ------------------------------------------------------------- Properties
+
+    /**
+     * Determine whether we are to validate the xml input against a schema.
+     * If so, then an error will be reported by the parse() methods if the
+     * input doesn't comply with the schema. If validation is disabled, then
+     * performance will be improved, but no error will be reported if the
+     * input is not correct.
+     * <p>
+     * Note that even when validation is disabled, any external schema or DTD
+     * referenced by the input document must still be read, as it can declare
+     * default attributes and similar items which affect xml parsing.
+     *
+     * @param validating The new validating parser flag.
+     *
+     * This must be called before <code>parse()</code> is called the first time.
+     */
+    public void setValidating(boolean validating) {
+        this.validating = validating;
+    }
+
+    /**
+     * Get the validating parser flag. See {@link #setValidating}.
+     */
+    public boolean getValidating() {
+        return (this.validating);
+    }
+
+    /**
+     * <p>Specify the XMLReader to be used to parse the input.</p>
+     *
+     * <p>This can be particularly useful in environments that are unfriendly
+     * to JAXP; it should always be possible to directly instantiate a parser
+     * using parser-specific code, and all decent xml parsers should implement
+     * (ie be castable to) the org.xml.sax.XMLReader interface even when the
+     * JAXP apis are not available or do not function correctly.</p>
+     *
+     * <p>If you have a SAXParser instance that should be used as the source
+     * of the input, then use:
+     * <pre>
+     *   setXMLReader(saxParser.getXMLReader());
+     * </pre>
+     * </p>
+     *
+     * <p>The reader passed here should be configured with namespace-aware
+     * parsing enabled, as the digester classes assume this.</p>
+     */
+    public void setXMLReader(XMLReader reader) {
+        this.reader = reader;
+    }
+
+    /**
+     * Set the class loader to be used for instantiating application objects
+     * when required. If a non-null value is passed to this method, then
+     * method {@link #useContextClassLoader} will have no effect.
+     * <p>
+     * When an Action is executed due to some xml input, and that Action
+     * wishes to create an object to represent the input, then the class
+     * used will be loaded via the specified classloader.
+     *
+     * @param classLoader The new class loader to use, or <code>null</code>
+     *  to revert to the standard rules
+     */
+    public void setExplicitClassLoader(ClassLoader classLoader) {
+        saxHandler.setExplicitClassLoader(classLoader);
+    }
+
+    /**
+     * Get the explicit class loader to be used by Actions for instantiating 
+     * objects when required. Null indicates that there is no explicit
+     * classloader set. 
+     * <p>
+     * When no explicit classloader has been specified, either the context 
+     * classloader (see {@link #setUseContextClassLoader}) or the classloader 
+     * that loaded the SAXHandler instance will be used.
+     *
+     * @return the classloader previously passed to setExplicitClassLoader,
+     * or null if no explicit classloader has been set. 
+     */
+    public ClassLoader getExplicitClassLoader() {
+        return saxHandler.getExplicitClassLoader();
+    }
+
+    /**
+     * Set the current logger for this Digester.
+     */
+    public void setLogger(Log log) {
+        saxHandler.setLogger(log);
+    }
+
+    /**
+     * Get the current Logger associated with this instance of the Digester
+     */
+    public Log getLogger() {
+        return saxHandler.getLogger();
+    }
+
+    /**
+     * Sets the logger used for logging SAX-related information.
+     * <strong>Note</strong> the output is finely grained.
+     * @param saxLog Log, not null
+     */
+    public void setSAXLogger(Log saxLog) {
+        saxHandler.setSAXLogger(saxLog);
+    }
+
+    /**
+     * Gets the logger used for logging SAX-related information.
+     * <strong>Note</strong> the output is finely grained.
+     */
+    public Log getSAXLogger() {
+        return saxHandler.getSAXLogger();
+    }
+
+    /**
+     * Set the <code>RuleManager</code> implementation object containing our
+     * rules collection and associated matching policy.
+     *
+     * @param ruleManager New RuleManager implementation
+     */
+    public void setRuleManager(RuleManager ruleManager) {
+        saxHandler.setRuleManager(ruleManager);
+    }
+
+    /**
+     * Get the <code>RuleManager</code> object containing our
+     * rule collection and associated matching policy.  If none has been
+     * established, a default implementation will be created and returned.
+     */
+    public RuleManager getRuleManager() {
+        return saxHandler.getRuleManager();
+    }
+
+    /**
+     * Set the publid id of the current file being parsed. This will cause
+     * the declared DOCTYPE (if any) of the input document to be ignored.
+     *
+     * Instead the provided publicId will be looked up in the known entities,
+     * and the resource located at the associated URL will be used as the
+     * DTD for this input document.
+     * <p>
+     * NOTE: if the input document doesn't include a DOCTYPE, then the
+     * DTD specified by this call is not used. There is currently no way
+     * to force an input document to be validated against a specific DTD
+     * (due to a lack of this feature in the xml standard).
+     *
+     * @param publicId the DTD/Schema public's id.
+     */
+    public void setPublicId(String publicId){
+        saxHandler.setPublicId(publicId);
+    }
+
+    /**
+     * Get the public identifier of the DTD we are currently parsing under,
+     * if any. If setPublicId has been called previously, then the value
+     * returned here will be the one explicitly set. Otherwise, if we have
+     * already seen a DOCTYPE declaration in the input data, then the
+     * public id in that DOCTYPE will be returned. Otherwise (parsing hasn't
+     * started or the input document had no DOCTYPE) null is returned.
+     */
+    public String getPublicId() {
+        return saxHandler.getPublicId();
+    }
+
+    /**
+     * Set the XML Schema URI used for validating a XML Instance.
+     *
+     * @param schemaLocation a URI to the schema.
+     */
+    public void setSchema(String schemaLocation){
+        saxHandler.setSchema(schemaLocation);
+    }
+
+    /**
+     * Get the XML Schema URI used for validating an XML instance.
+     */
+    public String getSchema() {
+        return saxHandler.getSchema();
+    }
+
+    /**
+     * Set the XML Schema language used when parsing. By default, we use W3C.
+     *
+     * @param schemaLanguage a URI to the schema language.
+     */
+    public void setSchemaLanguage(String schemaLanguage){
+        saxHandler.setSchemaLanguage(schemaLanguage);
+    }
+
+    /**
+     * Get the XML Schema language used when parsing.
+     */
+    public String getSchemaLanguage() {
+        return saxHandler.getSchemaLanguage();
+    }
+
+    /**
+     * Determine whether to use the Context Classloader (the one found by
+     * calling <code>Thread.currentThread().getContextClassLoader()</code>)
+     * to resolve/load classes when an Action needs to create an instance of
+     * an object to represent data in the xml input. If this is set to false,
+     * and there is no explicit classloader set, then the same classloader
+     * that loaded the Action class is used.
+     * <p>
+     * See {@link #setClassLoader}.
+     *
+     * @param use determines whether to use the Context Classloader.
+     */
+    public void setUseContextClassLoader(boolean use) {
+        saxHandler.setUseContextClassLoader(use);
+    }
+
+    /**
+     * Indicates whether the context classloader will be used by Actions
+     * when instantiating objects. See {@link #setUseContextClassLoader}.
+     */
+    public boolean getUseContextClassLoader() {
+        return saxHandler.getUseContextClassLoader();
+    }
+
+    /**
+     * Sets the <code>Substitutor</code> to be used to perform pre-processing
+     * on xml attributes and body text before Actions are applied.
+     *
+     * @param substitutor the Substitutor to be used, or null if no
+     *   substitution (pre-processing) is to be performed.
+     */
+    public void setSubstitutor(Substitutor substitutor) {
+        saxHandler.setSubstitutor(substitutor);
+    }
+
+    /**
+     * Gets the <code>Substitutor</code> used to perform pre-processing
+     * on xml attributes and body text before Actions are applied.
+     *
+     * @return Substitutor, null if no substitution (pre-processing) is to 
+     *   be performed.
+     */
+    public Substitutor getSubstitutor() {
+        return saxHandler.getSubstitutor();
+    }
+
+    /**
+     * Specifies a map of (publicId->URI) pairings that will be used by the
+     * default Entity Resolver when resolving entities in the input xml 
+     * (including the DTD or schema specified with the DOCTYPE).
+     * <p>
+     * See {@link #getKnownEntities}, and {@link #setEntityResolver}.
+     */
+    public void setKnownEntities(Map knownEntities) {
+        saxHandler.setKnownEntities(knownEntities);
+    }
+
+    /**
+     * <p>Register a mapping between a public or system ID (denoting an external
+     * entity, aka resource) and a URL indicating where that resource can be
+     * found, for use by the default Entity Resolver. It is particularly useful
+     * to register local locations for DTDs or schemas that the input xml may 
+     * reference.</p>
+     *
+     *<p>When the input xml refers to the entity via a public or system id, the
+     * resource pointed to by the registered URL is returned. This is commonly
+     * done for the input document's DTD, so that the DTD can be retrieved
+     * from a local file.</p>
+     *
+     * <p>This implementation provides only basic functionality. If more
+     * sophisticated features are required,using {@link #setEntityResolver} to
+     * set a custom resolver is recommended. Note in particular that if the
+     * input xml uses a system-ID to refer to an entity that is not registered,
+     * then the parser will attempt to use the system-id directly, potentially
+     * downloading the resource from a remote location.</p>
+     *
+     * <p>
+     * <strong>Note:</strong> This method will have no effect when a custom
+     * <code>EntityResolver</code> has been set. (Setting a custom
+     * <code>EntityResolver</code> overrides the internal implementation.)
+     * </p>
+     *
+     * @param publicOrSystemId Public or system identifier of the entity 
+     *  to be resolved
+     * @param entityURL The URL to use for reading this entity
+     */
+    public void registerKnownEntity(String publicOrSystemId, String entityURL) {
+        saxHandler.registerKnownEntity(publicOrSystemId, entityURL);
+    }
+
+    /**
+     * Returns a map of (publicId->URI) pairings that will be used by the
+     * default EntityResolver. 
+     * <p>
+     * See {@link #setKnownEntities}, and {@link #setEntityResolver}.
+     */
+    public Map getKnownEntities() {
+        return saxHandler.getKnownEntities();
+    }
+
+    // ------------------------------------------------------- Public Methods
+
+    /**
+     * Parse the content of the specified file using this Digester.  Returns
+     * the root element from the object stack (if any).
+     *
+     * @param file File containing the XML data to be parsed
+     *
+     * @exception IOException if an input/output error occurs
+     * @exception SAXException if a parsing exception occurs
+     */
+    public Object parse(File file)
+    throws DigestionException, IOException, SAXException {
+        try {
+            InputSource input = new InputSource(new FileInputStream(file));
+            input.setSystemId(file.toURL().toString());
+            getXMLReader().parse(input);
+            return saxHandler.getRoot();
+        }
+        catch(RuntimeException re) {
+            throw new DigestionException(re);
+        }
+    }
+
+    /**
+     * Parse the content of the specified input source using this Digester.
+     * Returns the root element from the object stack (if any).
+     *
+     * @param input Input source containing the XML data to be parsed
+     *
+     * @exception IOException if an input/output error occurs
+     * @exception SAXException if a parsing exception occurs
+     */
+    public Object parse(InputSource input)
+    throws DigestionException, IOException, SAXException {
+        try {
+            getXMLReader().parse(input);
+            return saxHandler.getRoot();
+        }
+        catch(RuntimeException re) {
+            throw new DigestionException(re);
+        }
+    }
+
+    /**
+     * Parse the content of the specified input stream using this Digester.
+     * Returns the root element from the object stack (if any).
+     * <p>
+     * Note that because the xml parser has no idea what the "real location"
+     * of the input is supposed to be, no relative referenced from the
+     * input xml document will work. If you need this behaviour, then
+     * use the parse(org.xml.sax.InputSource) variant, together with the
+     * InputSource.setSystemId method to tell the input source what the
+     * logical location of the input is supposed to be.
+     *
+     * @param input Input stream containing the XML data to be parsed
+     *
+     * @exception IOException if an input/output error occurs
+     * @exception SAXException if a parsing exception occurs
+     */
+    public Object parse(InputStream input)
+    throws DigestionException, IOException, SAXException {
+        try {
+            InputSource is = new InputSource(input);
+            getXMLReader().parse(is);
+            return saxHandler.getRoot();
+        }
+        catch(RuntimeException re) {
+            throw new DigestionException(re);
+        }
+    }
+
+    /**
+     * Parse the content of the specified reader using this Digester.
+     * Returns the root element from the object stack (if any).
+     * <p>
+     * Note that because the xml parser has no idea what the "real location"
+     * of the input is supposed to be, no relative referenced from the
+     * input xml document will work. If you need this behaviour, then
+     * use the parse(org.xml.sax.InputSource) variant, together with the
+     * InputSource.setSystemId method to tell the input source what the
+     * logical location of the input is supposed to be.
+     *
+     * @param reader Reader containing the XML data to be parsed
+     *
+     * @exception IOException if an input/output error occurs
+     * @exception SAXException if a parsing exception occurs
+     */
+    public Object parse(Reader reader)
+    throws DigestionException, IOException, SAXException {
+
+        try {
+            InputSource is = new InputSource(reader);
+            getXMLReader().parse(is);
+            return saxHandler.getRoot();
+        }
+        catch(RuntimeException re) {
+            throw new DigestionException(re);
+        }
+    }
+
+    /**
+     * Parse the content of the specified URI using this Digester.
+     * Returns the root element from the object stack (if any).
+     * <p>
+     * Note that because the xml parser has no idea what the "real location"
+     * of the input is supposed to be, no relative referenced from the
+     * input xml document will work. If you need this behaviour, then
+     * use the parse(org.xml.sax.InputSource) variant, together with the
+     * InputSource.setSystemId method to tell the input source what the
+     * logical location of the input is supposed to be.
+     *
+     * @param uri URI containing the XML data to be parsed
+     *
+     * @exception IOException if an input/output error occurs
+     * @exception SAXException if a parsing exception occurs
+     */
+    public Object parse(String uri)
+    throws DigestionException, IOException, SAXException {
+        try {
+            InputSource is = new InputSource(uri);
+            getXMLReader().parse(is);
+            return saxHandler.getRoot();
+        }
+        catch(RuntimeException re) {
+            throw new DigestionException(re);
+        }
+    }
+
+    // --------------------------------------------------------- Rule Methods
+
+    /**
+     * <p>Register a new rule (pattern/action pair).
+     *
+     * @param pattern Element matching pattern
+     * @param action Action to be registered
+     */
+    public void addRule(String pattern, Action action)
+    throws InvalidRuleException {
+        saxHandler.addRule(pattern, action);
+    }
+
+    // --------------------------------------------------- Object Stack Methods
+
+    /**
+     * Set the initial object that will form the root of the tree of
+     * objects generated during a parse.
+     * <p>
+     * Note that this is optional; an ObjectCreateAction associated with the
+     * root element of the input document performs the same task.
+     *
+     * @param object The new object
+     */
+    public void setInitialObject(Object object) {
+        saxHandler.setInitialObject(object);
+    }
+
+    /**
+     * Returns the root element of the tree of objects created as a result
+     * of applying the rules to the input XML.
+     * <p>
+     * If the digester stack was "primed" by explicitly pushing a root
+     * object onto the stack before parsing started, then that root object
+     * is returned here.
+     * <p>
+     * Alternatively, if an Action which creates an object (eg ObjectCreateAction)
+     * matched the root element of the xml, then the object created will be
+     * returned here.
+     * <p>
+     * In other cases, the object most recently pushed onto an empty digester
+     * stack is returned. This would be a most unusual use of digester, however;
+     * one of the previous configurations is much more likely.
+     * <p>
+     * Note that when using one of the Digester.parse methods, the return
+     * value from the parse method is exactly the same as the return value
+     * from this method. However when the Digester is being used as a
+     * SAXContentHandler, no such return value is available; in this case, this
+     * method allows you to access the root object that has been created
+     * after parsing has completed.
+     *
+     * @return the root object that has been created after parsing
+     *  or null if the digester has not parsed any XML yet.
+     */
+    public Object getRoot() {
+        return saxHandler.getRoot();
+    }
+
+    /**
+     * Return the XMLReader to be used for parsing the input document.
+     *
+     * @exception SAXException if no XMLReader can be instantiated
+     */
+    public XMLReader getXMLReader() throws SAXException {
+        if (reader != null) {
+            return reader;
+        }
+
+        try {
+            SAXParserFactory factory = SAXParserFactory.newInstance();
+            factory.setNamespaceAware(true);
+            factory.setValidating(validating);
+            
+            SAXParser parser = factory.newSAXParser();
+            reader = parser.getXMLReader();
+        } catch (Exception e) {
+            Log log = saxHandler.getLogger();
+            log.error("Digester.getXMLReader: ", e);
+            return null;
+        }
+
+        reader.setDTDHandler(saxHandler);
+        reader.setContentHandler(saxHandler);
+        reader.setEntityResolver(saxHandler);
+        reader.setErrorHandler(saxHandler);
+        return reader;
+    }
+
+    /**
+     * Specify the Entity Resolver used to determine the physical location
+     * of resources (such as DTDs or schemas) referred to by the input xml.
+     * <p>
+     * The value <i>null</i> indicates that the SAXHandler object will be
+     * used as the entity resolver. In this case, see methods:
+     * <ul>
+     * <li>{@link #setKnownEntities}</li>
+     * <li>{@link #registerKnownEntity}</li>
+     * </ul>
+     *
+     * @param entityResolver a class that implement the 
+     * <code>EntityResolver</code> interface, or <i>null</i> to restore
+     * the default behaviour.
+     */
+    public void setEntityResolver(EntityResolver entityResolver){
+        saxHandler.setEntityResolver(entityResolver);
+    }
+
+    /**
+     * Return the Entity Resolver used to determine the physical location
+     * of resources (such as DTDs or schemas) referred to by the input xml.
+     * <p>
+     * The value <i>null</i> indicates that the SAXHandler object will be
+     * used as the entity resolver. In this case, see methods:
+     * <ul>
+     * <li>{@link #setKnownEntities}</li>
+     * <li>{@link #registerKnownEntity}</li>
+     * </ul>
+     *
+     * @return the Entity Resolver to be used.
+     */
+    public EntityResolver getEntityResolver(){
+        return saxHandler.getEntityResolver();
+    }
+
+    /**
+     * Return the error handler which will be used if the xml parser detects
+     * errors in the xml input being parsed.
+     */
+    public ErrorHandler getErrorHandler() {
+        return saxHandler.getErrorHandler();
+    }
+
+    /**
+     * Set the error handler for this Digester.
+     *
+     * @param errorHandler The new error handler
+     */
+    public void setErrorHandler(ErrorHandler errorHandler) {
+        saxHandler.setErrorHandler(errorHandler);
+    }
+}

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/DigestionException.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/DigestionException.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/DigestionException.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/DigestionException.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,37 @@
+/* $Id: $
+ *
+ * Copyright 2001-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.
+ */ 
+
+
+package org.apache.commons.digester2;
+
+/**
+ */
+
+public class DigestionException extends Exception {
+    public DigestionException(String msg) {
+        super(msg);
+    }
+
+    public DigestionException(String msg, Throwable t) {
+        super(msg, t);
+    }
+    
+    public DigestionException(Throwable t) {
+        super(t);
+    }
+}
+

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/InvalidRuleException.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/InvalidRuleException.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/InvalidRuleException.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/InvalidRuleException.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,41 @@
+/* $Id: $
+ *
+ * Copyright 2001-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.
+ */ 
+
+
+package org.apache.commons.digester2;
+
+/**
+ * Thrown when a problem is detected as a rule is added to a RuleManager.
+ * One possible cause is that the pattern is invalid, but there may be
+ * others depending upon the RuleManager and Action involved.
+ */
+
+public class InvalidRuleException extends DigestionException {
+    public InvalidRuleException(String msg) {
+        super(msg);
+    }
+
+    public InvalidRuleException(Throwable t) {
+        super(t);
+    }
+    
+    public InvalidRuleException(String msg, Throwable t) {
+        super(msg, t);
+    }
+    
+}
+

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/MultiHashMap.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/MultiHashMap.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/MultiHashMap.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/MultiHashMap.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,446 @@
+/*
+ *  Copyright 2001-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.
+ */
+package org.apache.commons.digester2;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.AbstractCollection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * A <code>MultiMap</code> is a Map with slightly different semantics.
+ * Putting a value into the map will add the value to a Collection at that key.
+ * Getting a value will return a Collection, holding all the values put to that key.
+ * <p>
+ * This implementation uses an <code>ArrayList</code> as the collection.
+ * The internal storage list is made available without cloning via the
+ * <code>get(Object)</code> and <code>entrySet()</code> methods.
+ * The implementation returns <code>null</code> when there are no values mapped to a key.
+ * <p>
+ * For example:
+ * <pre>
+ * MultiMap mhm = new MultiHashMap();
+ * mhm.put(key, "A");
+ * mhm.put(key, "B");
+ * mhm.put(key, "C");
+ * List list = (List) mhm.get(key);</pre>
+ * <p>
+ * <code>list</code> will be a list containing "A", "B", "C".
+ *
+ * This code is derived from the class in apache-commons-collections v3.1.
+ * Thanks go to the authors of commons-collections!
+ *
+ */
+public class MultiHashMap extends HashMap {
+    
+    private static final Iterator EMPTY_ITERATOR = 
+        java.util.Collections.EMPTY_LIST.iterator();
+    
+    // backed values collection
+    private transient Collection values = null;
+    
+    // compatibility with commons-collection releases 2.0/2.1
+    private static final long serialVersionUID = 1943563828307035349L;
+
+    /**
+     * Constructor.
+     */
+    public MultiHashMap() {
+        super();
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param initialCapacity  the initial map capacity
+     */
+    public MultiHashMap(int initialCapacity) {
+        super(initialCapacity);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param initialCapacity  the initial map capacity
+     * @param loadFactor  the amount 0.0-1.0 at which to resize the map
+     */
+    public MultiHashMap(int initialCapacity, float loadFactor) {
+        super(initialCapacity, loadFactor);
+    }
+
+    /**
+     * Constructor. Note that this class has special behaviour if the source
+     * object being copied is a MultiHashMap; in that case, a copy of the
+     * collection is made too, so that adding an entry to the original
+     * MultiHashMap does not cause the value in the copy to change!
+     * 
+     * @param mapToCopy  a Map to copy
+     */
+    public MultiHashMap(Map mapToCopy) {
+        super((int) mapToCopy.size());
+        if (mapToCopy instanceof MultiHashMap) {
+            for (Iterator it = mapToCopy.entrySet().iterator(); it.hasNext();) {
+                Map.Entry entry = (Map.Entry) it.next();
+                Collection coll = (Collection) entry.getValue();
+                Collection newColl = createCollection(coll);
+                super.put(entry.getKey(), newColl);
+            }
+        } else {
+            putAll(mapToCopy);
+        }
+    }
+
+    /**
+     * Read the object during deserialization.
+     */
+    private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
+        // This method is needed because the 1.2/1.3 Java deserialisation called
+        // put and thus messed up that method
+        
+        // default read object
+        s.defaultReadObject();
+
+        // problem only with jvm <1.4
+        String version = "1.2";
+        try {
+            version = System.getProperty("java.version");
+        } catch (SecurityException ex) {
+            // ignore and treat as 1.2/1.3
+        }
+
+        if (version.startsWith("1.2") || version.startsWith("1.3")) {
+            for (Iterator iterator = entrySet().iterator(); iterator.hasNext();) {
+                Map.Entry entry = (Map.Entry) iterator.next();
+                // put has created a extra collection level, remove it
+                super.put(entry.getKey(), ((Collection) entry.getValue()).iterator().next());
+            }
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the total size of the map by counting all the values.
+     * 
+     * @return the total size of the map counting all values
+     * @since Commons Collections 3.1
+     */
+    public int totalSize() {
+        int total = 0;
+        Collection values = super.values();
+        for (Iterator it = values.iterator(); it.hasNext();) {
+            Collection coll = (Collection) it.next();
+            total += coll.size();
+        }
+        return total;
+    }
+
+    /**
+     * Gets the collection mapped to the specified key.
+     * This method is a convenience method to typecast the result of <code>get(key)</code>.
+     * 
+     * @param key  the key to retrieve
+     * @return the collection mapped to the key, null if no mapping
+     * @since Commons Collections 3.1
+     */
+    public Collection getCollection(Object key) {
+        return (Collection) get(key);
+    }
+
+    /**
+     * Gets the size of the collection mapped to the specified key.
+     * 
+     * @param key  the key to get size for
+     * @return the size of the collection at the key, zero if key not in map
+     * @since Commons Collections 3.1
+     */
+    public int size(Object key) {
+        Collection coll = getCollection(key);
+        if (coll == null) {
+            return 0;
+        }
+        return coll.size();
+    }
+
+    /**
+     * Gets an iterator for the collection mapped to the specified key.
+     * 
+     * @param key  the key to get an iterator for
+     * @return the iterator of the collection at the key, empty iterator if key not in map
+     * @since Commons Collections 3.1
+     */
+    public Iterator iterator(Object key) {
+        Collection coll = getCollection(key);
+        if (coll == null) {
+            return EMPTY_ITERATOR;
+        }
+        return coll.iterator();
+    }
+
+    /**
+     * Adds the value to the collection associated with the specified key.
+     * <p>
+     * Unlike a normal <code>Map</code> the previous value is not replaced.
+     * Instead the new value is added to the collection stored against the key.
+     *
+     * @param key  the key to store against
+     * @param value  the value to add to the collection at the key
+     * @return the value added if the map changed and null if the map did not change
+     */    
+    public Object put(Object key, Object value) {
+        // NOTE:: put is called during deserialization in JDK < 1.4 !!!!!!
+        //        so we must have a readObject()
+        Collection coll = getCollection(key);
+        if (coll == null) {
+            coll = createCollection(null);
+            super.put(key, coll);
+        }
+        boolean results = coll.add(value);
+        return (results ? value : null);
+    }
+
+    /**
+     * Adds a collection of values to the collection associated with the specified key.
+     *
+     * @param key  the key to store against
+     * @param values  the values to add to the collection at the key, null ignored
+     * @return true if this map changed
+     * @since Commons Collections 3.1
+     */    
+    public boolean putAll(Object key, Collection values) {
+        if (values == null || values.size() == 0) {
+            return false;
+        }
+        Collection coll = getCollection(key);
+        if (coll == null) {
+            coll = createCollection(values);
+            if (coll.size() == 0) {
+                return false;
+            }
+            super.put(key, coll);
+            return true;
+        } else {
+            return coll.addAll(values);
+        }
+    }
+
+    /**
+     * Checks whether the map contains the value specified.
+     * <p>
+     * This checks all collections against all keys for the value, and thus could be slow.
+     * 
+     * @param value  the value to search for
+     * @return true if the map contains the value
+     */
+    public boolean containsValue(Object value) {
+        Set pairs = super.entrySet();
+
+        if (pairs == null) {
+            return false;
+        }
+        Iterator pairsIterator = pairs.iterator();
+        while (pairsIterator.hasNext()) {
+            Map.Entry keyValuePair = (Map.Entry) pairsIterator.next();
+            Collection coll = (Collection) keyValuePair.getValue();
+            if (coll.contains(value)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Checks whether the collection at the specified key contains the value.
+     * 
+     * @param value  the value to search for
+     * @return true if the map contains the value
+     * @since Commons Collections 3.1
+     */
+    public boolean containsValue(Object key, Object value) {
+        Collection coll = getCollection(key);
+        if (coll == null) {
+            return false;
+        }
+        return coll.contains(value);
+    }
+
+    /**
+     * Removes a specific value from map.
+     * <p>
+     * The item is removed from the collection mapped to the specified key.
+     * Other values attached to that key are unaffected.
+     * <p>
+     * If the last value for a key is removed, <code>null</code> will be returned
+     * from a subsequant <code>get(key)</code>.
+     * 
+     * @param key  the key to remove from
+     * @param item  the value to remove
+     * @return the value removed (which was passed in), null if nothing removed
+     */
+    public Object remove(Object key, Object item) {
+        Collection valuesForKey = getCollection(key);
+        if (valuesForKey == null) {
+            return null;
+        }
+        valuesForKey.remove(item);
+
+        // remove the list if it is now empty
+        // (saves space, and allows equals to work)
+        if (valuesForKey.isEmpty()){
+            remove(key);
+        }
+        return item;
+    }
+
+    /**
+     * Clear the map.
+     * <p>
+     * This clears each collection in the map, and so may be slow.
+     */
+    public void clear() {
+        // For gc, clear each list in the map
+        Set pairs = super.entrySet();
+        Iterator pairsIterator = pairs.iterator();
+        while (pairsIterator.hasNext()) {
+            Map.Entry keyValuePair = (Map.Entry) pairsIterator.next();
+            Collection coll = (Collection) keyValuePair.getValue();
+            coll.clear();
+        }
+        super.clear();
+    }
+
+    /**
+     * Gets a collection containing all the values in the map.
+     * <p>
+     * This returns a collection containing the combination of values from all keys.
+     *
+     * @return a collection view of the values contained in this map
+     */
+    public Collection values() {
+        Collection vs = values;
+        return (vs != null ? vs : (values = new Values()));
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Inner class to view the elements.
+     */
+    private class Values extends AbstractCollection {
+
+        public Iterator iterator() {
+            return new ValueIterator();
+        }
+
+        public int size() {
+            int compt = 0;
+            Iterator it = iterator();
+            while (it.hasNext()) {
+                it.next();
+                compt++;
+            }
+            return compt;
+        }
+
+        public void clear() {
+            MultiHashMap.this.clear();
+        }
+
+    }
+
+    /**
+     * Inner iterator to view the elements.
+     */
+    private class ValueIterator implements Iterator {
+        private Iterator backedIterator;
+        private Iterator tempIterator;
+
+        private ValueIterator() {
+            backedIterator = MultiHashMap.super.values().iterator();
+        }
+
+        private boolean searchNextIterator() {
+            while (tempIterator == null || tempIterator.hasNext() == false) {
+                if (backedIterator.hasNext() == false) {
+                    return false;
+                }
+                tempIterator = ((Collection) backedIterator.next()).iterator();
+            }
+            return true;
+        }
+
+        public boolean hasNext() {
+            return searchNextIterator();
+        }
+
+        public Object next() {
+            if (searchNextIterator() == false) {
+                throw new NoSuchElementException();
+            }
+            return tempIterator.next();
+        }
+
+        public void remove() {
+            if (tempIterator == null) {
+                throw new IllegalStateException();
+            }
+            tempIterator.remove();
+        }
+
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Clone the map.
+     * <p>
+     * The clone will shallow clone the collections as well as the map.
+     * 
+     * @return the cloned map
+     */
+    public Object clone() {
+        MultiHashMap obj = (MultiHashMap) super.clone();
+
+        // clone each Collection container
+        for (Iterator it = entrySet().iterator(); it.hasNext();) {
+            Map.Entry entry = (Map.Entry) it.next();
+            Collection coll = (Collection) entry.getValue();
+            Collection newColl = createCollection(coll);
+            entry.setValue(newColl);
+        }
+        return obj;
+    }
+    
+    /** 
+     * Creates a new instance of the map value Collection container.
+     * <p>
+     * This method can be overridden to use your own collection type.
+     *
+     * @param coll  the collection to copy, may be null
+     * @return the new collection
+     */
+    protected Collection createCollection(Collection coll) {
+        if (coll == null) {
+            return new ArrayList();
+        } else {
+            return new ArrayList(coll);
+        }
+    }
+
+}

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/NestedSAXException.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/NestedSAXException.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/NestedSAXException.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/NestedSAXException.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,47 @@
+/* $Id: $
+ *
+ * Copyright 2001-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.
+ */ 
+
+
+package org.apache.commons.digester2;
+
+/**
+ * In some places in SAXHandler classes, we are permitted only to throw
+ * subclasses of SAXException. This class can be used to wrap the exception
+ * we really want to throw; the receiver should unwrap it via the getCause
+ * method.
+ * <p>
+ * We implement getCause directly here, in order to be able to support
+ * java platforms earlier than 1.4.
+ */
+
+public class NestedSAXException extends org.xml.sax.SAXException {
+    private Throwable cause;
+    
+    public NestedSAXException(String msg, Throwable t) {
+        super(msg);
+        cause = t;
+    }
+    
+    public NestedSAXException(Throwable t) {
+        cause = t;
+    }
+    
+    public Throwable getCause() {
+        return cause;
+    }
+}
+

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/ParseException.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/ParseException.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/ParseException.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/ParseException.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,38 @@
+/* $Id: $
+ *
+ * Copyright 2001-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.
+ */ 
+
+
+package org.apache.commons.digester2;
+
+/**
+ */
+
+public class ParseException extends DigestionException {
+    public ParseException(String msg) {
+        super(msg);
+    }
+
+    public ParseException(Throwable t) {
+        super(t);
+    }
+    
+    public ParseException(String msg, Throwable t) {
+        super(msg, t);
+    }
+    
+}
+

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/Path.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/Path.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/Path.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/Path.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,57 @@
+/* $Id: $
+ *
+ * Copyright 2001-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.
+ */ 
+
+
+package org.apache.commons.digester2;
+
+/**
+ * A simple class that represents the path to a particular XML element.
+ */
+
+public class Path {
+    StringBuffer buf = new StringBuffer();
+    ArrayStack lengths = new ArrayStack();
+    
+    public Path() {
+    }
+    
+    public void push(String namespace, String elementName) {
+        lengths.push(new Integer(buf.length()));
+        buf.append("/");
+        if ((namespace != null) && (namespace.length()>0)) {
+            buf.append('{');
+            buf.append(namespace);
+            buf.append('}');
+        }
+        buf.append(elementName);
+    }
+    
+    public void pop() {
+        int length = ((Integer)lengths.pop()).intValue();
+        buf.setLength(length);
+    }
+    
+    public String getPath() {
+        return buf.toString();
+    }
+    
+    public void clear() {
+        buf.setLength(0);
+        lengths.clear();
+    }
+}
+

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/RuleManager.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/RuleManager.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/RuleManager.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/RuleManager.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,98 @@
+/* $Id: $
+ *
+ * Copyright 2001-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.
+ */ 
+
+package org.apache.commons.digester2;
+
+import java.util.List;
+
+/**
+ * Public interface defining a collection of Action instances (and corresponding
+ * matching patterns) plus an implementation of a matching policy that selects
+ * the Actions that match a particular pattern of nested elements discovered
+ * during parsing.
+ *  <p>
+ * Terminology:
+ * <ul>
+ * <li>Pattern: a string with namespace prefixes in it, eg "/foo:bob"</li>
+ * <li>Path: a string with namespace uris in it, eg /{urn:foo}bob"</li>
+ * </ul>
+ * 
+ */
+
+public abstract class RuleManager {
+
+    // --------------------------------------------------------- Public Methods
+
+    /**
+     * Returns a new instance with the same type as the concrete object this
+     * method is invoked on, complete with contained Actions and patterns. Note
+     * that the new RuleManager instance may contain references to the same 
+     * Action instances as the old one, as Action instances are expected to be
+     * stateless and therefore can be safely shared between RuleManagers. 
+     */
+    public abstract RuleManager copy();
+    
+    /**
+     * Invoked before parsing each input document, this method gives the
+     * RuleManager and the managed Action objects the opportunity to do
+     * per-parse initialisation if required.
+     */
+    public void startParse(Context context) throws DigestionException {}
+     
+    /**
+     * Invoked after parsing each input document, this method gives the
+     * RuleManager and the managed Action objects the opportunity to do
+     * per-parse cleanup if required.
+     */
+     public void finishParse(Context context) throws DigestionException {}
+
+    /**
+     * Define a mapping between xml element prefix and namespace uri
+     * for use when rule patterns contain namespace prefixes.
+     */
+    public abstract void addNamespace(String prefix, String uri);
+    
+    /**
+     * Cause the specified Action to be invoked whenever an xml element
+     * is encountered in the input which matches the specified pattern.
+     * <p>
+     * If the pattern contains any namespace prefixes, eg "/myns:item",
+     * then an exception will be thrown unless that prefix has previously
+     * been defined via a call to method addNamespace.
+     * <p>
+     * Note that it is permitted for the same Action to be added multiple
+     * times with different associated patterns.
+     */
+    public abstract void addRule(String pattern, Action action)
+    throws InvalidRuleException;
+
+    /**
+     * Return a List of all registered Action instances that match the specified
+     * nesting pattern, or a zero-length List if there are no matches.  If more
+     * than one Action instance matches, they <strong>must</strong> be returned
+     * in the order originally registered through the <code>addRule()</code>
+     * method.
+     *
+     * @param path is a string of form
+     * <pre>/{namespace}elementName/{namespace}elementName"</pre>
+     * identifying the path from the root of the input document to the element 
+     * for which the caller wants the set of matching Action objects. If an
+     * element has no namespace, then the {} part is omitted.
+     */
+    public abstract List getMatchingActions(String path)
+        throws DigestionException;
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org