You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by si...@apache.org on 2011/05/12 20:03:33 UTC
svn commit: r1102402 [4/20] - in /commons/sandbox/digester3/trunk/src:
main/java/org/apache/commons/digester3/
main/java/org/apache/commons/digester3/annotations/
main/java/org/apache/commons/digester3/annotations/handlers/
main/java/org/apache/commons...
Modified: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/ExtendedBaseRules.java
URL: http://svn.apache.org/viewvc/commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/ExtendedBaseRules.java?rev=1102402&r1=1102401&r2=1102402&view=diff
==============================================================================
--- commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/ExtendedBaseRules.java (original)
+++ commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/ExtendedBaseRules.java Thu May 12 18:03:26 2011
@@ -16,10 +16,8 @@
* limitations under the License.
*/
-
package org.apache.commons.digester3;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -28,147 +26,122 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
-
/**
- * <p>Extension of {@link RulesBase} for complex schema.</p>
- *
- * <p>This is an extension of the basic pattern matching scheme
- * intended to improve support for mapping complex xml-schema.
- * It is intended to be a minimal extension of the standard rules
- * big enough to support complex schema but without the full generality
- * offered by more exotic matching pattern rules.</p>
- *
+ * <p>
+ * Extension of {@link RulesBase} for complex schema.
+ * </p>
+ * <p>
+ * This is an extension of the basic pattern matching scheme intended to improve support for mapping complex xml-schema.
+ * It is intended to be a minimal extension of the standard rules big enough to support complex schema but without the
+ * full generality offered by more exotic matching pattern rules.
+ * </p>
* <h4>When should you use this rather than the original?</h4>
- *
* <p>
- * This pattern-matching engine is complex and slower than the basic
- * default RulesBase class, but offers more functionality:
+ * This pattern-matching engine is complex and slower than the basic default RulesBase class, but offers more
+ * functionality:
* <ul>
- * <li>Universal patterns allow patterns to be specified which will match
- * regardless of whether there are "better matching" patterns available.</li>
- * <li>Parent-match patterns (eg "a/b/?") allow matching for all direct
- * children of a specified element.</li>
- * <li>Ancestor-match patterns (eg "a/b/*") allow matching all elements
- * nested within a specified element to any nesting depth.</li>
+ * <li>Universal patterns allow patterns to be specified which will match regardless of whether there are
+ * "better matching" patterns available.</li>
+ * <li>Parent-match patterns (eg "a/b/?") allow matching for all direct children of a specified element.</li>
+ * <li>Ancestor-match patterns (eg "a/b/*") allow matching all elements nested within a specified element to any nesting
+ * depth.</li>
* <li>Completely-wild patterns ("*" or "!*") allow matching all elements.</li>
* </ul>
* </p>
- *
* <h4>Universal Match Patterns</h4>
- *
- * <p>The default RulesBase pattern-matching engine always attempts to find
- * the "best matching pattern", and will ignore rules associated with other
- * patterns that match but are not "as good". As an example, if the pattern
- * "a/b/c" is associated with rules 1 and 2, and "*/c" is associated with
- * rules 3 and 4 then element "a/b/c" will cause only rules 1 and 2 to execute.
- * Rules 3 and 4 do have matching patterns, but because the patterns are shorter
- * and include wildcard characters they are regarded as being "not as good" as
- * a direct match. In general, exact patterns are better than wildcard patterns,
- * and among multiple patterns with wildcards, the longest is preferred.
- * See the RulesBase class for more information.</p>
- *
- * <p>This feature of preferring "better" patterns can be a powerful tool.
- * However it also means that patterns can interact in unexpected ways.</p>
- *
- * <p>When using the ExtendedBaseRules, any pattern prefixed with '!' bypasses
- * the "best match" feature. Even if there is an exact match or a longer
- * wildcard match, patterns prefixed by '!' will still be tested to see if
- * they match, and if so their associated Rule objects will be included in
- * the set of rules to be executed in the normal manner.</p>
- *
+ * <p>
+ * The default RulesBase pattern-matching engine always attempts to find the "best matching pattern", and will ignore
+ * rules associated with other patterns that match but are not "as good". As an example, if the pattern "a/b/c" is
+ * associated with rules 1 and 2, and "*/c" is associated with rules 3 and 4 then element "a/b/c" will cause only
+ * rules 1 and 2 to execute. Rules 3 and 4 do have matching patterns, but because the patterns are shorter and include
+ * wildcard characters they are regarded as being "not as good" as a direct match. In general, exact patterns are better
+ * than wildcard patterns, and among multiple patterns with wildcards, the longest is preferred. See the RulesBase class
+ * for more information.
+ * </p>
+ * <p>
+ * This feature of preferring "better" patterns can be a powerful tool. However it also means that patterns can interact
+ * in unexpected ways.
+ * </p>
+ * <p>
+ * When using the ExtendedBaseRules, any pattern prefixed with '!' bypasses the "best match" feature. Even if there is
+ * an exact match or a longer wildcard match, patterns prefixed by '!' will still be tested to see if they match, and if
+ * so their associated Rule objects will be included in the set of rules to be executed in the normal manner.
+ * </p>
* <ul>
- * <li>Pattern <code>"!*/a/b"</code> matches whenever an 'b' element
- * is inside an 'a'.</li>
- * <li>Pattern <code>"!a/b/?"</code> matches any child of a parent
- * matching <code>"a/b"</code> (see "Parent Match Patterns").</li>
- * <li>Pattern <code>"!*/a/b/?"</code> matches any child of a parent
- * matching <code>"!*/a/b"</code> (see "Parent Match Patterns").</li>
- * <li>Pattern <code>"!a/b/*"</code> matches any element whose path
- * starts with "a" then "b" (see "Ancestor Match Patterns").</li>
- * <li>Pattern <code>"!*/a/b/*"</code> matches any elements whose path
- * contains 'a/b' (see "Ancestor Match Patterns").</li>
+ * <li>Pattern <code>"!*/a/b"</code> matches whenever an 'b' element is inside an 'a'.</li>
+ * <li>Pattern <code>"!a/b/?"</code> matches any child of a parent matching <code>"a/b"</code> (see
+ * "Parent Match Patterns").</li>
+ * <li>Pattern <code>"!*/a/b/?"</code> matches any child of a parent matching <code>"!*/a/b"</code> (see
+ * "Parent Match Patterns").</li>
+ * <li>Pattern <code>"!a/b/*"</code> matches any element whose path starts with "a" then "b" (see
+ * "Ancestor Match Patterns").</li>
+ * <li>Pattern <code>"!*/a/b/*"</code> matches any elements whose path contains 'a/b' (see
+ * "Ancestor Match Patterns").</li>
* </ul>
- *
* <h4>Parent Match Patterns</h4>
- *
* <p>
* These will match direct child elements of a particular parent element.
* <ul>
* <li>
- * <code>"a/b/c/?"</code> matches any child whose parent matches
- * <code>"a/b/c"</code>. Exact parent rules take precedence over Ancestor
- * Match patterns.
- * </li>
+ * <code>"a/b/c/?"</code> matches any child whose parent matches <code>"a/b/c"</code>. Exact parent rules take
+ * precedence over Ancestor Match patterns.</li>
* <li>
- * <code>"*/a/b/c/?"</code> matches any child whose parent matches
- * <code>"*/a/b/c"</code>. The longest matching still applies to parent
- * matches but the length excludes the '?', which effectively means
- * that standard wildcard matches with the same level of depth are
- * chosen in preference.
- * </li>
+ * <code>"*/a/b/c/?"</code> matches any child whose parent matches <code>"*/a/b/c"</code>. The longest
+ * matching still applies to parent matches but the length excludes the '?', which effectively means that standard
+ * wildcard matches with the same level of depth are chosen in preference.</li>
* </ul>
* </p>
- *
* <h4>Ancestor Match Patterns</h4>
- *
* <p>
- * These will match elements whose parentage includes a particular sequence
- * of elements.
+ * These will match elements whose parentage includes a particular sequence of elements.
* <ul>
* <li>
- * <code>"a/b/*"</code> matches any element whose path starts with
- * 'a' then 'b'. Exact parent and parent match rules take precedence.
- * The longest ancestor match will take precedence.
- * </li>
+ * <code>"a/b/*"</code> matches any element whose path starts with 'a' then 'b'. Exact parent and parent match rules
+ * take precedence. The longest ancestor match will take precedence.</li>
* <li>
- * <code>"*/a/b/*"</code> matches any elements whose path contains
- * an element 'a' followed by an element 'b'. The longest matching still
- * applies but the length excludes the '*' at the end.
- * </li>
+ * <code>"*/a/b/*"</code> matches any elements whose path contains an element 'a' followed by an element 'b'.
+ * The longest matching still applies but the length excludes the '*' at the end.</li>
* </ul>
* </p>
- *
* <h4>Completely Wild Patterns</h4>
- *
- * <p>Pattern <code>"*"</code> matches every pattern that isn't matched by
- * any other basic rule.</p>
- *
- * <p>Pattern <code>"!*"</code> matches every pattern.</p>
- *
+ * <p>
+ * Pattern <code>"*"</code> matches every pattern that isn't matched by any other basic rule.
+ * </p>
+ * <p>
+ * Pattern <code>"!*"</code> matches every pattern.
+ * </p>
* <h4>Using The Extended Rules</h4>
- *
- * <p>By default, a Digester instance uses a {@link RulesBase} instance as
- * its pattern matching engine. To use an ExtendedBaseRules instance, call
- * the Digester.setRules method before adding any Rule objects to the digester
+ * <p>
+ * By default, a Digester instance uses a {@link RulesBase} instance as its pattern matching engine. To use an
+ * ExtendedBaseRules instance, call the Digester.setRules method before adding any Rule objects to the digester
* instance:
+ *
* <pre>
- * Digester digester = new Digester();
- * digester.setRules( new ExtendedBaseRules() );
- * </pre></p>
- *
- * <p>The most important thing to remember when using the extended rules is
- * that universal and non-universal patterns are completely independent.
- * Universal patterns are never affected by the addition of new patterns
- * or the removal of existing ones. Non-universal patterns are never affected
- * by the addition of new <em>universal</em> patterns or the removal of
- * existing <em>universal</em> patterns. As in the basic matching rules,
- * non-universal (basic) patterns <strong>can</strong> be affected by the
- * addition of new <em>non-universal</em> patterns or the removal of existing
- * <em>non-universal</em> patterns, because only rules associated with the
- * "best matching" pattern for each xml element are executed.
- *
- * <p> This means that you can use universal patterns to build up the simple
- * parts of your structure - for example defining universal creation and
- * property setting rules. More sophisticated and complex mapping will require
- * non-universal patterns and this might mean that some of the universal rules
- * will need to be replaced by a series of special cases using non-universal
- * rules. But by using universal rules as your backbone, these additions
- * should not break your existing rules.</p>
+ * Digester digester = new Digester();
+ * digester.setRules( new ExtendedBaseRules() );
+ * </pre>
+ *
+ * </p>
+ * <p>
+ * The most important thing to remember when using the extended rules is that universal and non-universal patterns are
+ * completely independent. Universal patterns are never affected by the addition of new patterns or the removal of
+ * existing ones. Non-universal patterns are never affected by the addition of new <em>universal</em> patterns or the
+ * removal of existing <em>universal</em> patterns. As in the basic matching rules, non-universal (basic) patterns
+ * <strong>can</strong> be affected by the addition of new <em>non-universal</em> patterns or the removal of existing
+ * <em>non-universal</em> patterns, because only rules associated with the "best matching" pattern for each xml element
+ * are executed.
+ * <p>
+ * This means that you can use universal patterns to build up the simple parts of your structure - for example defining
+ * universal creation and property setting rules. More sophisticated and complex mapping will require non-universal
+ * patterns and this might mean that some of the universal rules will need to be replaced by a series of special cases
+ * using non-universal rules. But by using universal rules as your backbone, these additions should not break your
+ * existing rules.
+ * </p>
*/
-
-public class ExtendedBaseRules extends RulesBase {
-
+public class ExtendedBaseRules
+ extends RulesBase
+{
// ----------------------------------------------------- Instance Variables
@@ -177,109 +150,112 @@ public class ExtendedBaseRules extends R
*/
private int counter = 0;
-
/**
- * The decision algorithm used (unfortunately) doesn't preserve the entry
- * order.
- * This map is used by a comparator which orders the list of matches
- * before it's returned.
- * This map stores the entry number keyed by the rule.
+ * The decision algorithm used (unfortunately) doesn't preserve the entry order. This map is used by a comparator
+ * which orders the list of matches before it's returned. This map stores the entry number keyed by the rule.
*/
private Map<Rule, Integer> order = new HashMap<Rule, Integer>();
-
// --------------------------------------------------------- Public Methods
-
/**
* Register a new Rule instance matching the specified pattern.
- *
+ *
* @param pattern Nesting pattern to be matched for this Rule
* @param rule Rule instance to be registered
*/
@Override
- public void add(String pattern, Rule rule) {
- super.add(pattern, rule);
+ public void add( String pattern, Rule rule )
+ {
+ super.add( pattern, rule );
counter++;
- order.put(rule, counter);
+ order.put( rule, counter );
}
-
/**
- * Return a List of all registered Rule instances that match the specified
- * nesting pattern, or a zero-length List if there are no matches. If more
- * than one Rule instance matches, they <strong>must</strong> be returned
- * in the order originally registered through the <code>add()</code>
- * method.
- *
+ * Return a List of all registered Rule instances that match the specified nesting pattern, or a zero-length List if
+ * there are no matches. If more than one Rule instance matches, they <strong>must</strong> be returned in the order
+ * originally registered through the <code>add()</code> method.
+ *
* @param pattern Nesting pattern to be matched
*/
@Override
- public List<Rule> match(String namespace, String pattern) {
+ public List<Rule> match( String namespace, String pattern )
+ {
// calculate the pattern of the parent
// (if the element has one)
String parentPattern = "";
- int lastIndex = pattern.lastIndexOf('/');
+ int lastIndex = pattern.lastIndexOf( '/' );
boolean hasParent = true;
- if (lastIndex == -1) {
+ if ( lastIndex == -1 )
+ {
// element has no parent
hasParent = false;
- } else {
+ }
+ else
+ {
// calculate the pattern of the parent
- parentPattern = pattern.substring(0, lastIndex);
+ parentPattern = pattern.substring( 0, lastIndex );
}
-
// we keep the list of universal matches separate
- List<Rule> universalList = new ArrayList<Rule>(counter);
+ List<Rule> universalList = new ArrayList<Rule>( counter );
// Universal all wildards ('!*')
// These are always matched so always add them
- List<Rule> tempList = this.cache.get("!*");
- if (tempList != null) {
- universalList.addAll(tempList);
+ List<Rule> tempList = this.cache.get( "!*" );
+ if ( tempList != null )
+ {
+ universalList.addAll( tempList );
}
// Universal exact parent match
// need to get this now since only wildcards are considered later
- tempList = this.cache.get("!" + parentPattern + "/?");
- if (tempList != null) {
- universalList.addAll(tempList);
+ tempList = this.cache.get( "!" + parentPattern + "/?" );
+ if ( tempList != null )
+ {
+ universalList.addAll( tempList );
}
-
// base behaviour means that if we certain matches, we don't continue
// but we just have a single combined loop and so we have to set
// a variable
boolean ignoreBasicMatches = false;
-
// see if we have an exact basic pattern match
- List<Rule> rulesList = this.cache.get(pattern);
- if (rulesList != null) {
+ List<Rule> rulesList = this.cache.get( pattern );
+ if ( rulesList != null )
+ {
// we have a match!
// so ignore all basic matches from now on
ignoreBasicMatches = true;
- } else {
+ }
+ else
+ {
// see if we have an exact child match
- if (hasParent) {
+ if ( hasParent )
+ {
// matching children takes preference
- rulesList = this.cache.get(parentPattern + "/?");
- if (rulesList != null) {
+ rulesList = this.cache.get( parentPattern + "/?" );
+ if ( rulesList != null )
+ {
// we have a match!
// so ignore all basic matches from now on
ignoreBasicMatches = true;
-
- } else {
+
+ }
+ else
+ {
// we don't have a match yet - so try exact ancester
//
- rulesList = findExactAncesterMatch(pattern);
- if (rulesList != null) {
+ rulesList = findExactAncesterMatch( pattern );
+ if ( rulesList != null )
+ {
// we have a match!
// so ignore all basic matches from now on
ignoreBasicMatches = true;
@@ -288,7 +264,6 @@ public class ExtendedBaseRules extends R
}
}
-
// OK - we're ready for the big loop!
// Unlike the basic rules case,
// we have to go through for all those universal rules in all cases.
@@ -296,71 +271,95 @@ public class ExtendedBaseRules extends R
// Find the longest key, ie more discriminant
String longKey = "";
int longKeyLength = 0;
-
- for (String key : this.cache.keySet()) {
+
+ for ( String key : this.cache.keySet() )
+ {
// find out if it's a univeral pattern
// set a flag
- boolean isUniversal = key.startsWith("!");
- if (isUniversal) {
+ boolean isUniversal = key.startsWith( "!" );
+ if ( isUniversal )
+ {
// and find the underlying key
- key = key.substring(1, key.length());
+ key = key.substring( 1, key.length() );
}
-
// don't need to check exact matches
- boolean wildcardMatchStart = key.startsWith("*/");
- boolean wildcardMatchEnd = key.endsWith("/*");
- if (wildcardMatchStart || (isUniversal && wildcardMatchEnd)) {
+ boolean wildcardMatchStart = key.startsWith( "*/" );
+ boolean wildcardMatchEnd = key.endsWith( "/*" );
+ if ( wildcardMatchStart || ( isUniversal && wildcardMatchEnd ) )
+ {
boolean parentMatched = false;
boolean basicMatched = false;
boolean ancesterMatched = false;
-
- boolean parentMatchEnd = key.endsWith("/?");
- if (parentMatchEnd) {
+
+ boolean parentMatchEnd = key.endsWith( "/?" );
+ if ( parentMatchEnd )
+ {
// try for a parent match
- parentMatched = parentMatch(key, pattern, parentPattern);
+ parentMatched = parentMatch( key, pattern, parentPattern );
- } else if (wildcardMatchEnd) {
+ }
+ else if ( wildcardMatchEnd )
+ {
// check for ancester match
- if (wildcardMatchStart) {
- String patternBody = key.substring(2, key.length() - 2);
- if (pattern.endsWith(patternBody)) {
+ if ( wildcardMatchStart )
+ {
+ String patternBody = key.substring( 2, key.length() - 2 );
+ if ( pattern.endsWith( patternBody ) )
+ {
ancesterMatched = true;
- } else {
- ancesterMatched = (pattern.indexOf(patternBody + "/") > -1);
}
- } else {
- String bodyPattern = key.substring(0, key.length() - 2);
- if (pattern.startsWith(bodyPattern))
+ else
{
- if (pattern.length() == bodyPattern.length()) {
+ ancesterMatched = ( pattern.indexOf( patternBody + "/" ) > -1 );
+ }
+ }
+ else
+ {
+ String bodyPattern = key.substring( 0, key.length() - 2 );
+ if ( pattern.startsWith( bodyPattern ) )
+ {
+ if ( pattern.length() == bodyPattern.length() )
+ {
// exact match
ancesterMatched = true;
- } else {
- ancesterMatched = ( pattern.charAt(bodyPattern.length()) == '/' );
}
- } else {
- ancesterMatched = false;
- }
- }
- } else {
+ else
+ {
+ ancesterMatched = ( pattern.charAt( bodyPattern.length() ) == '/' );
+ }
+ }
+ else
+ {
+ ancesterMatched = false;
+ }
+ }
+ }
+ else
+ {
// try for a base match
- basicMatched = basicMatch(key, pattern);
+ basicMatched = basicMatch( key, pattern );
}
- if (parentMatched || basicMatched || ancesterMatched) {
- if (isUniversal) {
+ if ( parentMatched || basicMatched || ancesterMatched )
+ {
+ if ( isUniversal )
+ {
// universal rules go straight in
// (no longest matching rule)
- tempList = this.cache.get("!" + key);
- if (tempList != null) {
- universalList.addAll(tempList);
+ tempList = this.cache.get( "!" + key );
+ if ( tempList != null )
+ {
+ universalList.addAll( tempList );
}
- } else {
- if (!ignoreBasicMatches) {
+ }
+ else
+ {
+ if ( !ignoreBasicMatches )
+ {
// ensure that all parent matches are SHORTER
// than rules with same level of matching.
//
@@ -368,17 +367,22 @@ public class ExtendedBaseRules extends R
// matching, but we don't care because in that case
// this if-stmt is not entered.
int keyLength = key.length();
- if (wildcardMatchStart) {
+ if ( wildcardMatchStart )
+ {
--keyLength;
}
- if (wildcardMatchEnd) {
+ if ( wildcardMatchEnd )
+ {
--keyLength;
- } else if (parentMatchEnd) {
+ }
+ else if ( parentMatchEnd )
+ {
--keyLength;
}
- if (keyLength > longKeyLength) {
- rulesList = this.cache.get(key);
+ if ( keyLength > longKeyLength )
+ {
+ rulesList = this.cache.get( key );
longKey = key;
longKeyLength = keyLength;
}
@@ -388,59 +392,66 @@ public class ExtendedBaseRules extends R
}
}
-
// '*' works in practice as a default matching
// (this is because anything is a deeper match!)
- if (rulesList == null) {
- rulesList = this.cache.get("*");
+ if ( rulesList == null )
+ {
+ rulesList = this.cache.get( "*" );
}
// if we've matched a basic pattern, then add to the universal list
- if (rulesList != null) {
- universalList.addAll(rulesList);
+ if ( rulesList != null )
+ {
+ universalList.addAll( rulesList );
}
-
// don't filter if namespace is null
- if (namespace != null) {
+ if ( namespace != null )
+ {
// remove invalid namespaces
Iterator<Rule> it = universalList.iterator();
- while (it.hasNext()) {
+ while ( it.hasNext() )
+ {
Rule rule = it.next();
String ns_uri = rule.getNamespaceURI();
- if (ns_uri != null && !ns_uri.equals(namespace)) {
+ if ( ns_uri != null && !ns_uri.equals( namespace ) )
+ {
it.remove();
}
}
}
-
// need to make sure that the collection is sort in the order
- // of addition. We use a custom comparator for this
- Collections.sort(
- universalList,
- new Comparator<Rule>() {
-
- public int compare(Rule r1, Rule r2) throws ClassCastException {
- // Get the entry order from the map
- Integer i1 = order.get(r1);
- Integer i2 = order.get(r2);
-
- // and use that to perform the comparison
- if (i1 == null) {
- if (i2 == null) {
+ // of addition. We use a custom comparator for this
+ Collections.sort( universalList, new Comparator<Rule>()
+ {
+
+ public int compare( Rule r1, Rule r2 )
+ throws ClassCastException
+ {
+ // Get the entry order from the map
+ Integer i1 = order.get( r1 );
+ Integer i2 = order.get( r2 );
+
+ // and use that to perform the comparison
+ if ( i1 == null )
+ {
+ if ( i2 == null )
+ {
- return 0;
+ return 0;
- }
- return -1;
- } else if (i2 == null) {
- return 1;
- }
-
- return (i1.intValue() - i2.intValue());
}
- });
+ return -1;
+ }
+ else if ( i2 == null )
+ {
+ return 1;
+ }
+
+ return ( i1.intValue() - i2.intValue() );
+ }
+ } );
return universalList;
}
@@ -448,30 +459,34 @@ public class ExtendedBaseRules extends R
/**
* Matching parent.
*/
- private boolean parentMatch(String key, String pattern, String parentPattern) {
- return parentPattern.endsWith(key.substring(1, key.length() - 2));
+ private boolean parentMatch( String key, String pattern, String parentPattern )
+ {
+ return parentPattern.endsWith( key.substring( 1, key.length() - 2 ) );
}
/**
- * Standard match.
- * Matches the end of the pattern to the key.
+ * Standard match. Matches the end of the pattern to the key.
*/
- private boolean basicMatch(String key, String pattern) {
- return (pattern.equals(key.substring(2)) ||
- pattern.endsWith(key.substring(1)));
+ private boolean basicMatch( String key, String pattern )
+ {
+ return ( pattern.equals( key.substring( 2 ) ) || pattern.endsWith( key.substring( 1 ) ) );
}
-
+
/**
* Finds an exact ancester match for given pattern
*/
- private List<Rule> findExactAncesterMatch(String parentPattern) {
+ private List<Rule> findExactAncesterMatch( String parentPattern )
+ {
List<Rule> matchingRules = null;
int lastIndex = parentPattern.length();
- while (lastIndex-- > 0) {
- lastIndex = parentPattern.lastIndexOf('/', lastIndex);
- if (lastIndex > 0) {
- matchingRules = this.cache.get(parentPattern.substring(0, lastIndex) + "/*");
- if (matchingRules != null) {
+ while ( lastIndex-- > 0 )
+ {
+ lastIndex = parentPattern.lastIndexOf( '/', lastIndex );
+ if ( lastIndex > 0 )
+ {
+ matchingRules = this.cache.get( parentPattern.substring( 0, lastIndex ) + "/*" );
+ if ( matchingRules != null )
+ {
return matchingRules;
}
}
Modified: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/FactoryCreateRule.java
URL: http://svn.apache.org/viewvc/commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/FactoryCreateRule.java?rev=1102402&r1=1102401&r2=1102402&view=diff
==============================================================================
--- commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/FactoryCreateRule.java (original)
+++ commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/FactoryCreateRule.java Thu May 12 18:03:26 2011
@@ -16,170 +16,172 @@
* limitations under the License.
*/
-
package org.apache.commons.digester3;
import java.util.Stack;
import org.xml.sax.Attributes;
-
/**
- * <p>Rule implementation that uses an {@link ObjectCreationFactory} to create
- * a new object which it pushes onto the object stack. When the element is
- * complete, the object will be popped.</p>
- *
- * <p>This rule is intended in situations where the element's attributes are
- * needed before the object can be created. A common senario is for the
- * ObjectCreationFactory implementation to use the attributes as parameters
- * in a call to either a factory method or to a non-empty constructor.
+ * <p>
+ * Rule implementation that uses an {@link ObjectCreationFactory} to create a new object which it pushes onto the object
+ * stack. When the element is complete, the object will be popped.
+ * </p>
+ * <p>
+ * This rule is intended in situations where the element's attributes are needed before the object can be created. A
+ * common senario is for the ObjectCreationFactory implementation to use the attributes as parameters in a call to
+ * either a factory method or to a non-empty constructor.
*/
-public class FactoryCreateRule extends Rule {
+public class FactoryCreateRule
+ extends Rule
+{
// ----------------------------------------------------------- Fields
-
+
/** Should exceptions thrown by the factory be ignored? */
private boolean ignoreCreateExceptions;
+
/** Stock to manage */
private Stack<Boolean> exceptionIgnoredStack;
// ----------------------------------------------------------- Constructors
/**
- * <p>Construct a factory create rule that will use the specified
- * class name to create an {@link ObjectCreationFactory} which will
- * then be used to create an object and push it on the stack.</p>
- *
- * <p>Exceptions thrown during the object creation process will be propagated.</p>
- *
+ * <p>
+ * Construct a factory create rule that will use the specified class name to create an {@link ObjectCreationFactory}
+ * which will then be used to create an object and push it on the stack.
+ * </p>
+ * <p>
+ * Exceptions thrown during the object creation process will be propagated.
+ * </p>
+ *
* @param className Java class name of the object creation factory class
*/
- public FactoryCreateRule(String className) {
+ public FactoryCreateRule( String className )
+ {
- this(className, false);
+ this( className, false );
}
-
/**
- * <p>Construct a factory create rule that will use the specified
- * class to create an {@link ObjectCreationFactory} which will
- * then be used to create an object and push it on the stack.</p>
- *
- * <p>Exceptions thrown during the object creation process will be propagated.</p>
- *
+ * <p>
+ * Construct a factory create rule that will use the specified class to create an {@link ObjectCreationFactory}
+ * which will then be used to create an object and push it on the stack.
+ * </p>
+ * <p>
+ * Exceptions thrown during the object creation process will be propagated.
+ * </p>
+ *
* @param clazz Java class name of the object creation factory class
*/
- public FactoryCreateRule(Class<?> clazz) {
+ public FactoryCreateRule( Class<?> clazz )
+ {
- this(clazz, false);
+ this( clazz, false );
}
-
/**
- * <p>Construct a factory create rule that will use the specified
- * class name (possibly overridden by the specified attribute if present)
- * to create an {@link ObjectCreationFactory}, which will then be used
- * to instantiate an object instance and push it onto the stack.</p>
- *
- * <p>Exceptions thrown during the object creation process will be propagated.</p>
- *
+ * <p>
+ * Construct a factory create rule that will use the specified class name (possibly overridden by the specified
+ * attribute if present) to create an {@link ObjectCreationFactory}, which will then be used to instantiate an
+ * object instance and push it onto the stack.
+ * </p>
+ * <p>
+ * Exceptions thrown during the object creation process will be propagated.
+ * </p>
+ *
* @param className Default Java class name of the factory class
- * @param attributeName Attribute name which, if present, contains an
- * override of the class name of the object creation factory to create.
+ * @param attributeName Attribute name which, if present, contains an override of the class name of the object
+ * creation factory to create.
*/
- public FactoryCreateRule(String className, String attributeName) {
+ public FactoryCreateRule( String className, String attributeName )
+ {
- this(className, attributeName, false);
+ this( className, attributeName, false );
}
-
/**
- * <p>Construct a factory create rule that will use the specified
- * class (possibly overridden by the specified attribute if present)
- * to create an {@link ObjectCreationFactory}, which will then be used
- * to instantiate an object instance and push it onto the stack.</p>
- *
- * <p>Exceptions thrown during the object creation process will be propagated.</p>
- *
+ * <p>
+ * Construct a factory create rule that will use the specified class (possibly overridden by the specified attribute
+ * if present) to create an {@link ObjectCreationFactory}, which will then be used to instantiate an object instance
+ * and push it onto the stack.
+ * </p>
+ * <p>
+ * Exceptions thrown during the object creation process will be propagated.
+ * </p>
+ *
* @param clazz Default Java class name of the factory class
- * @param attributeName Attribute name which, if present, contains an
- * override of the class name of the object creation factory to create.
+ * @param attributeName Attribute name which, if present, contains an override of the class name of the object
+ * creation factory to create.
*/
- public FactoryCreateRule(Class<?> clazz, String attributeName) {
+ public FactoryCreateRule( Class<?> clazz, String attributeName )
+ {
- this(clazz, attributeName, false);
+ this( clazz, attributeName, false );
}
-
/**
- * <p>Construct a factory create rule using the given, already instantiated,
- * {@link ObjectCreationFactory}.</p>
- *
- * <p>Exceptions thrown during the object creation process will be propagated.</p>
- *
+ * <p>
+ * Construct a factory create rule using the given, already instantiated, {@link ObjectCreationFactory}.
+ * </p>
+ * <p>
+ * Exceptions thrown during the object creation process will be propagated.
+ * </p>
+ *
* @param creationFactory called on to create the object.
*/
- public FactoryCreateRule(ObjectCreationFactory creationFactory) {
+ public FactoryCreateRule( ObjectCreationFactory creationFactory )
+ {
- this(creationFactory, false);
+ this( creationFactory, false );
}
-
+
/**
- * Construct a factory create rule that will use the specified
- * class name to create an {@link ObjectCreationFactory} which will
- * then be used to create an object and push it on the stack.
- *
+ * Construct a factory create rule that will use the specified class name to create an {@link ObjectCreationFactory}
+ * which will then be used to create an object and push it on the stack.
+ *
* @param className Java class name of the object creation factory class
- * @param ignoreCreateExceptions if true, exceptions thrown by the object
- * creation factory
- * will be ignored.
+ * @param ignoreCreateExceptions if true, exceptions thrown by the object creation factory will be ignored.
*/
- public FactoryCreateRule(String className, boolean ignoreCreateExceptions) {
+ public FactoryCreateRule( String className, boolean ignoreCreateExceptions )
+ {
- this(className, null, ignoreCreateExceptions);
+ this( className, null, ignoreCreateExceptions );
}
-
/**
- * Construct a factory create rule that will use the specified
- * class to create an {@link ObjectCreationFactory} which will
- * then be used to create an object and push it on the stack.
- *
+ * Construct a factory create rule that will use the specified class to create an {@link ObjectCreationFactory}
+ * which will then be used to create an object and push it on the stack.
+ *
* @param clazz Java class name of the object creation factory class
- * @param ignoreCreateExceptions if true, exceptions thrown by the
- * object creation factory
- * will be ignored.
+ * @param ignoreCreateExceptions if true, exceptions thrown by the object creation factory will be ignored.
*/
- public FactoryCreateRule(Class<?> clazz, boolean ignoreCreateExceptions) {
+ public FactoryCreateRule( Class<?> clazz, boolean ignoreCreateExceptions )
+ {
- this(clazz, null, ignoreCreateExceptions);
+ this( clazz, null, ignoreCreateExceptions );
}
-
/**
- * Construct a factory create rule that will use the specified
- * class name (possibly overridden by the specified attribute if present)
- * to create an {@link ObjectCreationFactory}, which will then be used
- * to instantiate an object instance and push it onto the stack.
- *
+ * Construct a factory create rule that will use the specified class name (possibly overridden by the specified
+ * attribute if present) to create an {@link ObjectCreationFactory}, which will then be used to instantiate an
+ * object instance and push it onto the stack.
+ *
* @param className Default Java class name of the factory class
- * @param attributeName Attribute name which, if present, contains an
- * override of the class name of the object creation factory to create.
- * @param ignoreCreateExceptions if true, exceptions thrown by the object
- * creation factory will be ignored.
- */
- public FactoryCreateRule(
- String className,
- String attributeName,
- boolean ignoreCreateExceptions) {
+ * @param attributeName Attribute name which, if present, contains an override of the class name of the object
+ * creation factory to create.
+ * @param ignoreCreateExceptions if true, exceptions thrown by the object creation factory will be ignored.
+ */
+ public FactoryCreateRule( String className, String attributeName, boolean ignoreCreateExceptions )
+ {
this.className = className;
this.attributeName = attributeName;
@@ -187,40 +189,31 @@ public class FactoryCreateRule extends R
}
-
/**
- * Construct a factory create rule that will use the specified
- * class (possibly overridden by the specified attribute if present)
- * to create an {@link ObjectCreationFactory}, which will then be used
- * to instantiate an object instance and push it onto the stack.
- *
+ * Construct a factory create rule that will use the specified class (possibly overridden by the specified attribute
+ * if present) to create an {@link ObjectCreationFactory}, which will then be used to instantiate an object instance
+ * and push it onto the stack.
+ *
* @param clazz Default Java class name of the factory class
- * @param attributeName Attribute name which, if present, contains an
- * override of the class name of the object creation factory to create.
- * @param ignoreCreateExceptions if true, exceptions thrown by the object
- * creation factory will be ignored.
+ * @param attributeName Attribute name which, if present, contains an override of the class name of the object
+ * creation factory to create.
+ * @param ignoreCreateExceptions if true, exceptions thrown by the object creation factory will be ignored.
*/
- public FactoryCreateRule(
- Class<?> clazz,
- String attributeName,
- boolean ignoreCreateExceptions) {
+ public FactoryCreateRule( Class<?> clazz, String attributeName, boolean ignoreCreateExceptions )
+ {
- this(clazz.getName(), attributeName, ignoreCreateExceptions);
+ this( clazz.getName(), attributeName, ignoreCreateExceptions );
}
-
/**
- * Construct a factory create rule using the given, already instantiated,
- * {@link ObjectCreationFactory}.
- *
+ * Construct a factory create rule using the given, already instantiated, {@link ObjectCreationFactory}.
+ *
* @param creationFactory called on to create the object.
- * @param ignoreCreateExceptions if true, exceptions thrown by the object
- * creation factory will be ignored.
+ * @param ignoreCreateExceptions if true, exceptions thrown by the object creation factory will be ignored.
*/
- public FactoryCreateRule(
- ObjectCreationFactory creationFactory,
- boolean ignoreCreateExceptions) {
+ public FactoryCreateRule( ObjectCreationFactory creationFactory, boolean ignoreCreateExceptions )
+ {
this.creationFactory = creationFactory;
this.ignoreCreateExceptions = ignoreCreateExceptions;
@@ -228,179 +221,195 @@ public class FactoryCreateRule extends R
// ----------------------------------------------------- Instance Variables
-
/**
* The attribute containing an override class name if it is present.
*/
protected String attributeName = null;
-
/**
- * The Java class name of the ObjectCreationFactory to be created.
- * This class must have a no-arguments constructor.
+ * The Java class name of the ObjectCreationFactory to be created. This class must have a no-arguments constructor.
*/
protected String className = null;
-
/**
- * The object creation factory we will use to instantiate objects
- * as required based on the attributes specified in the matched XML
- * element.
+ * The object creation factory we will use to instantiate objects as required based on the attributes specified in
+ * the matched XML element.
*/
protected ObjectCreationFactory creationFactory = null;
-
// --------------------------------------------------------- Public Methods
-
/**
* Process the beginning of this element.
- *
+ *
* @param attributes The attribute list of this element
*/
@Override
- public void begin(String namespace, String name, Attributes attributes) throws Exception {
-
- if (ignoreCreateExceptions) {
-
- if (exceptionIgnoredStack == null) {
+ public void begin( String namespace, String name, Attributes attributes )
+ throws Exception
+ {
+
+ if ( ignoreCreateExceptions )
+ {
+
+ if ( exceptionIgnoredStack == null )
+ {
exceptionIgnoredStack = new Stack<Boolean>();
}
-
- try {
- Object instance = getFactory(attributes).createObject(attributes);
-
- if (getDigester().getLogger().isDebugEnabled()) {
- getDigester().getLogger().debug("[FactoryCreateRule]{" + getDigester().getMatch() +
- "} New " + (instance == null ? "null object" :
- instance.getClass().getName()));
+
+ try
+ {
+ Object instance = getFactory( attributes ).createObject( attributes );
+
+ if ( getDigester().getLogger().isDebugEnabled() )
+ {
+ getDigester().getLogger().debug( "[FactoryCreateRule]{"
+ + getDigester().getMatch()
+ + "} New "
+ + ( instance == null ? "null object"
+ : instance.getClass().getName() ) );
}
- getDigester().push(instance);
- exceptionIgnoredStack.push(Boolean.FALSE);
-
- } catch (Exception e) {
+ getDigester().push( instance );
+ exceptionIgnoredStack.push( Boolean.FALSE );
+
+ }
+ catch ( Exception e )
+ {
// log message and error
- if (getDigester().getLogger().isInfoEnabled()) {
- getDigester().getLogger().info("[FactoryCreateRule] Create exception ignored: " +
- ((e.getMessage() == null) ? e.getClass().getName() : e.getMessage()));
- if (getDigester().getLogger().isDebugEnabled()) {
- getDigester().getLogger().debug("[FactoryCreateRule] Ignored exception:", e);
+ if ( getDigester().getLogger().isInfoEnabled() )
+ {
+ getDigester().getLogger().info( "[FactoryCreateRule] Create exception ignored: "
+ + ( ( e.getMessage() == null ) ? e.getClass().getName()
+ : e.getMessage() ) );
+ if ( getDigester().getLogger().isDebugEnabled() )
+ {
+ getDigester().getLogger().debug( "[FactoryCreateRule] Ignored exception:", e );
}
}
- exceptionIgnoredStack.push(Boolean.TRUE);
+ exceptionIgnoredStack.push( Boolean.TRUE );
}
-
- } else {
- Object instance = getFactory(attributes).createObject(attributes);
-
- if (getDigester().getLogger().isDebugEnabled()) {
- getDigester().getLogger().debug("[FactoryCreateRule]{" + getDigester().getMatch() +
- "} New " + (instance == null ? "null object" :
- instance.getClass().getName()));
+
+ }
+ else
+ {
+ Object instance = getFactory( attributes ).createObject( attributes );
+
+ if ( getDigester().getLogger().isDebugEnabled() )
+ {
+ getDigester().getLogger().debug( "[FactoryCreateRule]{"
+ + getDigester().getMatch()
+ + "} New "
+ + ( instance == null ? "null object"
+ : instance.getClass().getName() ) );
}
- getDigester().push(instance);
+ getDigester().push( instance );
}
}
-
/**
* Process the end of this element.
*/
@Override
- public void end(String namespace, String name) throws Exception {
-
- // check if object was created
+ public void end( String namespace, String name )
+ throws Exception
+ {
+
+ // check if object was created
// this only happens if an exception was thrown and we're ignoring them
- if (
- ignoreCreateExceptions &&
- exceptionIgnoredStack != null &&
- !(exceptionIgnoredStack.empty())) {
-
- if (exceptionIgnoredStack.pop().booleanValue()) {
+ if ( ignoreCreateExceptions && exceptionIgnoredStack != null && !( exceptionIgnoredStack.empty() ) )
+ {
+
+ if ( exceptionIgnoredStack.pop().booleanValue() )
+ {
// creation exception was ignored
// nothing was put onto the stack
- if (getDigester().getLogger().isTraceEnabled()) {
- getDigester().getLogger().trace("[FactoryCreateRule] No creation so no push so no pop");
+ if ( getDigester().getLogger().isTraceEnabled() )
+ {
+ getDigester().getLogger().trace( "[FactoryCreateRule] No creation so no push so no pop" );
}
return;
}
- }
+ }
Object top = getDigester().pop();
- if (getDigester().getLogger().isDebugEnabled()) {
- getDigester().getLogger().debug("[FactoryCreateRule]{" + getDigester().getMatch() +
- "} Pop " + top.getClass().getName());
+ if ( getDigester().getLogger().isDebugEnabled() )
+ {
+ getDigester().getLogger().debug( "[FactoryCreateRule]{" + getDigester().getMatch() + "} Pop "
+ + top.getClass().getName() );
}
}
-
/**
* Clean up after parsing is complete.
*/
@Override
- public void finish() throws Exception {
+ public void finish()
+ throws Exception
+ {
- if (attributeName != null) {
+ if ( attributeName != null )
+ {
creationFactory = null;
}
}
-
/**
* Render a printable version of this Rule.
*/
@Override
- public String toString() {
+ public String toString()
+ {
- StringBuilder sb = new StringBuilder("FactoryCreateRule[");
- sb.append("className=");
- sb.append(className);
- sb.append(", attributeName=");
- sb.append(attributeName);
- if (creationFactory != null) {
- sb.append(", creationFactory=");
- sb.append(creationFactory);
+ StringBuilder sb = new StringBuilder( "FactoryCreateRule[" );
+ sb.append( "className=" );
+ sb.append( className );
+ sb.append( ", attributeName=" );
+ sb.append( attributeName );
+ if ( creationFactory != null )
+ {
+ sb.append( ", creationFactory=" );
+ sb.append( creationFactory );
}
- sb.append("]");
- return (sb.toString());
+ sb.append( "]" );
+ return ( sb.toString() );
}
-
// ------------------------------------------------------ Protected Methods
-
/**
- * Return an instance of our associated object creation factory,
- * creating one if necessary.
- *
+ * Return an instance of our associated object creation factory, creating one if necessary.
+ *
* @param attributes Attributes passed to our factory creation element
- *
* @exception Exception if any error occurs
*/
- protected ObjectCreationFactory getFactory(Attributes attributes)
- throws Exception {
+ protected ObjectCreationFactory getFactory( Attributes attributes )
+ throws Exception
+ {
- if (creationFactory == null) {
+ if ( creationFactory == null )
+ {
String realClassName = className;
- if (attributeName != null) {
- String value = attributes.getValue(attributeName);
- if (value != null) {
+ if ( attributeName != null )
+ {
+ String value = attributes.getValue( attributeName );
+ if ( value != null )
+ {
realClassName = value;
}
}
- if (getDigester().getLogger().isDebugEnabled()) {
- getDigester().getLogger().debug("[FactoryCreateRule]{" + getDigester().getMatch() +
- "} New factory " + realClassName);
+ if ( getDigester().getLogger().isDebugEnabled() )
+ {
+ getDigester().getLogger().debug( "[FactoryCreateRule]{" + getDigester().getMatch() + "} New factory "
+ + realClassName );
}
- Class<?> clazz = getDigester().getClassLoader().loadClass(realClassName);
- creationFactory = (ObjectCreationFactory)
- clazz.newInstance();
- creationFactory.setDigester(getDigester());
+ Class<?> clazz = getDigester().getClassLoader().loadClass( realClassName );
+ creationFactory = (ObjectCreationFactory) clazz.newInstance();
+ creationFactory.setDigester( getDigester() );
}
- return (creationFactory);
+ return ( creationFactory );
- }
+ }
}
Modified: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/NodeCreateRule.java
URL: http://svn.apache.org/viewvc/commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/NodeCreateRule.java?rev=1102402&r1=1102401&r2=1102402&view=diff
==============================================================================
--- commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/NodeCreateRule.java (original)
+++ commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/NodeCreateRule.java Thu May 12 18:03:26 2011
@@ -16,10 +16,8 @@
* limitations under the License.
*/
-
package org.apache.commons.digester3;
-
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -34,117 +32,96 @@ 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
+ * 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>
+ * <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</code> 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
+ * The created node will be normalized, meaning it will not contain text nodes that only contain white space characters.
+ * <p>
+ * The created <code>Node</code> 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</code> will never be triggered by Digester, which
- * usually is the behavior one would expect.</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</code> 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>
*
- * <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 {
-
+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.
+ * 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 {
-
+ 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>
+ * <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)
+ * @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(Document doc, Node root)
- throws ParserConfigurationException, SAXException {
+ public NodeBuilder( Document doc, 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.
+ * 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.
+ * 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.
*/
@@ -155,26 +132,32 @@ public class NodeCreateRule extends Rule
*/
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.
+ * 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) {
+ private void addTextIfPresent()
+ throws SAXException
+ {
+ if ( topText.length() > 0 )
+ {
String str = topText.toString();
- topText.setLength(0);
+ topText.setLength( 0 );
- if (str.trim().length() > 0) {
+ if ( str.trim().length() > 0 )
+ {
// 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 (DOMException e) {
- throw new SAXException(e.getMessage());
+ try
+ {
+ top.appendChild( doc.createTextNode( str ) );
+ }
+ catch ( DOMException e )
+ {
+ throw new SAXException( e.getMessage() );
}
}
}
@@ -182,24 +165,20 @@ public class NodeCreateRule extends Rule
// --------------------------------------------- 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.
+ * 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.
+ * 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.
+ * 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
@@ -207,13 +186,13 @@ public class NodeCreateRule extends Rule
* @throws SAXException if the DOM implementation throws an exception
*/
@Override
- public void characters(char[] ch, int start, int length)
- throws SAXException {
+ public void characters( char[] ch, int start, int length )
+ throws SAXException
+ {
- topText.append(ch, start, length);
+ topText.append( ch, start, length );
}
-
/**
* Checks whether control needs to be returned to Digester.
*
@@ -223,54 +202,56 @@ public class NodeCreateRule extends Rule
* @throws SAXException if the DOM implementation throws an exception
*/
@Override
- public void endElement(String namespaceURI, String localName,
- String qName)
- throws SAXException {
-
+ public void endElement( String namespaceURI, String localName, String qName )
+ throws SAXException
+ {
+
addTextIfPresent();
- try {
- if (depth == 0) {
- getDigester().setCustomContentHandler(oldContentHandler);
- getDigester().push(root);
- getDigester().endElement(namespaceURI, localName, qName);
+ try
+ {
+ if ( depth == 0 )
+ {
+ getDigester().setCustomContentHandler( oldContentHandler );
+ getDigester().push( root );
+ getDigester().endElement( namespaceURI, localName, qName );
}
-
+
top = top.getParentNode();
depth--;
- } catch (DOMException e) {
- throw new SAXException(e.getMessage());
+ }
+ catch ( DOMException e )
+ {
+ throw new SAXException( e.getMessage() );
}
}
-
/**
- * Adds a new
- * {@link org.w3c.dom.ProcessingInstruction ProcessingInstruction} to
- * the current node.
+ * 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
+ * @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(String target, String data)
- throws SAXException {
-
- try {
- top.appendChild(doc.createProcessingInstruction(target, data));
- } catch (DOMException e) {
- throw new SAXException(e.getMessage());
+ public void processingInstruction( String target, String data )
+ throws SAXException
+ {
+
+ try
+ {
+ top.appendChild( doc.createProcessingInstruction( target, data ) );
+ }
+ catch ( DOMException e )
+ {
+ throw new SAXException( e.getMessage() );
}
}
-
/**
- * Adds a new child {@link org.w3c.dom.Element Element} to the current
- * node.
+ * Adds a new child {@link org.w3c.dom.Element Element} to the current node.
*
* @param namespaceURI the namespace URI
* @param localName the local name
@@ -279,201 +260,194 @@ public class NodeCreateRule extends Rule
* @throws SAXException if the DOM implementation throws an exception
*/
@Override
- public void startElement(String namespaceURI, String localName,
- String qName, Attributes atts)
- throws SAXException {
+ public void startElement( String namespaceURI, String localName, String qName, Attributes atts )
+ throws SAXException
+ {
addTextIfPresent();
- try {
+ try
+ {
Node previousTop = top;
- if ((localName == null) || (localName.length() == 0)) {
- top = doc.createElement(qName);
- } else {
- top = doc.createElementNS(namespaceURI, localName);
+ if ( ( localName == null ) || ( localName.length() == 0 ) )
+ {
+ top = doc.createElement( qName );
+ }
+ else
+ {
+ top = doc.createElementNS( namespaceURI, localName );
}
- for (int i = 0; i < atts.getLength(); i++) {
+ for ( int i = 0; i < atts.getLength(); i++ )
+ {
Attr attr = null;
- if ((atts.getLocalName(i) == null) ||
- (atts.getLocalName(i).length() == 0)) {
- 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);
+ if ( ( atts.getLocalName( i ) == null ) || ( atts.getLocalName( i ).length() == 0 ) )
+ {
+ 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);
+ previousTop.appendChild( top );
depth++;
- } catch (DOMException e) {
- throw new SAXException(e.getMessage());
+ }
+ catch ( 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}.
+ * Default constructor. Creates an instance of this rule that will create a DOM {@link org.w3c.dom.Element Element}.
*/
- public NodeCreateRule() throws ParserConfigurationException {
+ public NodeCreateRule()
+ throws ParserConfigurationException
+ {
- this(Node.ELEMENT_NODE);
+ 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</code> that should be used when constructing the
- * node tree.
+ * 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</code> that should be used when constructing the node tree.
*
* @param documentBuilder the JAXP <code>DocumentBuilder</code> to use
*/
- public NodeCreateRule(DocumentBuilder documentBuilder) {
+ public NodeCreateRule( DocumentBuilder documentBuilder )
+ {
- this(Node.ELEMENT_NODE, 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</code> parameter.
+ * 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</code> 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}
+ * @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 IllegalArgumentException if the node type is not supported
*/
- public NodeCreateRule(int nodeType) throws ParserConfigurationException {
+ public NodeCreateRule( int nodeType )
+ throws ParserConfigurationException
+ {
- this(nodeType,
- DocumentBuilderFactory.newInstance().newDocumentBuilder());
+ 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</code> parameter. This constructor lets you
- * specify the JAXP <code>DocumentBuilder</code> that should be used when
- * constructing the node tree.
+ * 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</code> parameter. This constructor lets you specify the JAXP <code>DocumentBuilder</code> 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 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</code> to use
* @throws IllegalArgumentException if the node type is not supported
*/
- public NodeCreateRule(int nodeType, DocumentBuilder documentBuilder) {
+ public NodeCreateRule( int nodeType, DocumentBuilder documentBuilder )
+ {
- if (!((nodeType == Node.DOCUMENT_FRAGMENT_NODE) ||
- (nodeType == Node.ELEMENT_NODE))) {
- throw new IllegalArgumentException(
- "Can only create nodes of type DocumentFragment and Element");
+ 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</code> 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.
+ * 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).
+ * 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 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(String namespaceURI, String name, Attributes attributes)
- throws Exception {
+ public void begin( String namespaceURI, String name, Attributes attributes )
+ throws Exception
+ {
Document doc = documentBuilder.newDocument();
NodeBuilder builder = null;
- if (nodeType == Node.ELEMENT_NODE) {
+ 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));
+ 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));
+ }
+ 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());
+ 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);
+ getDigester().setCustomContentHandler( builder );
}
-
/**
* Pop the Node off the top of the stack.
*/
@Override
- public void end(String namespace, String name) throws Exception {
+ public void end( String namespace, String name )
+ throws Exception
+ {
getDigester().pop();
}
-
}