minor Rules APIs improvement, taking inspiration from an idea described in DIGESTER-95; using the extended APIs users can contribute that feature just providing a customized Rules implementation rather than modifying the existing Digester code, forcing the custom-case cast as shown in the patch

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/digester/trunk@1139976 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/commons/digester3/Digester.java b/src/main/java/org/apache/commons/digester3/Digester.java
index c9852eb..2fc4900 100644
--- a/src/main/java/org/apache/commons/digester3/Digester.java
+++ b/src/main/java/org/apache/commons/digester3/Digester.java
@@ -1296,7 +1296,7 @@
         }
 
         // Fire "begin" events for all relevant rules
-        List<Rule> rules = getRules().match( namespaceURI, match );
+        List<Rule> rules = getRules().match( namespaceURI, match, localName, list );
         matches.push( rules );
         if ( ( rules != null ) && ( rules.size() > 0 ) )
         {
diff --git a/src/main/java/org/apache/commons/digester3/ExtendedBaseRules.java b/src/main/java/org/apache/commons/digester3/ExtendedBaseRules.java
index e0540b8..aadfe32 100644
--- a/src/main/java/org/apache/commons/digester3/ExtendedBaseRules.java
+++ b/src/main/java/org/apache/commons/digester3/ExtendedBaseRules.java
@@ -27,6 +27,8 @@
 import java.util.List;
 import java.util.Map;
 
+import org.xml.sax.Attributes;
+
 /**
  * <p>
  * Extension of {@link RulesBase} for complex schema.
@@ -173,7 +175,7 @@
      * {@inheritDoc}
      */
     @Override
-    public List<Rule> match( String namespace, String pattern )
+    public List<Rule> match( String namespaceURI, String pattern, String name, Attributes attributes )
     {
         // calculate the pattern of the parent
         // (if the element has one)
@@ -425,7 +427,7 @@
         }
 
         // don't filter if namespace is null
-        if ( namespace != null )
+        if ( namespaceURI != null )
         {
             // remove invalid namespaces
             Iterator<Rule> it = universalList.iterator();
@@ -433,7 +435,7 @@
             {
                 Rule rule = it.next();
                 String nsUri = rule.getNamespaceURI();
-                if ( nsUri != null && !nsUri.equals( namespace ) )
+                if ( nsUri != null && !nsUri.equals( namespaceURI ) )
                 {
                     it.remove();
                 }
diff --git a/src/main/java/org/apache/commons/digester3/PatternRuleMatcher.java b/src/main/java/org/apache/commons/digester3/PatternRuleMatcher.java
new file mode 100644
index 0000000..fd6bca3
--- /dev/null
+++ b/src/main/java/org/apache/commons/digester3/PatternRuleMatcher.java
@@ -0,0 +1,136 @@
+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 org.xml.sax.Attributes;
+
+/**
+ * @since 3.0
+ */
+final class PatternRuleMatcher
+    implements RuleMatcher
+{
+
+    private final String pattern;
+
+    private String namespaceURI;
+
+    public PatternRuleMatcher( String pattern )
+    {
+        this( pattern, null );
+    }
+
+    public PatternRuleMatcher( String pattern, /* @Nullable */String namespaceURI )
+    {
+        if ( pattern == null )
+        {
+            throw new IllegalArgumentException( "Input pattern must be not null" );
+        }
+
+        this.pattern = pattern;
+        this.namespaceURI = namespaceURI;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean match( String namespace, String pattern, String name, Attributes attributes )
+    {
+        if ( namespaceURI != null && !namespace.equals( namespaceURI ) )
+        {
+            return false;
+        }
+        return this.pattern.equals( pattern );
+    }
+
+    public String getPattern()
+    {
+        return pattern;
+    }
+
+    public String getNamespaceURI()
+    {
+        return namespaceURI;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ( ( namespaceURI == null ) ? 0 : namespaceURI.hashCode() );
+        result = prime * result + pattern.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( this == obj )
+        {
+            return true;
+        }
+
+        if ( obj == null )
+        {
+            return false;
+        }
+
+        if ( getClass() != obj.getClass() )
+        {
+            return false;
+        }
+
+        PatternRuleMatcher other = (PatternRuleMatcher) obj;
+        if ( namespaceURI == null )
+        {
+            if ( other.getNamespaceURI() != null )
+            {
+                return false;
+            }
+        }
+        else if ( !namespaceURI.equals( other.getNamespaceURI() ) )
+        {
+            return false;
+        }
+
+        if ( !pattern.equals( other.getPattern() ) )
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString()
+    {
+        return format( "%s (%s)", pattern, namespaceURI );
+    }
+
+}
diff --git a/src/main/java/org/apache/commons/digester3/RegexRules.java b/src/main/java/org/apache/commons/digester3/RegexRules.java
index 95aed5d..1322b1e 100644
--- a/src/main/java/org/apache/commons/digester3/RegexRules.java
+++ b/src/main/java/org/apache/commons/digester3/RegexRules.java
@@ -22,6 +22,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.xml.sax.Attributes;
+
 /**
  * <p>
  * Rules implementation that uses regular expression matching for paths.
@@ -98,7 +100,6 @@
     /**
      * {@inheritDoc}
      */
-    @Override
     public void clear()
     {
         registeredRules.clear();
@@ -107,8 +108,7 @@
     /**
      * {@inheritDoc}
      */
-    @Override
-    public List<Rule> match( String namespaceURI, String pattern )
+    public List<Rule> match( String namespaceURI, String pattern, String name, Attributes attributes )
     {
         //
         // not a particularly quick implementation
@@ -132,7 +132,6 @@
     /**
      * {@inheritDoc}
      */
-    @Override
     public List<Rule> rules()
     {
         ArrayList<Rule> rules = new ArrayList<Rule>( registeredRules.size() );
diff --git a/src/main/java/org/apache/commons/digester3/RuleMatcher.java b/src/main/java/org/apache/commons/digester3/RuleMatcher.java
new file mode 100644
index 0000000..2d7a465
--- /dev/null
+++ b/src/main/java/org/apache/commons/digester3/RuleMatcher.java
@@ -0,0 +1,44 @@
+package org.apache.commons.digester3;
+
+import org.xml.sax.Attributes;
+
+/*
+ * 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.
+ */
+
+/**
+ * Defines a functor interface implemented by classes that perform a predicate test
+ *
+ * @since 3.0
+ */
+public interface RuleMatcher
+{
+
+    /**
+     * Use the specified parameter to perform a test.
+     *
+     * @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 pattern Nesting pattern to be matched for this Rule
+     * @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
+     * @return true, if the test succeeds, false otherwise
+     */
+    boolean match( String namespace, String pattern, String name, Attributes attributes );
+
+}
diff --git a/src/main/java/org/apache/commons/digester3/Rules.java b/src/main/java/org/apache/commons/digester3/Rules.java
index 163dc89..6730f52 100644
--- a/src/main/java/org/apache/commons/digester3/Rules.java
+++ b/src/main/java/org/apache/commons/digester3/Rules.java
@@ -21,6 +21,8 @@
 
 import java.util.List;
 
+import org.xml.sax.Attributes;
+
 /**
  * Public interface defining a collection of Rule instances (and corresponding matching patterns) plus an implementation
  * of a matching policy that selects the rules that match a particular pattern of nested elements discovered during
@@ -85,7 +87,7 @@
      * @param pattern Nesting pattern to be matched
      * @return a List of all registered Rule instances that match the specified nesting pattern
      */
-    List<Rule> match( String namespaceURI, String pattern );
+    List<Rule> match( String namespaceURI, String pattern, String name, Attributes attributes );
 
     /**
      * Return a List of all registered Rule instances, or a zero-length List if there are no registered Rule instances.
diff --git a/src/main/java/org/apache/commons/digester3/RulesBase.java b/src/main/java/org/apache/commons/digester3/RulesBase.java
index 0889cd1..5c938fa 100644
--- a/src/main/java/org/apache/commons/digester3/RulesBase.java
+++ b/src/main/java/org/apache/commons/digester3/RulesBase.java
@@ -23,6 +23,8 @@
 import java.util.HashMap;
 import java.util.List;
 
+import org.xml.sax.Attributes;
+
 /**
  * <p>
  * Default implementation of the <code>Rules</code> interface that supports the standard rule matching behavior. This
@@ -156,7 +158,7 @@
     /**
      * {@inheritDoc}
      */
-    public List<Rule> match( String namespaceURI, String pattern )
+    public List<Rule> match( String namespaceURI, String pattern, String name, Attributes attributes )
     {
         // List rulesList = (List) this.cache.get(pattern);
         List<Rule> rulesList = lookup( namespaceURI, pattern );
diff --git a/src/main/java/org/apache/commons/digester3/SetNestedPropertiesRule.java b/src/main/java/org/apache/commons/digester3/SetNestedPropertiesRule.java
index 611e01e..0c414b7 100644
--- a/src/main/java/org/apache/commons/digester3/SetNestedPropertiesRule.java
+++ b/src/main/java/org/apache/commons/digester3/SetNestedPropertiesRule.java
@@ -21,21 +21,19 @@
 
 import static java.lang.String.format;
 
-import java.util.List;
-import java.util.LinkedList;
+import java.beans.PropertyDescriptor;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
-import java.beans.PropertyDescriptor;
 
 import org.apache.commons.beanutils.BeanUtils;
 import org.apache.commons.beanutils.DynaBean;
 import org.apache.commons.beanutils.DynaProperty;
 import org.apache.commons.beanutils.PropertyUtils;
-
-import org.xml.sax.Attributes;
-
 import org.apache.commons.logging.Log;
+import org.xml.sax.Attributes;
 
 /**
  * <p>
@@ -371,9 +369,9 @@
         {
         }
 
-        public List<Rule> match( String namespaceURI, String matchPath )
+        public List<Rule> match( String namespaceURI, String matchPath, String name, Attributes attributes )
         {
-            List<Rule> match = decoratedRules.match( namespaceURI, matchPath );
+            List<Rule> match = decoratedRules.match( namespaceURI, matchPath, name, attributes );
 
             if ( ( matchPath.startsWith( matchPrefix ) ) && ( matchPath.indexOf( '/', matchPrefix.length() ) == -1 ) )
             {
diff --git a/src/main/java/org/apache/commons/digester3/WithDefaultsRulesWrapper.java b/src/main/java/org/apache/commons/digester3/WithDefaultsRulesWrapper.java
index ae4b29e..9fa597e 100644
--- a/src/main/java/org/apache/commons/digester3/WithDefaultsRulesWrapper.java
+++ b/src/main/java/org/apache/commons/digester3/WithDefaultsRulesWrapper.java
@@ -22,6 +22,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.xml.sax.Attributes;
+
 /**
  * <p>
  * <code>Rules</code> <em>Decorator</em> that returns default rules when no matches are returned by the wrapped
@@ -137,9 +139,9 @@
     /**
      * {@inheritDoc}
      */
-    public List<Rule> match( String namespaceURI, String pattern )
+    public List<Rule> match( String namespaceURI, String pattern, String name, Attributes attributes )
     {
-        List<Rule> matches = wrappedRules.match( namespaceURI, pattern );
+        List<Rule> matches = wrappedRules.match( namespaceURI, pattern, name, attributes );
         if ( matches == null || matches.isEmpty() )
         {
             // a little bit of defensive programming
diff --git a/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java b/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java
index 3331034..d89fec3 100644
--- a/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java
+++ b/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java
@@ -435,7 +435,7 @@
         // and now we have to fire any custom rules which would have
         // been matched by the same path that matched this rule, had
         // they been loaded at that time.
-        List<Rule> rules = newRules.getDecoratedRules().match( namespace, path );
+        List<Rule> rules = newRules.getDecoratedRules().match( namespace, path, name, attributes );
         fireBeginMethods( rules, namespace, name, attributes );
     }
 
@@ -462,7 +462,7 @@
 
         String path = getDigester().getMatch();
         PluginRules newRules = (PluginRules) getDigester().getRules();
-        List<Rule> rules = newRules.getDecoratedRules().match( namespace, path );
+        List<Rule> rules = newRules.getDecoratedRules().match( namespace, path, name, null );
         fireBodyMethods( rules, namespace, name, text );
     }
 
@@ -476,7 +476,7 @@
         // see body method for more info
         String path = getDigester().getMatch();
         PluginRules newRules = (PluginRules) getDigester().getRules();
-        List<Rule> rules = newRules.getDecoratedRules().match( namespace, path );
+        List<Rule> rules = newRules.getDecoratedRules().match( namespace, path, name, null );
         fireEndMethods( rules, namespace, name );
 
         // pop the stack of PluginRules instances, which
diff --git a/src/main/java/org/apache/commons/digester3/plugins/PluginRules.java b/src/main/java/org/apache/commons/digester3/plugins/PluginRules.java
index 87fc8b6..2fef3e1 100644
--- a/src/main/java/org/apache/commons/digester3/plugins/PluginRules.java
+++ b/src/main/java/org/apache/commons/digester3/plugins/PluginRules.java
@@ -26,6 +26,7 @@
 import org.apache.commons.digester3.Rules;
 import org.apache.commons.digester3.RulesBase;
 import org.apache.commons.logging.Log;
+import org.xml.sax.Attributes;
 
 /**
  * A custom digester Rules manager which must be used as the Rules object when using the plugins module functionality.
@@ -354,17 +355,9 @@
     }
 
     /**
-     * Return a List of all registered Rule instances that match the specified nodepath, 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.
-     * <p>
-     * 
-     * @param namespaceURI Namespace URI for which to select matching rules, or <code>null</code> to match regardless of
-     *            namespace URI
-     * @param path the path to the xml nodes to be matched.
-     * @return The List of all registered Rule instances that match the specified nodepath
+     * {@inheritDoc}
      */
-    public List<Rule> match( String namespaceURI, String path )
+    public List<Rule> match( String namespaceURI, String path, String name, Attributes attributes )
     {
         Log log = LogUtils.getLogger( digester );
         boolean debug = log.isDebugEnabled();
@@ -382,7 +375,7 @@
                 log.debug( "Path [" + path + "] delegated to parent." );
             }
 
-            matches = parent.match( namespaceURI, path );
+            matches = parent.match( namespaceURI, path, name, attributes );
 
             // Note that in the case where path equals mountPoint,
             // we deliberately return only the rules from the parent,
@@ -393,7 +386,7 @@
         else
         {
             log.debug( "delegating to decorated rules." );
-            matches = decoratedRules.match( namespaceURI, path );
+            matches = decoratedRules.match( namespaceURI, path, name, attributes );
         }
 
         return matches;
diff --git a/src/test/java/org/apache/commons/digester3/DigesterTestCase.java b/src/test/java/org/apache/commons/digester3/DigesterTestCase.java
index 599f7f9..1e5e863 100644
--- a/src/test/java/org/apache/commons/digester3/DigesterTestCase.java
+++ b/src/test/java/org/apache/commons/digester3/DigesterTestCase.java
@@ -285,15 +285,15 @@
     public void testRules()
     {
 
-        assertEquals( "Initial rules list is empty", 0, digester.getRules().match( null, "a" ).size() );
+        assertEquals( "Initial rules list is empty", 0, digester.getRules().match( null, "a", null, null ).size() );
         digester.addSetProperties( "a" );
-        assertEquals( "Add a matching rule", 1, digester.getRules().match( null, "a" ).size() );
+        assertEquals( "Add a matching rule", 1, digester.getRules().match( null, "a", null, null ).size() );
         digester.addSetProperties( "b" );
-        assertEquals( "Add a non-matching rule", 1, digester.getRules().match( null, "a" ).size() );
+        assertEquals( "Add a non-matching rule", 1, digester.getRules().match( null, "a", null, null ).size() );
         digester.addSetProperties( "a/b" );
-        assertEquals( "Add a non-matching nested rule", 1, digester.getRules().match( null, "a" ).size() );
+        assertEquals( "Add a non-matching nested rule", 1, digester.getRules().match( null, "a", null, null ).size() );
         digester.addSetProperties( "a/b" );
-        assertEquals( "Add a second matching rule", 2, digester.getRules().match( null, "a/b" ).size() );
+        assertEquals( "Add a second matching rule", 2, digester.getRules().match( null, "a/b", null, null ).size() );
 
     }
 
@@ -322,19 +322,19 @@
         digester.addRule( "*/c/d", new TestRule( "*/c/d" ) );
 
         // Test exact match
-        assertEquals( "Exact match takes precedence 1", 1, digester.getRules().match( null, "a/b/c/d" ).size() );
+        assertEquals( "Exact match takes precedence 1", 1, digester.getRules().match( null, "a/b/c/d", null, null ).size() );
         assertEquals( "Exact match takes precedence 2", "a/b/c/d",
-                      ( (TestRule) digester.getRules().match( null, "a/b/c/d" ).iterator().next() ).getIdentifier() );
+                      ( (TestRule) digester.getRules().match( null, "a/b/c/d", null, null ).iterator().next() ).getIdentifier() );
 
         // Test wildcard tail matching
-        assertEquals( "Wildcard tail matching rule 1", 1, digester.getRules().match( null, "a/b/d" ).size() );
+        assertEquals( "Wildcard tail matching rule 1", 1, digester.getRules().match( null, "a/b/d", null, null ).size() );
         assertEquals( "Wildcard tail matching rule 2", "*/d",
-                      ( (TestRule) digester.getRules().match( null, "a/b/d" ).iterator().next() ).getIdentifier() );
+                      ( (TestRule) digester.getRules().match( null, "a/b/d", null, null ).iterator().next() ).getIdentifier() );
 
         // Test the longest matching pattern rule
-        assertEquals( "Longest tail rule 1", 1, digester.getRules().match( null, "x/c/d" ).size() );
+        assertEquals( "Longest tail rule 1", 1, digester.getRules().match( null, "x/c/d", null, null ).size() );
         assertEquals( "Longest tail rule 2", "*/c/d",
-                      ( (TestRule) digester.getRules().match( null, "x/c/d" ).iterator().next() ).getIdentifier() );
+                      ( (TestRule) digester.getRules().match( null, "x/c/d", null, null ).iterator().next() ).getIdentifier() );
 
     }
 
diff --git a/src/test/java/org/apache/commons/digester3/ExtendedBaseRulesTestCase.java b/src/test/java/org/apache/commons/digester3/ExtendedBaseRulesTestCase.java
index 83b495d..d3dbbdd 100644
--- a/src/test/java/org/apache/commons/digester3/ExtendedBaseRulesTestCase.java
+++ b/src/test/java/org/apache/commons/digester3/ExtendedBaseRulesTestCase.java
@@ -80,7 +80,7 @@
         Iterator<Rule> it = null;
 
         // this should match just the exact since this has presidence
-        list = digester.getRules().match( null, "alpha/beta/gamma/delta" );
+        list = digester.getRules().match( null, "alpha/beta/gamma/delta", null, null );
 
         // all three rules should match
         assertEquals( "Testing basic parent mismatch (A)", 1, list.size() );
@@ -89,7 +89,7 @@
         assertEquals( "Testing basic parent mismatch (B)", "exact", ( (TestRule) it.next() ).getIdentifier() );
 
         // we don't have an exact match for this child so we should get the exact parent
-        list = digester.getRules().match( null, "alpha/beta/gamma/epsilon" );
+        list = digester.getRules().match( null, "alpha/beta/gamma/epsilon", null, null );
 
         // all three rules should match
         assertEquals( "Testing basic parent mismatch (C)", 1, list.size() );
@@ -98,7 +98,7 @@
         assertEquals( "Testing basic parent mismatch (D)", "exact_parent", ( (TestRule) it.next() ).getIdentifier() );
 
         // wild child overrides wild parent
-        list = digester.getRules().match( null, "alpha/omega/beta/gamma/epsilon" );
+        list = digester.getRules().match( null, "alpha/omega/beta/gamma/epsilon", null, null );
 
         // all three rules should match
         assertEquals( "Testing basic parent mismatch (E)", 1, list.size() );
@@ -107,7 +107,7 @@
         assertEquals( "Testing basic parent mismatch (F)", "wild_child", ( (TestRule) it.next() ).getIdentifier() );
 
         // nothing else matches so return wild parent
-        list = digester.getRules().match( null, "alpha/omega/beta/gamma/zeta" );
+        list = digester.getRules().match( null, "alpha/omega/beta/gamma/zeta", null, null );
 
         // all three rules should match
         assertEquals( "Testing basic parent mismatch (G)", 1, list.size() );
@@ -148,7 +148,7 @@
         Iterator<Rule> it = null;
 
         // test universal wild head
-        list = digester.getRules().match( null, "alpha/beta/gamma" );
+        list = digester.getRules().match( null, "alpha/beta/gamma", null, null );
 
         assertEquals( "Testing universal wildcard mismatch (A)", 2, list.size() );
 
@@ -158,7 +158,7 @@
                       ( (TestRule) it.next() ).getIdentifier() );
 
         // test universal parent
-        list = digester.getRules().match( null, "alpha/beta/gamma/epsilon" );
+        list = digester.getRules().match( null, "alpha/beta/gamma/epsilon", null, null );
 
         assertEquals( "Testing universal wildcard mismatch (D)", 2, list.size() );
 
@@ -168,7 +168,7 @@
         assertEquals( "Testing universal wildcard mismatch (F)", "exact2", ( (TestRule) it.next() ).getIdentifier() );
 
         // test universal parent
-        list = digester.getRules().match( null, "alpha/beta/gamma/zeta" );
+        list = digester.getRules().match( null, "alpha/beta/gamma/zeta", null, null );
 
         assertEquals( "Testing universal wildcard mismatch (G)", 2, list.size() );
 
@@ -179,7 +179,7 @@
                       ( (TestRule) it.next() ).getIdentifier() );
 
         // test wildcard universal parent
-        list = digester.getRules().match( null, "alpha/epsilon/beta/gamma/alpha" );
+        list = digester.getRules().match( null, "alpha/epsilon/beta/gamma/alpha", null, null );
 
         assertEquals( "Testing universal wildcard mismatch (J)", 2, list.size() );
 
@@ -190,7 +190,7 @@
                       ( (TestRule) it.next() ).getIdentifier() );
 
         // test wildcard universal parent
-        list = digester.getRules().match( null, "alpha/epsilon/beta/gamma/zeta" );
+        list = digester.getRules().match( null, "alpha/epsilon/beta/gamma/zeta", null, null );
 
         assertEquals( "Testing universal wildcard mismatch (M)", 2, list.size() );
 
@@ -228,7 +228,7 @@
         Iterator<Rule> it = null;
 
         // The universal wild will always match whatever else does
-        list = digester.getRules().match( null, "alpha/beta/gamma/delta" );
+        list = digester.getRules().match( null, "alpha/beta/gamma/delta", null, null );
 
         // all three rules should match
         assertEquals( "Testing wild mismatch (A)", 2, list.size() );
@@ -238,7 +238,7 @@
         assertEquals( "Testing wild mismatch (C)", "exact", ( (TestRule) it.next() ).getIdentifier() );
 
         // The universal wild will always match whatever else does
-        list = digester.getRules().match( null, "alpha/beta/gamma/epsilon" );
+        list = digester.getRules().match( null, "alpha/beta/gamma/epsilon", null, null );
 
         assertEquals( "Testing wild mismatch (D)", 2, list.size() );
 
@@ -248,7 +248,7 @@
 
         // The universal wild will always match whatever else does
         // we have no other non-universal matching so this will match the non-universal wild as well
-        list = digester.getRules().match( null, "alpha/gamma" );
+        list = digester.getRules().match( null, "alpha/gamma", null, null );
 
         assertEquals( "Testing wild mismatch (G)", 2, list.size() );
 
@@ -280,25 +280,25 @@
 
         List<Rule> list = null;
 
-        list = digester.getRules().match( null, "a" );
+        list = digester.getRules().match( null, "a", null, null );
 
         assertEquals( "Testing tail wrong size (A)", 1, list.size() );
         assertEquals( "Testing tail mismatch (B)", "a_tail", ( (TestRule) list.get( 0 ) ).getIdentifier() );
 
-        list = digester.getRules().match( null, "beta/a" );
+        list = digester.getRules().match( null, "beta/a", null, null );
 
         assertEquals( "Testing tail wrong size (C)", 1, list.size() );
         assertEquals( "Testing tail mismatch (D)", "a_tail", ( (TestRule) list.get( 0 ) ).getIdentifier() );
 
-        list = digester.getRules().match( null, "be/aaa" );
+        list = digester.getRules().match( null, "be/aaa", null, null );
 
         assertEquals( "Testing tail no matches (E)", 0, list.size() );
 
-        list = digester.getRules().match( null, "aaa" );
+        list = digester.getRules().match( null, "aaa", null, null );
 
         assertEquals( "Testing tail no matches (F)", 0, list.size() );
 
-        list = digester.getRules().match( null, "a/beta" );
+        list = digester.getRules().match( null, "a/beta", null, null );
 
         assertEquals( "Testing tail no matches (G)", 0, list.size() );
 
@@ -319,23 +319,23 @@
         digester.addRule( "a/b/c", new TestRule( "a-b-c" ) );
         digester.addRule( "a/b/?", new TestRule( "a-b-child" ) );
 
-        List<Rule> list = digester.getRules().match( null, "a/b/c" );
+        List<Rule> list = digester.getRules().match( null, "a/b/c", null, null );
 
         assertEquals( "Simple ancester matches (1)", 2, list.size() );
         assertEquals( "Univeral ancester mismatch (1)", "uni-a-b-star", ( (TestRule) list.get( 0 ) ).getIdentifier() );
         assertEquals( "Parent precedence failure", "a-b-c", ( (TestRule) list.get( 1 ) ).getIdentifier() );
 
-        list = digester.getRules().match( null, "a/b/b" );
+        list = digester.getRules().match( null, "a/b/b", null, null );
         assertEquals( "Simple ancester matches (2)", 2, list.size() );
         assertEquals( "Univeral ancester mismatch (2)", "uni-a-b-star", ( (TestRule) list.get( 0 ) ).getIdentifier() );
         assertEquals( "Child precedence failure", "a-b-child", ( (TestRule) list.get( 1 ) ).getIdentifier() );
 
-        list = digester.getRules().match( null, "a/b/d" );
+        list = digester.getRules().match( null, "a/b/d", null, null );
         assertEquals( "Simple ancester matches (3)", 2, list.size() );
         assertEquals( "Univeral ancester mismatch (3)", "uni-a-b-star", ( (TestRule) list.get( 0 ) ).getIdentifier() );
         assertEquals( "Ancester mismatch (1)", "a-b-child", ( (TestRule) list.get( 1 ) ).getIdentifier() );
 
-        list = digester.getRules().match( null, "a/b/d/e/f" );
+        list = digester.getRules().match( null, "a/b/d/e/f", null, null );
         assertEquals( "Simple ancester matches (4)", 2, list.size() );
         assertEquals( "Univeral ancester mismatch (4)", "uni-a-b-star", ( (TestRule) list.get( 0 ) ).getIdentifier() );
         assertEquals( "Ancester mismatch (2)", "a-b-star", ( (TestRule) list.get( 1 ) ).getIdentifier() );
@@ -348,22 +348,22 @@
         digester.addRule( "*/b/c/d", new TestRule( "star-b-c-d" ) );
         digester.addRule( "a/b/c", new TestRule( "a-b-c" ) );
 
-        list = digester.getRules().match( null, "a/b/c" );
+        list = digester.getRules().match( null, "a/b/c", null, null );
         assertEquals( "Wild ancester match (1)", 2, list.size() );
         assertEquals( "Univeral ancester mismatch (5)", "uni-star-a-b-star",
                       ( (TestRule) list.get( 0 ) ).getIdentifier() );
         assertEquals( "Match missed (1)", "a-b-c", ( (TestRule) list.get( 1 ) ).getIdentifier() );
 
-        list = digester.getRules().match( null, "b/c" );
+        list = digester.getRules().match( null, "b/c", null, null );
         assertEquals( "Wild ancester match (2)", 1, list.size() );
         assertEquals( "Match missed (2)", "star-b-c-star", ( (TestRule) list.get( 0 ) ).getIdentifier() );
 
-        list = digester.getRules().match( null, "a/b/c/d" );
+        list = digester.getRules().match( null, "a/b/c/d", null, null );
         assertEquals( "Wild ancester match (3)", 2, list.size() );
         assertEquals( "Match missed (3)", "uni-star-a-b-star", ( (TestRule) list.get( 0 ) ).getIdentifier() );
         assertEquals( "Match missed (4)", "star-b-c-d", ( (TestRule) list.get( 1 ) ).getIdentifier() );
 
-        list = digester.getRules().match( null, "b/b/c/e/d" );
+        list = digester.getRules().match( null, "b/b/c/e/d", null, null );
         assertEquals( "Wild ancester match (2)", 1, list.size() );
         assertEquals( "Match missed (5)", "star-b-c-star", ( (TestRule) list.get( 0 ) ).getIdentifier() );
     }
@@ -376,19 +376,19 @@
 
         digester.addRule( "a/b/c/d/*", new TestRule( "a-b-c-d-star" ) );
 
-        List<Rule> list = digester.getRules().match( null, "a/b/c/d/e" );
+        List<Rule> list = digester.getRules().match( null, "a/b/c/d/e", null, null );
         assertEquals( "Long match (1)", 1, list.size() );
         assertEquals( "Match missed (1)", "a-b-c-d-star", ( (TestRule) list.get( 0 ) ).getIdentifier() );
 
-        list = digester.getRules().match( null, "a/b/c/d/e/f" );
+        list = digester.getRules().match( null, "a/b/c/d/e/f", null, null );
         assertEquals( "Long match (2)", 1, list.size() );
         assertEquals( "Match missed (2)", "a-b-c-d-star", ( (TestRule) list.get( 0 ) ).getIdentifier() );
 
-        list = digester.getRules().match( null, "a/b/c/d/e/f/g" );
+        list = digester.getRules().match( null, "a/b/c/d/e/f/g", null, null );
         assertEquals( "Long match (3)", 1, list.size() );
         assertEquals( "Match missed (3)", "a-b-c-d-star", ( (TestRule) list.get( 0 ) ).getIdentifier() );
 
-        list = digester.getRules().match( null, "a/b/c/d" );
+        list = digester.getRules().match( null, "a/b/c/d", null, null );
         assertEquals( "Long match (4)", 0, list.size() );
     }
 
@@ -400,7 +400,7 @@
         digester.addRule( "!instructors/*", new TestRule( "instructors" ) );
         digester.addRule( "!instructor/*", new TestRule( "instructor" ) );
 
-        List<Rule> list = digester.getRules().match( null, "instructors" );
+        List<Rule> list = digester.getRules().match( null, "instructors", null, null );
         assertEquals( "Only expect to match instructors", 1, list.size() );
         assertEquals( "Instructors expected", "instructors", ( (TestRule) list.get( 0 ) ).getIdentifier() );
 
@@ -413,7 +413,7 @@
 
         digester.addRule( "!instructors/*", new TestRule( "instructors" ) );
 
-        List<Rule> list = digester.getRules().match( null, "/tosh/instructors/fiddlesticks" );
+        List<Rule> list = digester.getRules().match( null, "/tosh/instructors/fiddlesticks", null, null );
         assertEquals( "No matches expected", 0, list.size() );
 
     }
diff --git a/src/test/java/org/apache/commons/digester3/RegexRulesTestCase.java b/src/test/java/org/apache/commons/digester3/RegexRulesTestCase.java
index 2ec70bf..6b5f29b 100644
--- a/src/test/java/org/apache/commons/digester3/RegexRulesTestCase.java
+++ b/src/test/java/org/apache/commons/digester3/RegexRulesTestCase.java
@@ -58,13 +58,13 @@
 
         // now test a few patterns
         // check that all are return in the order which they were added
-        List<Rule> matches = rules.match( "", "x/g/e" );
+        List<Rule> matches = rules.match( "", "x/g/e", null, null );
         assertEquals( "Wrong number of rules returned (1)", 3, matches.size() );
         assertEquals( "Rule Out Of Order (1)", "alpha", ( (TestRule) matches.get( 0 ) ).getIdentifier() );
         assertEquals( "Rule Out Of Order (2)", "beta", ( (TestRule) matches.get( 1 ) ).getIdentifier() );
         assertEquals( "Rule Out Of Order (3)", "gamma", ( (TestRule) matches.get( 2 ) ).getIdentifier() );
 
-        matches = rules.match( "", "/a" );
+        matches = rules.match( "", "/a", null, null );
         assertEquals( "Wrong number of rules returned (2)", 3, matches.size() );
         assertEquals( "Rule Out Of Order (4)", "alpha", ( (TestRule) matches.get( 0 ) ).getIdentifier() );
         assertEquals( "Rule Out Of Order (5)", "beta", ( (TestRule) matches.get( 1 ) ).getIdentifier() );
@@ -91,10 +91,10 @@
 
         // now test a few patterns
         // check that all are return in the order which they were added
-        List<Rule> matches = rules.match( "", "/b/c" );
+        List<Rule> matches = rules.match( "", "/b/c", null, null );
         assertEquals( "Wrong number of rules returned (1)", 0, matches.size() );
 
-        matches = rules.match( "", "/b/c/f" );
+        matches = rules.match( "", "/b/c/f", null, null );
         assertEquals( "Wrong number of rules returned (2)", 0, matches.size() );
     }
 
@@ -118,11 +118,11 @@
 
         // now test a few patterns
         // check that all are return in the order which they were added
-        List<Rule> matches = rules.match( "", "/match" );
+        List<Rule> matches = rules.match( "", "/match", null, null );
         assertEquals( "Wrong number of rules returned (1)", 1, matches.size() );
         assertEquals( "Wrong Rule (1)", "beta", ( (TestRule) matches.get( 0 ) ).getIdentifier() );
 
-        matches = rules.match( "", "/a/match" );
+        matches = rules.match( "", "/a/match", null, null );
         assertEquals( "Wrong Rule (2)", "beta", ( (TestRule) matches.get( 0 ) ).getIdentifier() );
     }
 
@@ -151,7 +151,7 @@
         assertEquals( "Rule Out Of Order (2)", "beta", ( (TestRule) matches.get( 1 ) ).getIdentifier() );
         assertEquals( "Rule Out Of Order (3)", "gamma", ( (TestRule) matches.get( 2 ) ).getIdentifier() );
 
-        matches = rules.match( "", "/eggs" );
+        matches = rules.match( "", "/eggs", null, null );
         assertEquals( "Wrong number of rules returned (2)", 3, matches.size() );
         assertEquals( "Rule Out Of Order (4)", "alpha", ( (TestRule) matches.get( 0 ) ).getIdentifier() );
         assertEquals( "Rule Out Of Order (5)", "beta", ( (TestRule) matches.get( 1 ) ).getIdentifier() );
@@ -161,7 +161,7 @@
         matches = rules.rules();
         assertEquals( "Wrong number of rules returned (3)", 0, matches.size() );
 
-        matches = rules.match( "", "/eggs" );
+        matches = rules.match( "", "/eggs", null, null );
         assertEquals( "Wrong number of rules returned (4)", 0, matches.size() );
     }
 
diff --git a/src/test/java/org/apache/commons/digester3/RulesBaseTestCase.java b/src/test/java/org/apache/commons/digester3/RulesBaseTestCase.java
index a8c535c..4667fd6 100644
--- a/src/test/java/org/apache/commons/digester3/RulesBaseTestCase.java
+++ b/src/test/java/org/apache/commons/digester3/RulesBaseTestCase.java
@@ -101,15 +101,15 @@
 
         // perform tests
 
-        assertEquals( "Initial rules list is empty", 0, digester.getRules().match( null, "a" ).size() );
+        assertEquals( "Initial rules list is empty", 0, digester.getRules().match( null, "a", null, null ).size() );
         digester.addSetProperties( "a" );
-        assertEquals( "Add a matching rule", 1, digester.getRules().match( null, "a" ).size() );
+        assertEquals( "Add a matching rule", 1, digester.getRules().match( null, "a", null, null ).size() );
         digester.addSetProperties( "b" );
-        assertEquals( "Add a non-matching rule", 1, digester.getRules().match( null, "a" ).size() );
+        assertEquals( "Add a non-matching rule", 1, digester.getRules().match( null, "a", null, null ).size() );
         digester.addSetProperties( "a/b" );
-        assertEquals( "Add a non-matching nested rule", 1, digester.getRules().match( null, "a" ).size() );
+        assertEquals( "Add a non-matching nested rule", 1, digester.getRules().match( null, "a", null, null ).size() );
         digester.addSetProperties( "a/b" );
-        assertEquals( "Add a second matching rule", 2, digester.getRules().match( null, "a/b" ).size() );
+        assertEquals( "Add a second matching rule", 2, digester.getRules().match( null, "a/b", null, null ).size() );
 
         // clean up
         digester.getRules().clear();
@@ -144,27 +144,27 @@
         digester.addRule( "*/c/d", new TestRule( "*/c/d" ) );
 
         // Test exact match
-        assertEquals( "Exact match takes precedence 1", 1, digester.getRules().match( null, "a/b/c/d" ).size() );
+        assertEquals( "Exact match takes precedence 1", 1, digester.getRules().match( null, "a/b/c/d", null, null ).size() );
         assertEquals( "Exact match takes precedence 2", "a/b/c/d",
-                      ( (TestRule) digester.getRules().match( null, "a/b/c/d" ).iterator().next() ).getIdentifier() );
+                      ( (TestRule) digester.getRules().match( null, "a/b/c/d", null, null ).iterator().next() ).getIdentifier() );
 
         // Test wildcard tail matching
-        assertEquals( "Wildcard tail matching rule 1", 1, digester.getRules().match( null, "a/b/d" ).size() );
+        assertEquals( "Wildcard tail matching rule 1", 1, digester.getRules().match( null, "a/b/d", null, null ).size() );
         assertEquals( "Wildcard tail matching rule 2", "*/d",
-                      ( (TestRule) digester.getRules().match( null, "a/b/d" ).iterator().next() ).getIdentifier() );
+                      ( (TestRule) digester.getRules().match( null, "a/b/d", null, null ).iterator().next() ).getIdentifier() );
 
         // Test the longest matching pattern rule
-        assertEquals( "Longest tail rule 1", 1, digester.getRules().match( null, "x/c/d" ).size() );
+        assertEquals( "Longest tail rule 1", 1, digester.getRules().match( null, "x/c/d", null, null ).size() );
         assertEquals( "Longest tail rule 2", "*/c/d",
-                      ( (TestRule) digester.getRules().match( null, "x/c/d" ).iterator().next() ).getIdentifier() );
+                      ( (TestRule) digester.getRules().match( null, "x/c/d", null, null ).iterator().next() ).getIdentifier() );
 
         // Test wildcard tail matching at the top level,
         // i.e. the wildcard is nothing
         digester.addRule( "*/a", new TestRule( "*/a" ) );
-        assertEquals( "Wildcard tail matching rule 3", 1, digester.getRules().match( null, "a" ).size() );
+        assertEquals( "Wildcard tail matching rule 3", 1, digester.getRules().match( null, "a", null, null ).size() );
 
         assertEquals( "Wildcard tail matching rule 3 (match too much)", 0,
-                      digester.getRules().match( null, "aa" ).size() );
+                      digester.getRules().match( null, "aa", null, null ).size() );
         // clean up
         digester.getRules().clear();
 
@@ -192,7 +192,7 @@
         list = digester.getRules().rules();
 
         // test that matching null namespace brings back namespace and non-namespace rules
-        list = digester.getRules().match( null, "alpha/beta/gamma" );
+        list = digester.getRules().match( null, "alpha/beta/gamma", null, null );
 
         assertEquals( "Null namespace match (A)", 2, list.size() );
 
@@ -201,7 +201,7 @@
         assertEquals( "Null namespace match (C)", "Euclidean-Namespace", ( (TestRule) it.next() ).getIdentifier() );
 
         // test that matching euclid namespace brings back namespace and non-namespace rules
-        list = digester.getRules().match( "euclidean", "alpha/beta/gamma" );
+        list = digester.getRules().match( "euclidean", "alpha/beta/gamma", null, null );
 
         assertEquals( "Matching namespace match (A)", 2, list.size() );
 
@@ -210,7 +210,7 @@
         assertEquals( "Matching namespace match (C)", "Euclidean-Namespace", ( (TestRule) it.next() ).getIdentifier() );
 
         // test that matching another namespace brings back only non-namespace rule
-        list = digester.getRules().match( "hyperbolic", "alpha/beta/gamma" );
+        list = digester.getRules().match( "hyperbolic", "alpha/beta/gamma", null, null );
 
         assertEquals( "Non matching namespace match (A)", 1, list.size() );
 
@@ -240,7 +240,7 @@
         digester.addRule( "alpha/beta/gamma", new TestRule( "three" ) );
 
         // test that rules are returned in set order
-        List<Rule> list = digester.getRules().match( null, "alpha/beta/gamma" );
+        List<Rule> list = digester.getRules().match( null, "alpha/beta/gamma", null, null );
 
         assertEquals( "Testing ordering mismatch (A)", 3, list.size() );
 
@@ -269,7 +269,7 @@
         digester.addRule( "beta/gamma/alpha", new TestRule( "three" ) );
 
         // test that rules are returned in set order
-        List<Rule> list = digester.getRules().match( null, "alpha/beta/gamma" );
+        List<Rule> list = digester.getRules().match( null, "alpha/beta/gamma", null, null );
 
         assertEquals( "Testing number of matches", 1, list.size() );
 
diff --git a/src/test/java/org/apache/commons/digester3/WithDefaultsRulesWrapperTestCase.java b/src/test/java/org/apache/commons/digester3/WithDefaultsRulesWrapperTestCase.java
index 188aa91..87b75c6 100644
--- a/src/test/java/org/apache/commons/digester3/WithDefaultsRulesWrapperTestCase.java
+++ b/src/test/java/org/apache/commons/digester3/WithDefaultsRulesWrapperTestCase.java
@@ -95,13 +95,13 @@
         rules.addDefault( new TestRule( "Roger" ) );
         rules.addDefault( new TestRule( "Rabbit" ) );
 
-        List<Rule> matches = rules.match( "", "alpha" );
+        List<Rule> matches = rules.match( "", "alpha", null, null );
         assertEquals( "Wrong size (1)", 3, matches.size() );
         assertEquals( "Wrong order (1)", "Tom", ( (TestRule) matches.get( 0 ) ).getIdentifier() );
         assertEquals( "Wrong order (2)", "Dick", ( (TestRule) matches.get( 1 ) ).getIdentifier() );
         assertEquals( "Wrong order (3)", "Harry", ( (TestRule) matches.get( 2 ) ).getIdentifier() );
 
-        matches = rules.match( "", "not-alpha" );
+        matches = rules.match( "", "not-alpha", null, null );
         assertEquals( "Wrong size (2)", 2, matches.size() );
         assertEquals( "Wrong order (4)", "Roger", ( (TestRule) matches.get( 0 ) ).getIdentifier() );
         assertEquals( "Wrong order (5)", "Rabbit", ( (TestRule) matches.get( 1 ) ).getIdentifier() );