commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rdon...@apache.org
Subject cvs commit: jakarta-commons/digester/src/test/org/apache/commons/digester EBRTestCase.java
Date Wed, 12 Mar 2003 22:10:52 GMT
rdonkin     2003/03/12 14:10:52

  Modified:    digester/src/java/org/apache/commons/digester
                        ExtendedBaseRules.java
               digester/src/test/org/apache/commons/digester
                        EBRTestCase.java
  Log:
  Fix for bug #16350. This adds another kind of wildcard match - and ancester tail match.
This allows matching patterns such as a/b/*. Based on a patch submitted by Kelvin Tan
  
  Revision  Changes    Path
  1.5       +63 -12    jakarta-commons/digester/src/java/org/apache/commons/digester/ExtendedBaseRules.java
  
  Index: ExtendedBaseRules.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/digester/src/java/org/apache/commons/digester/ExtendedBaseRules.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ExtendedBaseRules.java	2 Feb 2003 16:09:53 -0000	1.4
  +++ ExtendedBaseRules.java	12 Mar 2003 22:10:50 -0000	1.5
  @@ -102,7 +102,7 @@
    *     to call.
    *     <ul>
    *     <li><code>"a/b/c/?"</code> matches any child whose parent matches
  - *         <code>"a/b/c"</code>.  Exact parent rules take precendence over
  + *         <code>"a/b/c"</code>.  Exact parent rules take precedence over
    *         standard wildcard tail endings.</li>
    *     <li><code>"*&#47;a/b/c/?"</code> matches any child whose parent
matches
    *         "*&#47;a/b/c"</code>.  The longest matching still applies to parent
  @@ -110,7 +110,18 @@
    *         that standard wildcard matches with the same level of depth are
    *         chosen in preference.</li>
    *     </ul></li>
  - * <li><em>Universal Wildcard Match </em> -  Any pattern prefixed with
'!'
  + * <li><em>Ancester Match</em> - Will match elements who parentage includes

  + * 	a particular sequence of elements.
  + * 	<ul>
  + *      <li><code>"a/b/*"</code> matches any element whose parentage
path starts with
  + *	    'a' then 'b'. Exact parent and parent match rules take precedence. The longest
  + *           ancester match will take precedence.</li>
  + *	<li><code>"*&#47;a/b/*"</code> matches any elements whose parentage
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>
  + * </li>
  + * <li><em>Universal Wildcard Match</em> -  Any pattern prefixed with
'!'
    *     bypasses the longest matching rule.  Even if there is an exact match
    *     or a longer wildcard match,  patterns prefixed by '!' will still be
    *     tested to see if they match.  This can be used for example to specify
  @@ -122,6 +133,10 @@
    *         matching <code>"a/b"</code>.</li>
    *     <li>Pattern <code>"!*&#47;a/b/?"</code> matches any child
of a parent
    *         matching <code>"!*&#47;a/b"</code></li>
  + *     <li>Pattern <code>"!a/b/*"</code> matches any element whose parentage
path starts with
  + *	    "a" then "b".</li>
  + *     <li>Pattern <code>"!*&#47;a/b/*"</code> matches any elements
whose parentage path contains
  + *          'a/b'</li>
    *    </ul></li>
    * <li><em>Wild Match</em>
    *     <ul>
  @@ -207,7 +222,6 @@
        * @param pattern Nesting pattern to be matched
        */
       public List match(String namespace, String pattern) {
  -
           // calculate the pattern of the parent
           // (if the element has one)
           String parentPattern = "";
  @@ -266,6 +280,16 @@
                       // we have a match!
                       // so ignore all basic matches from now on
                       ignoreBasicMatches = true;
  +                    
  +                } else {
  +                    // we don't have a match yet - so try exact ancester
  +                    //
  +                    rulesList = findExactAncesterMatch(parentPattern);
  +                    if (rulesList != null) {
  +                        // we have a match!
  +                        // so ignore all basic matches from now on
  +                        ignoreBasicMatches = true;
  +                    }
                   }
               }
           }
  @@ -289,22 +313,32 @@
                   key = key.substring(1, key.length());
               }
   
  -
  +                    
               // don't need to check exact matches
  -            if (key.startsWith("*/")) {
  +            if (key.startsWith("*/") || (isUniversal && key.endsWith("/*"))) {
   
                   boolean parentMatched = false;
                   boolean basicMatched = false;
  +                boolean ancesterMatched = false;
                   if (key.endsWith("/?")) {
                       // try for a parent match
                       parentMatched = parentMatch(key, pattern, parentPattern);
   
  +                } else if (key.endsWith("/*")) {
  +                    // check for ancester match
  +                    int patternStart = 0;
  +                    if (key.startsWith("*/")) {
  +                        patternStart = 2;
  +                    }
  +                    ancesterMatched = 
  +                        (pattern.lastIndexOf(key.substring(patternStart, key.length() -
2)) > -1);
  +                                    
                   } else {
                       // try for a base match
                       basicMatched = basicMatch(key, pattern);
                   }
   
  -                if (parentMatched || basicMatched) {
  +                if (parentMatched || basicMatched || ancesterMatched) {
                       if (isUniversal) {
                           // universal rules go straight in
                           // (no longest matching rule)
  @@ -318,7 +352,7 @@
                               // ensure that all parent matches are SHORTER
                               // than rules with same level of matching
                               int keyLength = key.length();
  -                            if (parentMatched) {
  +                            if (parentMatched || ancesterMatched) {
                                   keyLength--;
                               }
   
  @@ -408,5 +442,22 @@
           return (pattern.equals(key.substring(2)) ||
                   pattern.endsWith(key.substring(1)));
       }
  -
  +    
  +    /**
  +     * Finds an exact ancester match for given pattern
  +     */
  +    private List findExactAncesterMatch(String parentPattern) {
  +        List matchingRules = null;
  +        int lastIndex = parentPattern.length();
  +        while (lastIndex-- > 0) {
  +            lastIndex = parentPattern.lastIndexOf('/', lastIndex);
  +            if (lastIndex > 0) {
  +                matchingRules = (List) this.cache.get(parentPattern.substring(0, lastIndex)
+ "/*");
  +                if (matchingRules != null) {
  +                    return matchingRules;
  +                }
  +            }
  +        }
  +        return null;
  +    }
   }
  
  
  
  1.7       +67 -4     jakarta-commons/digester/src/test/org/apache/commons/digester/EBRTestCase.java
  
  Index: EBRTestCase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/digester/src/test/org/apache/commons/digester/EBRTestCase.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- EBRTestCase.java	2 Feb 2003 15:52:14 -0000	1.6
  +++ EBRTestCase.java	12 Mar 2003 22:10:51 -0000	1.7
  @@ -384,4 +384,67 @@
           digester.getRules().clear();
   
       }
  +    
  +    public void testAncesterMatch() throws Exception {
  +        System.out.println("Starting ancester match...");
  +        // test fixed root ancester
  +        digester.getRules().clear();
  +        
  +        digester.addRule("!a/b/*", new TestRule("uni-a-b-star"));
  +        digester.addRule("a/b/*", new TestRule("a-b-star"));
  +        digester.addRule("a/b/c", new TestRule("a-b-c"));
  +        digester.addRule("a/b/?", new TestRule("a-b-child"));
  +        
  +        List
  +        list = digester.getRules().match(null, "a/b/c");
  +        
  +        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");        
  +        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");        
  +        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");        
  +        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());
  +        
  +        // test wild root ancester
  +        digester.getRules().clear();
  +
  +        digester.addRule("!*/a/b/*", new TestRule("uni-star-a-b-star"));
  +        digester.addRule("*/b/c/*", new TestRule("star-b-c-star"));
  +        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");  
  +        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");  
  +        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"); 
  +        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"); 
  +        assertEquals("Wild ancester match (2)", 1, list.size());
  +        assertEquals("Match missed (5)", "star-b-c-star" , ((TestRule) list.get(0)).getIdentifier());
   
  +        System.out.println("Finished ancester match.");
  +    }
   }
  
  
  

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


Mime
View raw message