You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/08/30 15:14:26 UTC
[commons-digester] branch master updated: Use standard Javadoc @since tag format
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-digester.git
The following commit(s) were added to refs/heads/master by this push:
new 999e65f1 Use standard Javadoc @since tag format
999e65f1 is described below
commit 999e65f1e92a3dfbb50afa707e9b0187e1440dc0
Author: Gary Gregory <gg...@rocketsoftware.com>
AuthorDate: Tue Aug 30 11:14:22 2022 -0400
Use standard Javadoc @since tag format
---
.../commons/digester3/AbstractMethodRule.java | 546 ++++++-------
.../apache/commons/digester3/NodeCreateRule.java | 876 ++++++++++-----------
.../java/org/apache/commons/digester3/Rule.java | 342 ++++----
3 files changed, 882 insertions(+), 882 deletions(-)
diff --git a/core/src/main/java/org/apache/commons/digester3/AbstractMethodRule.java b/core/src/main/java/org/apache/commons/digester3/AbstractMethodRule.java
index 6a41c297..8cabc7a5 100644
--- a/core/src/main/java/org/apache/commons/digester3/AbstractMethodRule.java
+++ b/core/src/main/java/org/apache/commons/digester3/AbstractMethodRule.java
@@ -1,273 +1,273 @@
-package org.apache.commons.digester3;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-import static java.lang.String.format;
-import static org.apache.commons.beanutils.MethodUtils.invokeExactMethod;
-import static org.apache.commons.beanutils.MethodUtils.invokeMethod;
-
-import org.xml.sax.Attributes;
-
-/**
- * Abstract implementation for {@link org.apache.commons.digester3.SetNextRule},
- * {@link org.apache.commons.digester3.SetRootRule} and {@link org.apache.commons.digester3.SetTopRule} rules.
- *
- * @since 3.0
- */
-public abstract class AbstractMethodRule
- extends Rule
-{
-
- /**
- * The method name to call on the parent object.
- */
- protected String methodName = null;
-
- /**
- * The Java class name of the parameter type expected by the method.
- */
- protected String paramTypeName = null;
-
- /**
- * The Java class name of the parameter type expected by the method.
- */
- protected Class<?> paramType;
-
- /**
- * Should we use exact matching. Default is no.
- */
- protected boolean useExactMatch = false;
-
- /**
- * Should this rule be invoked when {@link #begin(String, String, Attributes)} (true)
- * or {@link #end(String, String)} (false) methods are invoked, false by default.
- */
- protected boolean fireOnBegin = false;
-
- /**
- * Construct a "set next" rule with the specified method name. The method's argument type is assumed to be the class
- * of the child object.
- *
- * @param methodName Method name of the parent method to call
- */
- public AbstractMethodRule( final String methodName )
- {
- this( methodName, (String) null );
- }
-
- /**
- * Construct a "set next" rule with the specified method name.
- *
- * @param methodName Method name of the parent method to call
- * @param paramType Java class of the parent method's argument (if you wish to use a primitive type, specify the
- * corresonding Java wrapper class instead, such as {@code java.lang.Boolean} for a
- * {@code boolean} parameter)
- */
- public AbstractMethodRule( final String methodName, final Class<?> paramType )
- {
- this( methodName, paramType.getName() );
- this.paramType = paramType;
- }
-
- /**
- * Construct a "set next" rule with the specified method name.
- *
- * @param methodName Method name of the parent method to call
- * @param paramTypeName Java class of the parent method's argument (if you wish to use a primitive type, specify the
- * corresonding Java wrapper class instead, such as {@code java.lang.Boolean} for a
- * {@code boolean} parameter)
- */
- public AbstractMethodRule( final String methodName, final String paramTypeName )
- {
- this.methodName = methodName;
- this.paramTypeName = paramTypeName;
- }
-
- /**
- * <p>
- * Is exact matching being used.
- * </p>
- * <p>
- * This rule uses {@code org.apache.commons.beanutils.MethodUtils} to introspect the relevent objects so that
- * the right method can be called. Originally, {@code MethodUtils.invokeExactMethod} was used. This matches
- * methods very strictly and so may not find a matching method when one exists. This is still the behavior when
- * exact matching is enabled.
- * </p>
- * <p>
- * When exact matching is disabled, {@code MethodUtils.invokeMethod} is used. This method finds more methods
- * but is less precise when there are several methods with correct signatures. So, if you want to choose an exact
- * signature you might need to enable this property.
- * </p>
- * <p>
- * The default setting is to disable exact matches.
- * </p>
- *
- * @return true if exact matching is enabled
- * @since Digester Release 1.1.1
- */
- public boolean isExactMatch()
- {
- return useExactMatch;
- }
-
- /**
- * Sets this rule be invoked when {@link #begin(String, String, Attributes)} (true)
- * or {@link #end(String, String)} (false) methods are invoked, false by default.
- *
- * @param fireOnBegin flag to mark this rule be invoked when {@link #begin(String, String, Attributes)} (true)
- * or {@link #end(String, String)} (false) methods are invoked, false by default.
- */
- public void setFireOnBegin( final boolean fireOnBegin )
- {
- this.fireOnBegin = fireOnBegin;
- }
-
- /**
- * Returns the flag this rule be invoked when {@link #begin(String, String, Attributes)} (true)
- * or {@link #end(String, String)} (false) methods are invoked, false by default.
- *
- * @return the flag this rule be invoked when {@link #begin(String, String, Attributes)} (true)
- * or {@link #end(String, String)} (false) methods are invoked, false by default.
- */
- public boolean isFireOnBegin()
- {
- return fireOnBegin;
- }
-
- /**
- * <p>
- * Set whether exact matching is enabled.
- * </p>
- * <p>
- * See {@link #isExactMatch()}.
- * </p>
- *
- * @param useExactMatch should this rule use exact method matching
- * @since Digester Release 1.1.1
- */
- public void setExactMatch( final boolean useExactMatch )
- {
- this.useExactMatch = useExactMatch;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void begin( final String namespace, final String name, final Attributes attributes )
- throws Exception
- {
- if ( fireOnBegin )
- {
- invoke();
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void end( final String namespace, final String name )
- throws Exception
- {
- if ( !fireOnBegin )
- {
- invoke();
- }
- }
-
- /**
- * Just performs the method execution.
- *
- * @throws Exception if any error occurs.
- */
- private void invoke()
- throws Exception
- {
- // Identify the objects to be used
- final Object child = getChild();
- final Object parent = getParent();
- if ( getDigester().getLogger().isDebugEnabled() )
- {
- if ( parent == null )
- {
- getDigester().getLogger().debug( format( "[%s]{%s} Call [NULL PARENT].%s(%s)",
- getClass().getSimpleName(),
- getDigester().getMatch(),
- methodName,
- child ) );
- }
- else
- {
- getDigester().getLogger().debug( format( "[%s]{%s} Call %s.%s(%s)",
- getClass().getSimpleName(),
- getDigester().getMatch(),
- parent.getClass().getName(),
- methodName,
- child ) );
- }
- }
-
- // Call the specified method
- final Class<?> paramTypes[] = new Class<?>[1];
- if ( paramType != null )
- {
- paramTypes[0] = getDigester().getClassLoader().loadClass( paramTypeName );
- }
- else
- {
- paramTypes[0] = child.getClass();
- }
-
- if ( useExactMatch )
- {
- invokeExactMethod( parent, methodName, new Object[] { child }, paramTypes );
- }
- else
- {
- invokeMethod( parent, methodName, new Object[] { child }, paramTypes );
- }
- }
-
- /**
- * Returns the argument object of method has to be invoked.
- *
- * @return the argument object of method has to be invoked.
- */
- protected abstract Object getChild();
-
- /**
- * Returns the target object of method has to be invoked.
- *
- * @return the target object of method has to be invoked.
- */
- protected abstract Object getParent();
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final String toString()
- {
- return format( "%s[methodName=%s, paramType=%s, paramTypeName=%s, useExactMatch=%s, fireOnBegin=%s]",
- getClass().getSimpleName(), methodName, paramType, paramTypeName, useExactMatch, fireOnBegin );
- }
-
-}
+package org.apache.commons.digester3;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import static java.lang.String.format;
+import static org.apache.commons.beanutils.MethodUtils.invokeExactMethod;
+import static org.apache.commons.beanutils.MethodUtils.invokeMethod;
+
+import org.xml.sax.Attributes;
+
+/**
+ * Abstract implementation for {@link org.apache.commons.digester3.SetNextRule},
+ * {@link org.apache.commons.digester3.SetRootRule} and {@link org.apache.commons.digester3.SetTopRule} rules.
+ *
+ * @since 3.0
+ */
+public abstract class AbstractMethodRule
+ extends Rule
+{
+
+ /**
+ * The method name to call on the parent object.
+ */
+ protected String methodName = null;
+
+ /**
+ * The Java class name of the parameter type expected by the method.
+ */
+ protected String paramTypeName = null;
+
+ /**
+ * The Java class name of the parameter type expected by the method.
+ */
+ protected Class<?> paramType;
+
+ /**
+ * Should we use exact matching. Default is no.
+ */
+ protected boolean useExactMatch = false;
+
+ /**
+ * Should this rule be invoked when {@link #begin(String, String, Attributes)} (true)
+ * or {@link #end(String, String)} (false) methods are invoked, false by default.
+ */
+ protected boolean fireOnBegin = false;
+
+ /**
+ * Construct a "set next" rule with the specified method name. The method's argument type is assumed to be the class
+ * of the child object.
+ *
+ * @param methodName Method name of the parent method to call
+ */
+ public AbstractMethodRule( final String methodName )
+ {
+ this( methodName, (String) null );
+ }
+
+ /**
+ * Construct a "set next" rule with the specified method name.
+ *
+ * @param methodName Method name of the parent method to call
+ * @param paramType Java class of the parent method's argument (if you wish to use a primitive type, specify the
+ * corresonding Java wrapper class instead, such as {@code java.lang.Boolean} for a
+ * {@code boolean} parameter)
+ */
+ public AbstractMethodRule( final String methodName, final Class<?> paramType )
+ {
+ this( methodName, paramType.getName() );
+ this.paramType = paramType;
+ }
+
+ /**
+ * Construct a "set next" rule with the specified method name.
+ *
+ * @param methodName Method name of the parent method to call
+ * @param paramTypeName Java class of the parent method's argument (if you wish to use a primitive type, specify the
+ * corresonding Java wrapper class instead, such as {@code java.lang.Boolean} for a
+ * {@code boolean} parameter)
+ */
+ public AbstractMethodRule( final String methodName, final String paramTypeName )
+ {
+ this.methodName = methodName;
+ this.paramTypeName = paramTypeName;
+ }
+
+ /**
+ * <p>
+ * Is exact matching being used.
+ * </p>
+ * <p>
+ * This rule uses {@code org.apache.commons.beanutils.MethodUtils} to introspect the relevent objects so that
+ * the right method can be called. Originally, {@code MethodUtils.invokeExactMethod} was used. This matches
+ * methods very strictly and so may not find a matching method when one exists. This is still the behavior when
+ * exact matching is enabled.
+ * </p>
+ * <p>
+ * When exact matching is disabled, {@code MethodUtils.invokeMethod} is used. This method finds more methods
+ * but is less precise when there are several methods with correct signatures. So, if you want to choose an exact
+ * signature you might need to enable this property.
+ * </p>
+ * <p>
+ * The default setting is to disable exact matches.
+ * </p>
+ *
+ * @return true if exact matching is enabled
+ * @since 1.1.1
+ */
+ public boolean isExactMatch()
+ {
+ return useExactMatch;
+ }
+
+ /**
+ * Sets this rule be invoked when {@link #begin(String, String, Attributes)} (true)
+ * or {@link #end(String, String)} (false) methods are invoked, false by default.
+ *
+ * @param fireOnBegin flag to mark this rule be invoked when {@link #begin(String, String, Attributes)} (true)
+ * or {@link #end(String, String)} (false) methods are invoked, false by default.
+ */
+ public void setFireOnBegin( final boolean fireOnBegin )
+ {
+ this.fireOnBegin = fireOnBegin;
+ }
+
+ /**
+ * Returns the flag this rule be invoked when {@link #begin(String, String, Attributes)} (true)
+ * or {@link #end(String, String)} (false) methods are invoked, false by default.
+ *
+ * @return the flag this rule be invoked when {@link #begin(String, String, Attributes)} (true)
+ * or {@link #end(String, String)} (false) methods are invoked, false by default.
+ */
+ public boolean isFireOnBegin()
+ {
+ return fireOnBegin;
+ }
+
+ /**
+ * <p>
+ * Set whether exact matching is enabled.
+ * </p>
+ * <p>
+ * See {@link #isExactMatch()}.
+ * </p>
+ *
+ * @param useExactMatch should this rule use exact method matching
+ * @since 1.1.1
+ */
+ public void setExactMatch( final boolean useExactMatch )
+ {
+ this.useExactMatch = useExactMatch;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void begin( final String namespace, final String name, final Attributes attributes )
+ throws Exception
+ {
+ if ( fireOnBegin )
+ {
+ invoke();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void end( final String namespace, final String name )
+ throws Exception
+ {
+ if ( !fireOnBegin )
+ {
+ invoke();
+ }
+ }
+
+ /**
+ * Just performs the method execution.
+ *
+ * @throws Exception if any error occurs.
+ */
+ private void invoke()
+ throws Exception
+ {
+ // Identify the objects to be used
+ final Object child = getChild();
+ final Object parent = getParent();
+ if ( getDigester().getLogger().isDebugEnabled() )
+ {
+ if ( parent == null )
+ {
+ getDigester().getLogger().debug( format( "[%s]{%s} Call [NULL PARENT].%s(%s)",
+ getClass().getSimpleName(),
+ getDigester().getMatch(),
+ methodName,
+ child ) );
+ }
+ else
+ {
+ getDigester().getLogger().debug( format( "[%s]{%s} Call %s.%s(%s)",
+ getClass().getSimpleName(),
+ getDigester().getMatch(),
+ parent.getClass().getName(),
+ methodName,
+ child ) );
+ }
+ }
+
+ // Call the specified method
+ final Class<?> paramTypes[] = new Class<?>[1];
+ if ( paramType != null )
+ {
+ paramTypes[0] = getDigester().getClassLoader().loadClass( paramTypeName );
+ }
+ else
+ {
+ paramTypes[0] = child.getClass();
+ }
+
+ if ( useExactMatch )
+ {
+ invokeExactMethod( parent, methodName, new Object[] { child }, paramTypes );
+ }
+ else
+ {
+ invokeMethod( parent, methodName, new Object[] { child }, paramTypes );
+ }
+ }
+
+ /**
+ * Returns the argument object of method has to be invoked.
+ *
+ * @return the argument object of method has to be invoked.
+ */
+ protected abstract Object getChild();
+
+ /**
+ * Returns the target object of method has to be invoked.
+ *
+ * @return the target object of method has to be invoked.
+ */
+ protected abstract Object getParent();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final String toString()
+ {
+ return format( "%s[methodName=%s, paramType=%s, paramTypeName=%s, useExactMatch=%s, fireOnBegin=%s]",
+ getClass().getSimpleName(), methodName, paramType, paramTypeName, useExactMatch, fireOnBegin );
+ }
+
+}
diff --git a/core/src/main/java/org/apache/commons/digester3/NodeCreateRule.java b/core/src/main/java/org/apache/commons/digester3/NodeCreateRule.java
index 37dbbb2b..bf65b95e 100644
--- a/core/src/main/java/org/apache/commons/digester3/NodeCreateRule.java
+++ b/core/src/main/java/org/apache/commons/digester3/NodeCreateRule.java
@@ -1,438 +1,438 @@
-package org.apache.commons.digester3;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.w3c.dom.Attr;
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-/**
- * A rule implementation that creates a DOM {@link org.w3c.dom.Node Node} containing the XML at the element that matched
- * the rule. Two concrete types of nodes can be created by this rule:
- * <ul>
- * <li>the default is to create an {@link org.w3c.dom.Element Element} node. The created element will correspond to the
- * element that matched the rule, containing all XML content underneath that element.</li>
- * <li>alternatively, this rule can create nodes of type {@link org.w3c.dom.DocumentFragment DocumentFragment}, which
- * will contain only the XML content under the element the rule was trigged on.</li>
- * </ul>
- * The created node will be normalized, meaning it will not contain text nodes that only contain white space characters.
- * <p>
- * The created {@code Node} will be pushed on Digester's object stack when done. To use it in the context of
- * another DOM {@link org.w3c.dom.Document Document}, it must be imported first, using the Document method
- * {@link org.w3c.dom.Document#importNode(org.w3c.dom.Node, boolean) importNode()}.
- * </p>
- * <p>
- * <strong>Important Note:</strong> This is implemented by replacing the SAX {@link org.xml.sax.ContentHandler
- * ContentHandler} in the parser used by Digester, and resetting it when the matched element is closed. As a side
- * effect, rules that would match XML nodes under the element that matches a {@code NodeCreateRule} will never be
- * triggered by Digester, which usually is the behavior one would expect.
- * </p>
- * <p>
- * <strong>Note</strong> that the current implementation does not set the namespace prefixes in the exported nodes. The
- * (usually more important) namespace URIs are set, of course.
- * </p>
- *
- * @since Digester 1.4
- */
-public class NodeCreateRule
- extends Rule
-{
-
- // ---------------------------------------------------------- Inner Classes
-
- /**
- * The SAX content handler that does all the actual work of assembling the DOM node tree from the SAX events.
- */
- private class NodeBuilder
- extends DefaultHandler
- {
-
- // ------------------------------------------------------- Constructors
-
- /**
- * Constructor.
- * <p>
- * Stores the content handler currently used by Digester so it can be reset when done, and initializes the DOM
- * objects needed to build the node.
- * </p>
- *
- * @param doc the document to use to create nodes
- * @param root the root node
- * @throws ParserConfigurationException if the DocumentBuilderFactory could not be instantiated
- * @throws SAXException if the XMLReader could not be instantiated by Digester (should not happen)
- */
- public NodeBuilder( final Document doc, final Node root )
- throws ParserConfigurationException, SAXException
- {
- this.doc = doc;
- this.root = root;
- this.top = root;
-
- oldContentHandler = getDigester().getCustomContentHandler();
- }
-
- // ------------------------------------------------- Instance Variables
-
- /**
- * The content handler used by Digester before it was set to this content handler.
- */
- protected ContentHandler oldContentHandler = null;
-
- /**
- * Depth of the current node, relative to the element where the content handler was put into action.
- */
- protected int depth = 0;
-
- /**
- * A DOM Document used to create the various Node instances.
- */
- protected Document doc = null;
-
- /**
- * The DOM node that will be pushed on Digester's stack.
- */
- protected Node root = null;
-
- /**
- * The current top DOM mode.
- */
- protected Node top = null;
-
- /**
- * The text content of the current top DOM node.
- */
- protected StringBuilder topText = new StringBuilder();
-
- // --------------------------------------------- Helper Methods
-
- /**
- * Appends a {@link org.w3c.dom.Text Text} node to the current node if the content reported by the parser is not
- * purely whitespace.
- */
- private void addTextIfPresent()
- throws SAXException
- {
- if ( topText.length() > 0 )
- {
- final String str = topText.toString();
- topText.setLength( 0 );
-
- if ( !str.trim().isEmpty() )
- {
- // The contained text is not *pure* whitespace, so create
- // a text node to hold it. Note that the "untrimmed" text
- // is stored in the node.
- try
- {
- top.appendChild( doc.createTextNode( str ) );
- }
- catch ( final DOMException e )
- {
- throw new SAXException( e.getMessage() );
- }
- }
- }
- }
-
- // --------------------------------------------- ContentHandler Methods
-
- /**
- * Handle notification about text embedded within the current node.
- * <p>
- * An xml parser calls this when text is found. We need to ensure that this text gets attached to the new Node
- * we are creating - except in the case where the only text in the node is whitespace.
- * <p>
- * There is a catch, however. According to the sax specification, a parser does not need to pass all of the text
- * content of a node in one go; it can make multiple calls passing part of the data on each call. In particular,
- * when the body of an element includes xml entity-references, at least some parsers make a separate call to
- * this method to pass just the entity content.
- * <p>
- * In this method, we therefore just append the provided text to a "current text" buffer. When the element end
- * is found, or a child element is found then we can check whether we have all-whitespace. See method
- * addTextIfPresent.
- *
- * @param ch the characters from the XML document
- * @param start the start position in the array
- * @param length the number of characters to read from the array
- * @throws SAXException if the DOM implementation throws an exception
- */
- @Override
- public void characters( final char[] ch, final int start, final int length )
- throws SAXException
- {
- topText.append( ch, start, length );
- }
-
- /**
- * Checks whether control needs to be returned to Digester.
- *
- * @param namespaceURI the namespace URI
- * @param localName the local name
- * @param qName the qualified (prefixed) name
- * @throws SAXException if the DOM implementation throws an exception
- */
- @Override
- public void endElement( final String namespaceURI, final String localName, final String qName )
- throws SAXException
- {
- addTextIfPresent();
-
- try
- {
- if ( depth == 0 )
- {
- getDigester().setCustomContentHandler( oldContentHandler );
- getDigester().push( root );
- getDigester().endElement( namespaceURI, localName, qName );
- }
-
- top = top.getParentNode();
- depth--;
- }
- catch ( final DOMException e )
- {
- throw new SAXException( e.getMessage() );
- }
- }
-
- /**
- * Adds a new {@link org.w3c.dom.ProcessingInstruction ProcessingInstruction} to the current node.
- *
- * @param target the processing instruction target
- * @param data the processing instruction data, or null if none was supplied
- * @throws SAXException if the DOM implementation throws an exception
- */
- @Override
- public void processingInstruction( final String target, final String data )
- throws SAXException
- {
- try
- {
- top.appendChild( doc.createProcessingInstruction( target, data ) );
- }
- catch ( final DOMException e )
- {
- throw new SAXException( e.getMessage() );
- }
- }
-
- /**
- * Adds a new child {@link org.w3c.dom.Element Element} to the current node.
- *
- * @param namespaceURI the namespace URI
- * @param localName the local name
- * @param qName the qualified (prefixed) name
- * @param atts the list of attributes
- * @throws SAXException if the DOM implementation throws an exception
- */
- @Override
- public void startElement( final String namespaceURI, final String localName, final String qName, final Attributes atts )
- throws SAXException
- {
- addTextIfPresent();
-
- try
- {
- final Node previousTop = top;
- if ( ( localName == null ) || ( localName.isEmpty() ) )
- {
- top = doc.createElement( qName );
- }
- else
- {
- top = doc.createElementNS( namespaceURI, localName );
- }
- for ( int i = 0; i < atts.getLength(); i++ )
- {
- Attr attr = null;
- if ( ( atts.getLocalName( i ) == null ) || ( atts.getLocalName( i ).isEmpty() ) )
- {
- attr = doc.createAttribute( atts.getQName( i ) );
- attr.setNodeValue( atts.getValue( i ) );
- ( (Element) top ).setAttributeNode( attr );
- }
- else
- {
- attr = doc.createAttributeNS( atts.getURI( i ), atts.getLocalName( i ) );
- attr.setNodeValue( atts.getValue( i ) );
- ( (Element) top ).setAttributeNodeNS( attr );
- }
- }
- previousTop.appendChild( top );
- depth++;
- }
- catch ( final DOMException e )
- {
- throw new SAXException( e.getMessage() );
- }
- }
- }
-
- // ----------------------------------------------------------- Constructors
-
- /**
- * Default constructor. Creates an instance of this rule that will create a DOM {@link org.w3c.dom.Element Element}.
- *
- * @throws ParserConfigurationException if a DocumentBuilder cannot be created which satisfies the
- * configuration requested.
- * @see DocumentBuilderFactory#newDocumentBuilder()
- */
- public NodeCreateRule()
- throws ParserConfigurationException
- {
- this( Node.ELEMENT_NODE );
- }
-
- /**
- * Constructor. Creates an instance of this rule that will create a DOM {@link org.w3c.dom.Element Element}, but
- * lets you specify the JAXP {@code DocumentBuilder} that should be used when constructing the node tree.
- *
- * @param documentBuilder the JAXP {@code DocumentBuilder} to use
- */
- public NodeCreateRule( final DocumentBuilder documentBuilder )
- {
- this( Node.ELEMENT_NODE, documentBuilder );
- }
-
- /**
- * Constructor. Creates an instance of this rule that will create either a DOM {@link org.w3c.dom.Element Element}
- * or a DOM {@link org.w3c.dom.DocumentFragment DocumentFragment}, depending on the value of the
- * {@code nodeType} parameter.
- *
- * @param nodeType the type of node to create, which can be either {@link org.w3c.dom.Node#ELEMENT_NODE
- * Node.ELEMENT_NODE} or {@link org.w3c.dom.Node#DOCUMENT_FRAGMENT_NODE Node.DOCUMENT_FRAGMENT_NODE}
- * @throws ParserConfigurationException if a DocumentBuilder cannot be created which satisfies the
- * configuration requested.
- * @see DocumentBuilderFactory#newDocumentBuilder()
- */
- public NodeCreateRule( final int nodeType )
- throws ParserConfigurationException
- {
- this( nodeType, DocumentBuilderFactory.newInstance().newDocumentBuilder() );
- }
-
- /**
- * Constructor. Creates an instance of this rule that will create either a DOM {@link org.w3c.dom.Element Element}
- * or a DOM {@link org.w3c.dom.DocumentFragment DocumentFragment}, depending on the value of the
- * {@code nodeType} parameter. This constructor lets you specify the JAXP {@code DocumentBuilder} that
- * should be used when constructing the node tree.
- *
- * @param nodeType the type of node to create, which can be either {@link org.w3c.dom.Node#ELEMENT_NODE
- * Node.ELEMENT_NODE} or {@link org.w3c.dom.Node#DOCUMENT_FRAGMENT_NODE Node.DOCUMENT_FRAGMENT_NODE}
- * @param documentBuilder the JAXP {@code DocumentBuilder} to use
- */
- public NodeCreateRule( final int nodeType, final DocumentBuilder documentBuilder )
- {
- if ( !( ( nodeType == Node.DOCUMENT_FRAGMENT_NODE ) || ( nodeType == Node.ELEMENT_NODE ) ) )
- {
- throw new IllegalArgumentException( "Can only create nodes of type DocumentFragment and Element" );
- }
- this.nodeType = nodeType;
- this.documentBuilder = documentBuilder;
- }
-
- // ----------------------------------------------------- Instance Variables
-
- /**
- * The JAXP {@code DocumentBuilder} to use.
- */
- private DocumentBuilder documentBuilder = null;
-
- /**
- * The type of the node that should be created. Must be one of the constants defined in {@link org.w3c.dom.Node
- * Node}, but currently only {@link org.w3c.dom.Node#ELEMENT_NODE Node.ELEMENT_NODE} and
- * {@link org.w3c.dom.Node#DOCUMENT_FRAGMENT_NODE Node.DOCUMENT_FRAGMENT_NODE} are allowed values.
- */
- private int nodeType = Node.ELEMENT_NODE;
-
- // ----------------------------------------------------------- Rule Methods
-
- /**
- * When this method fires, the digester is told to forward all SAX ContentHandler events to the builder object,
- * resulting in a DOM being built instead of normal digester rule-handling occurring. When the end of the current
- * xml element is encountered, the original content handler is restored (expected to be NULL, allowing normal
- * Digester operations to continue).
- *
- * @param namespaceURI the namespace URI of the matching element, or an empty string if the parser is not namespace
- * aware or the element has no namespace
- * @param name the local name if the parser is namespace aware, or just the element name otherwise
- * @param attributes The attribute list of this element
- * @throws Exception indicates a JAXP configuration problem
- */
- @Override
- public void begin( final String namespaceURI, final String name, final Attributes attributes )
- throws Exception
- {
- final Document doc = documentBuilder.newDocument();
- NodeBuilder builder = null;
- if ( nodeType == Node.ELEMENT_NODE )
- {
- Element element = null;
- if ( getDigester().getNamespaceAware() )
- {
- element = doc.createElementNS( namespaceURI, name );
- for ( int i = 0; i < attributes.getLength(); i++ )
- {
- element.setAttributeNS( attributes.getURI( i ), attributes.getQName( i ),
- attributes.getValue( i ) );
- }
- }
- else
- {
- element = doc.createElement( name );
- for ( int i = 0; i < attributes.getLength(); i++ )
- {
- element.setAttribute( attributes.getQName( i ), attributes.getValue( i ) );
- }
- }
- builder = new NodeBuilder( doc, element );
- }
- else
- {
- builder = new NodeBuilder( doc, doc.createDocumentFragment() );
- }
- // the NodeBuilder constructor has already saved the original
- // value of the digester's custom content handler (expected to
- // be null, but we save it just in case). So now we just
- // need to tell the digester to forward events to the builder.
- getDigester().setCustomContentHandler( builder );
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void end( final String namespace, final String name )
- throws Exception
- {
- getDigester().pop();
- }
-
-}
+package org.apache.commons.digester3;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * A rule implementation that creates a DOM {@link org.w3c.dom.Node Node} containing the XML at the element that matched
+ * the rule. Two concrete types of nodes can be created by this rule:
+ * <ul>
+ * <li>the default is to create an {@link org.w3c.dom.Element Element} node. The created element will correspond to the
+ * element that matched the rule, containing all XML content underneath that element.</li>
+ * <li>alternatively, this rule can create nodes of type {@link org.w3c.dom.DocumentFragment DocumentFragment}, which
+ * will contain only the XML content under the element the rule was trigged on.</li>
+ * </ul>
+ * The created node will be normalized, meaning it will not contain text nodes that only contain white space characters.
+ * <p>
+ * The created {@code Node} will be pushed on Digester's object stack when done. To use it in the context of
+ * another DOM {@link org.w3c.dom.Document Document}, it must be imported first, using the Document method
+ * {@link org.w3c.dom.Document#importNode(org.w3c.dom.Node, boolean) importNode()}.
+ * </p>
+ * <p>
+ * <strong>Important Note:</strong> This is implemented by replacing the SAX {@link org.xml.sax.ContentHandler
+ * ContentHandler} in the parser used by Digester, and resetting it when the matched element is closed. As a side
+ * effect, rules that would match XML nodes under the element that matches a {@code NodeCreateRule} will never be
+ * triggered by Digester, which usually is the behavior one would expect.
+ * </p>
+ * <p>
+ * <strong>Note</strong> that the current implementation does not set the namespace prefixes in the exported nodes. The
+ * (usually more important) namespace URIs are set, of course.
+ * </p>
+ *
+ * @since 1.4
+ */
+public class NodeCreateRule
+ extends Rule
+{
+
+ // ---------------------------------------------------------- Inner Classes
+
+ /**
+ * The SAX content handler that does all the actual work of assembling the DOM node tree from the SAX events.
+ */
+ private class NodeBuilder
+ extends DefaultHandler
+ {
+
+ // ------------------------------------------------------- Constructors
+
+ /**
+ * Constructor.
+ * <p>
+ * Stores the content handler currently used by Digester so it can be reset when done, and initializes the DOM
+ * objects needed to build the node.
+ * </p>
+ *
+ * @param doc the document to use to create nodes
+ * @param root the root node
+ * @throws ParserConfigurationException if the DocumentBuilderFactory could not be instantiated
+ * @throws SAXException if the XMLReader could not be instantiated by Digester (should not happen)
+ */
+ public NodeBuilder( final Document doc, final Node root )
+ throws ParserConfigurationException, SAXException
+ {
+ this.doc = doc;
+ this.root = root;
+ this.top = root;
+
+ oldContentHandler = getDigester().getCustomContentHandler();
+ }
+
+ // ------------------------------------------------- Instance Variables
+
+ /**
+ * The content handler used by Digester before it was set to this content handler.
+ */
+ protected ContentHandler oldContentHandler = null;
+
+ /**
+ * Depth of the current node, relative to the element where the content handler was put into action.
+ */
+ protected int depth = 0;
+
+ /**
+ * A DOM Document used to create the various Node instances.
+ */
+ protected Document doc = null;
+
+ /**
+ * The DOM node that will be pushed on Digester's stack.
+ */
+ protected Node root = null;
+
+ /**
+ * The current top DOM mode.
+ */
+ protected Node top = null;
+
+ /**
+ * The text content of the current top DOM node.
+ */
+ protected StringBuilder topText = new StringBuilder();
+
+ // --------------------------------------------- Helper Methods
+
+ /**
+ * Appends a {@link org.w3c.dom.Text Text} node to the current node if the content reported by the parser is not
+ * purely whitespace.
+ */
+ private void addTextIfPresent()
+ throws SAXException
+ {
+ if ( topText.length() > 0 )
+ {
+ final String str = topText.toString();
+ topText.setLength( 0 );
+
+ if ( !str.trim().isEmpty() )
+ {
+ // The contained text is not *pure* whitespace, so create
+ // a text node to hold it. Note that the "untrimmed" text
+ // is stored in the node.
+ try
+ {
+ top.appendChild( doc.createTextNode( str ) );
+ }
+ catch ( final DOMException e )
+ {
+ throw new SAXException( e.getMessage() );
+ }
+ }
+ }
+ }
+
+ // --------------------------------------------- ContentHandler Methods
+
+ /**
+ * Handle notification about text embedded within the current node.
+ * <p>
+ * An xml parser calls this when text is found. We need to ensure that this text gets attached to the new Node
+ * we are creating - except in the case where the only text in the node is whitespace.
+ * <p>
+ * There is a catch, however. According to the sax specification, a parser does not need to pass all of the text
+ * content of a node in one go; it can make multiple calls passing part of the data on each call. In particular,
+ * when the body of an element includes xml entity-references, at least some parsers make a separate call to
+ * this method to pass just the entity content.
+ * <p>
+ * In this method, we therefore just append the provided text to a "current text" buffer. When the element end
+ * is found, or a child element is found then we can check whether we have all-whitespace. See method
+ * addTextIfPresent.
+ *
+ * @param ch the characters from the XML document
+ * @param start the start position in the array
+ * @param length the number of characters to read from the array
+ * @throws SAXException if the DOM implementation throws an exception
+ */
+ @Override
+ public void characters( final char[] ch, final int start, final int length )
+ throws SAXException
+ {
+ topText.append( ch, start, length );
+ }
+
+ /**
+ * Checks whether control needs to be returned to Digester.
+ *
+ * @param namespaceURI the namespace URI
+ * @param localName the local name
+ * @param qName the qualified (prefixed) name
+ * @throws SAXException if the DOM implementation throws an exception
+ */
+ @Override
+ public void endElement( final String namespaceURI, final String localName, final String qName )
+ throws SAXException
+ {
+ addTextIfPresent();
+
+ try
+ {
+ if ( depth == 0 )
+ {
+ getDigester().setCustomContentHandler( oldContentHandler );
+ getDigester().push( root );
+ getDigester().endElement( namespaceURI, localName, qName );
+ }
+
+ top = top.getParentNode();
+ depth--;
+ }
+ catch ( final DOMException e )
+ {
+ throw new SAXException( e.getMessage() );
+ }
+ }
+
+ /**
+ * Adds a new {@link org.w3c.dom.ProcessingInstruction ProcessingInstruction} to the current node.
+ *
+ * @param target the processing instruction target
+ * @param data the processing instruction data, or null if none was supplied
+ * @throws SAXException if the DOM implementation throws an exception
+ */
+ @Override
+ public void processingInstruction( final String target, final String data )
+ throws SAXException
+ {
+ try
+ {
+ top.appendChild( doc.createProcessingInstruction( target, data ) );
+ }
+ catch ( final DOMException e )
+ {
+ throw new SAXException( e.getMessage() );
+ }
+ }
+
+ /**
+ * Adds a new child {@link org.w3c.dom.Element Element} to the current node.
+ *
+ * @param namespaceURI the namespace URI
+ * @param localName the local name
+ * @param qName the qualified (prefixed) name
+ * @param atts the list of attributes
+ * @throws SAXException if the DOM implementation throws an exception
+ */
+ @Override
+ public void startElement( final String namespaceURI, final String localName, final String qName, final Attributes atts )
+ throws SAXException
+ {
+ addTextIfPresent();
+
+ try
+ {
+ final Node previousTop = top;
+ if ( ( localName == null ) || ( localName.isEmpty() ) )
+ {
+ top = doc.createElement( qName );
+ }
+ else
+ {
+ top = doc.createElementNS( namespaceURI, localName );
+ }
+ for ( int i = 0; i < atts.getLength(); i++ )
+ {
+ Attr attr = null;
+ if ( ( atts.getLocalName( i ) == null ) || ( atts.getLocalName( i ).isEmpty() ) )
+ {
+ attr = doc.createAttribute( atts.getQName( i ) );
+ attr.setNodeValue( atts.getValue( i ) );
+ ( (Element) top ).setAttributeNode( attr );
+ }
+ else
+ {
+ attr = doc.createAttributeNS( atts.getURI( i ), atts.getLocalName( i ) );
+ attr.setNodeValue( atts.getValue( i ) );
+ ( (Element) top ).setAttributeNodeNS( attr );
+ }
+ }
+ previousTop.appendChild( top );
+ depth++;
+ }
+ catch ( final DOMException e )
+ {
+ throw new SAXException( e.getMessage() );
+ }
+ }
+ }
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Default constructor. Creates an instance of this rule that will create a DOM {@link org.w3c.dom.Element Element}.
+ *
+ * @throws ParserConfigurationException if a DocumentBuilder cannot be created which satisfies the
+ * configuration requested.
+ * @see DocumentBuilderFactory#newDocumentBuilder()
+ */
+ public NodeCreateRule()
+ throws ParserConfigurationException
+ {
+ this( Node.ELEMENT_NODE );
+ }
+
+ /**
+ * Constructor. Creates an instance of this rule that will create a DOM {@link org.w3c.dom.Element Element}, but
+ * lets you specify the JAXP {@code DocumentBuilder} that should be used when constructing the node tree.
+ *
+ * @param documentBuilder the JAXP {@code DocumentBuilder} to use
+ */
+ public NodeCreateRule( final DocumentBuilder documentBuilder )
+ {
+ this( Node.ELEMENT_NODE, documentBuilder );
+ }
+
+ /**
+ * Constructor. Creates an instance of this rule that will create either a DOM {@link org.w3c.dom.Element Element}
+ * or a DOM {@link org.w3c.dom.DocumentFragment DocumentFragment}, depending on the value of the
+ * {@code nodeType} parameter.
+ *
+ * @param nodeType the type of node to create, which can be either {@link org.w3c.dom.Node#ELEMENT_NODE
+ * Node.ELEMENT_NODE} or {@link org.w3c.dom.Node#DOCUMENT_FRAGMENT_NODE Node.DOCUMENT_FRAGMENT_NODE}
+ * @throws ParserConfigurationException if a DocumentBuilder cannot be created which satisfies the
+ * configuration requested.
+ * @see DocumentBuilderFactory#newDocumentBuilder()
+ */
+ public NodeCreateRule( final int nodeType )
+ throws ParserConfigurationException
+ {
+ this( nodeType, DocumentBuilderFactory.newInstance().newDocumentBuilder() );
+ }
+
+ /**
+ * Constructor. Creates an instance of this rule that will create either a DOM {@link org.w3c.dom.Element Element}
+ * or a DOM {@link org.w3c.dom.DocumentFragment DocumentFragment}, depending on the value of the
+ * {@code nodeType} parameter. This constructor lets you specify the JAXP {@code DocumentBuilder} that
+ * should be used when constructing the node tree.
+ *
+ * @param nodeType the type of node to create, which can be either {@link org.w3c.dom.Node#ELEMENT_NODE
+ * Node.ELEMENT_NODE} or {@link org.w3c.dom.Node#DOCUMENT_FRAGMENT_NODE Node.DOCUMENT_FRAGMENT_NODE}
+ * @param documentBuilder the JAXP {@code DocumentBuilder} to use
+ */
+ public NodeCreateRule( final int nodeType, final DocumentBuilder documentBuilder )
+ {
+ if ( !( ( nodeType == Node.DOCUMENT_FRAGMENT_NODE ) || ( nodeType == Node.ELEMENT_NODE ) ) )
+ {
+ throw new IllegalArgumentException( "Can only create nodes of type DocumentFragment and Element" );
+ }
+ this.nodeType = nodeType;
+ this.documentBuilder = documentBuilder;
+ }
+
+ // ----------------------------------------------------- Instance Variables
+
+ /**
+ * The JAXP {@code DocumentBuilder} to use.
+ */
+ private DocumentBuilder documentBuilder = null;
+
+ /**
+ * The type of the node that should be created. Must be one of the constants defined in {@link org.w3c.dom.Node
+ * Node}, but currently only {@link org.w3c.dom.Node#ELEMENT_NODE Node.ELEMENT_NODE} and
+ * {@link org.w3c.dom.Node#DOCUMENT_FRAGMENT_NODE Node.DOCUMENT_FRAGMENT_NODE} are allowed values.
+ */
+ private int nodeType = Node.ELEMENT_NODE;
+
+ // ----------------------------------------------------------- Rule Methods
+
+ /**
+ * When this method fires, the digester is told to forward all SAX ContentHandler events to the builder object,
+ * resulting in a DOM being built instead of normal digester rule-handling occurring. When the end of the current
+ * xml element is encountered, the original content handler is restored (expected to be NULL, allowing normal
+ * Digester operations to continue).
+ *
+ * @param namespaceURI the namespace URI of the matching element, or an empty string if the parser is not namespace
+ * aware or the element has no namespace
+ * @param name the local name if the parser is namespace aware, or just the element name otherwise
+ * @param attributes The attribute list of this element
+ * @throws Exception indicates a JAXP configuration problem
+ */
+ @Override
+ public void begin( final String namespaceURI, final String name, final Attributes attributes )
+ throws Exception
+ {
+ final Document doc = documentBuilder.newDocument();
+ NodeBuilder builder = null;
+ if ( nodeType == Node.ELEMENT_NODE )
+ {
+ Element element = null;
+ if ( getDigester().getNamespaceAware() )
+ {
+ element = doc.createElementNS( namespaceURI, name );
+ for ( int i = 0; i < attributes.getLength(); i++ )
+ {
+ element.setAttributeNS( attributes.getURI( i ), attributes.getQName( i ),
+ attributes.getValue( i ) );
+ }
+ }
+ else
+ {
+ element = doc.createElement( name );
+ for ( int i = 0; i < attributes.getLength(); i++ )
+ {
+ element.setAttribute( attributes.getQName( i ), attributes.getValue( i ) );
+ }
+ }
+ builder = new NodeBuilder( doc, element );
+ }
+ else
+ {
+ builder = new NodeBuilder( doc, doc.createDocumentFragment() );
+ }
+ // the NodeBuilder constructor has already saved the original
+ // value of the digester's custom content handler (expected to
+ // be null, but we save it just in case). So now we just
+ // need to tell the digester to forward events to the builder.
+ getDigester().setCustomContentHandler( builder );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void end( final String namespace, final String name )
+ throws Exception
+ {
+ getDigester().pop();
+ }
+
+}
diff --git a/core/src/main/java/org/apache/commons/digester3/Rule.java b/core/src/main/java/org/apache/commons/digester3/Rule.java
index 9dab9ca6..7235a33c 100644
--- a/core/src/main/java/org/apache/commons/digester3/Rule.java
+++ b/core/src/main/java/org/apache/commons/digester3/Rule.java
@@ -1,171 +1,171 @@
-package org.apache.commons.digester3;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-import org.xml.sax.Attributes;
-
-/**
- * Concrete implementations of this class implement actions to be taken when a
- * corresponding nested pattern of XML elements has been matched.
- * <p>
- * Writing a custom Rule is considered perfectly normal when using Digester, and
- * is encouraged whenever the default set of Rule classes don't meet your
- * requirements; the digester framework can help process xml even when the
- * built-in rules aren't quite what is needed. Creating a custom Rule is just as
- * easy as subclassing javax.servlet.http.HttpServlet for webapps, or
- * javax.swing.Action for GUI applications.
- * <p>
- * If a rule wishes to manipulate a digester stack (the default object stack, a
- * named stack, or the parameter stack) then it should only ever push objects in
- * the rule's begin method and always pop exactly the same number of objects off
- * the stack during the rule's end method. Of course peeking at the objects on
- * the stacks can be done from anywhere.
- * <p>
- * Rule objects should limit their state data to the digester object stack and
- * named stacks. Storing state in instance fields (other than digester) during
- * the parsing process will cause problems if invoked in a "nested" manner; this
- * can happen if the same instance is added to digester multiple times or if a
- * wildcard pattern is used which can match both an element and a child of the
- * same element.
- * <p>
- * Rule objects are not thread-safe when each thread creates a new digester, as
- * is commonly the case. In a multithreaded context you should create new Rule
- * instances for every digester or synchronize read/write access to the digester
- * within the Rule.
- */public abstract class Rule
-{
-
- // ----------------------------------------------------- Instance Variables
-
- /**
- * The Digester with which this Rule is associated.
- */
- private Digester digester = null;
-
- /**
- * The namespace URI for which this Rule is relevant, if any.
- */
- private String namespaceURI = null;
-
- // ------------------------------------------------------------- Properties
-
- /**
- * Return the Digester with which this Rule is associated.
- *
- * @return the Digester with which this Rule is associated
- */
- public Digester getDigester()
- {
- return ( this.digester );
- }
-
- /**
- * Set the {@code Digester} with which this {@code Rule} is associated.
- *
- * @param digester the {@code Digester} with which this {@code Rule} is associated
- */
- public void setDigester( final Digester digester )
- {
- this.digester = digester;
- }
-
- /**
- * Return the namespace URI for which this Rule is relevant, if any.
- *
- * @return the namespace URI for which this Rule is relevant, if any
- */
- public String getNamespaceURI()
- {
- return ( this.namespaceURI );
- }
-
- /**
- * Set the namespace URI for which this Rule is relevant, if any.
- *
- * @param namespaceURI Namespace URI for which this Rule is relevant, or {@code null} to match independent of
- * namespace.
- */
- public void setNamespaceURI( final String namespaceURI )
- {
- this.namespaceURI = namespaceURI;
- }
-
- // --------------------------------------------------------- Public Methods
-
- /**
- * This method is called when the beginning of a matching XML element is encountered.
- *
- * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace
- * aware or the element has no namespace
- * @param name the local name if the parser is namespace aware, or just the element name otherwise
- * @param attributes The attribute list of this element
- * @throws Exception if any error occurs
- * @since Digester 1.4
- */
- public void begin( final String namespace, final String name, final Attributes attributes )
- throws Exception
- {
- // The default implementation does nothing
- }
-
- /**
- * This method is called when the body of a matching XML element is encountered. If the element has no body, this
- * method is called with an empty string as the body text.
- *
- * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace
- * aware or the element has no namespace
- * @param name the local name if the parser is namespace aware, or just the element name otherwise
- * @param text The text of the body of this element
- * @throws Exception if any error occurs
- * @since Digester 1.4
- */
- public void body( final String namespace, final String name, final String text )
- throws Exception
- {
- // The default implementation does nothing
- }
-
- /**
- * This method is called when the end of a matching XML element is encountered.
- *
- * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace
- * aware or the element has no namespace
- * @param name the local name if the parser is namespace aware, or just the element name otherwise
- * @throws Exception if any error occurs
- * @since Digester 1.4
- */
- public void end( final String namespace, final String name )
- throws Exception
- {
- // The default implementation does nothing
- }
-
- /**
- * This method is called after all parsing methods have been called, to allow Rules to remove temporary data.
- *
- * @throws Exception if any error occurs
- */
- public void finish()
- throws Exception
- {
- // The default implementation does nothing
- }
-
-}
+package org.apache.commons.digester3;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.xml.sax.Attributes;
+
+/**
+ * Concrete implementations of this class implement actions to be taken when a
+ * corresponding nested pattern of XML elements has been matched.
+ * <p>
+ * Writing a custom Rule is considered perfectly normal when using Digester, and
+ * is encouraged whenever the default set of Rule classes don't meet your
+ * requirements; the digester framework can help process xml even when the
+ * built-in rules aren't quite what is needed. Creating a custom Rule is just as
+ * easy as subclassing javax.servlet.http.HttpServlet for webapps, or
+ * javax.swing.Action for GUI applications.
+ * <p>
+ * If a rule wishes to manipulate a digester stack (the default object stack, a
+ * named stack, or the parameter stack) then it should only ever push objects in
+ * the rule's begin method and always pop exactly the same number of objects off
+ * the stack during the rule's end method. Of course peeking at the objects on
+ * the stacks can be done from anywhere.
+ * <p>
+ * Rule objects should limit their state data to the digester object stack and
+ * named stacks. Storing state in instance fields (other than digester) during
+ * the parsing process will cause problems if invoked in a "nested" manner; this
+ * can happen if the same instance is added to digester multiple times or if a
+ * wildcard pattern is used which can match both an element and a child of the
+ * same element.
+ * <p>
+ * Rule objects are not thread-safe when each thread creates a new digester, as
+ * is commonly the case. In a multithreaded context you should create new Rule
+ * instances for every digester or synchronize read/write access to the digester
+ * within the Rule.
+ */public abstract class Rule
+{
+
+ // ----------------------------------------------------- Instance Variables
+
+ /**
+ * The Digester with which this Rule is associated.
+ */
+ private Digester digester = null;
+
+ /**
+ * The namespace URI for which this Rule is relevant, if any.
+ */
+ private String namespaceURI = null;
+
+ // ------------------------------------------------------------- Properties
+
+ /**
+ * Return the Digester with which this Rule is associated.
+ *
+ * @return the Digester with which this Rule is associated
+ */
+ public Digester getDigester()
+ {
+ return ( this.digester );
+ }
+
+ /**
+ * Set the {@code Digester} with which this {@code Rule} is associated.
+ *
+ * @param digester the {@code Digester} with which this {@code Rule} is associated
+ */
+ public void setDigester( final Digester digester )
+ {
+ this.digester = digester;
+ }
+
+ /**
+ * Return the namespace URI for which this Rule is relevant, if any.
+ *
+ * @return the namespace URI for which this Rule is relevant, if any
+ */
+ public String getNamespaceURI()
+ {
+ return ( this.namespaceURI );
+ }
+
+ /**
+ * Set the namespace URI for which this Rule is relevant, if any.
+ *
+ * @param namespaceURI Namespace URI for which this Rule is relevant, or {@code null} to match independent of
+ * namespace.
+ */
+ public void setNamespaceURI( final String namespaceURI )
+ {
+ this.namespaceURI = namespaceURI;
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * This method is called when the beginning of a matching XML element is encountered.
+ *
+ * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace
+ * aware or the element has no namespace
+ * @param name the local name if the parser is namespace aware, or just the element name otherwise
+ * @param attributes The attribute list of this element
+ * @throws Exception if any error occurs
+ * @since 1.4
+ */
+ public void begin( final String namespace, final String name, final Attributes attributes )
+ throws Exception
+ {
+ // The default implementation does nothing
+ }
+
+ /**
+ * This method is called when the body of a matching XML element is encountered. If the element has no body, this
+ * method is called with an empty string as the body text.
+ *
+ * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace
+ * aware or the element has no namespace
+ * @param name the local name if the parser is namespace aware, or just the element name otherwise
+ * @param text The text of the body of this element
+ * @throws Exception if any error occurs
+ * @since 1.4
+ */
+ public void body( final String namespace, final String name, final String text )
+ throws Exception
+ {
+ // The default implementation does nothing
+ }
+
+ /**
+ * This method is called when the end of a matching XML element is encountered.
+ *
+ * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace
+ * aware or the element has no namespace
+ * @param name the local name if the parser is namespace aware, or just the element name otherwise
+ * @throws Exception if any error occurs
+ * @since 1.4
+ */
+ public void end( final String namespace, final String name )
+ throws Exception
+ {
+ // The default implementation does nothing
+ }
+
+ /**
+ * This method is called after all parsing methods have been called, to allow Rules to remove temporary data.
+ *
+ * @throws Exception if any error occurs
+ */
+ public void finish()
+ throws Exception
+ {
+ // The default implementation does nothing
+ }
+
+}