001    /* $Id: RegexRules.java 729097 2008-12-23 20:37:19Z rahul $
002     *
003     * Licensed to the Apache Software Foundation (ASF) under one or more
004     * contributor license agreements.  See the NOTICE file distributed with
005     * this work for additional information regarding copyright ownership.
006     * The ASF licenses this file to You under the Apache License, Version 2.0
007     * (the "License"); you may not use this file except in compliance with
008     * the License.  You may obtain a copy of the License at
009     * 
010     *      http://www.apache.org/licenses/LICENSE-2.0
011     * 
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */ 
018    
019    package org.apache.commons.digester;
020    
021    import java.util.ArrayList;
022    import java.util.List;
023    
024    /**
025     * <p>Rules implementation that uses regular expression matching for paths.</p>
026     *
027     * <p>The regex implementation is pluggable, allowing different strategies to be used.
028     * The basic way that this class work does not vary.
029     * All patterns are tested to see if they match the path using the regex matcher.
030     * All those that do are return in the order which the rules were added.</p>
031     *
032     * @since 1.5
033     */
034    
035    public class RegexRules extends AbstractRulesImpl {
036    
037        // --------------------------------------------------------- Fields
038        
039        /** All registered <code>Rule</code>'s  */
040        private ArrayList<RegisteredRule> registeredRules = new ArrayList<RegisteredRule>();
041        /** The regex strategy used by this RegexRules */
042        private RegexMatcher matcher;
043    
044        // --------------------------------------------------------- Constructor
045    
046        /**
047         * Construct sets the Regex matching strategy.
048         *
049         * @param matcher the regex strategy to be used, not null
050         * @throws IllegalArgumentException if the strategy is null
051         */
052        public RegexRules(RegexMatcher matcher) {
053            setRegexMatcher(matcher);
054        }
055    
056        // --------------------------------------------------------- Properties
057        
058        /** 
059         * Gets the current regex matching strategy.
060         */
061        public RegexMatcher getRegexMatcher() {
062            return matcher;
063        }
064        
065        /** 
066         * Sets the current regex matching strategy.
067         *
068         * @param matcher use this RegexMatcher, not null
069         * @throws IllegalArgumentException if the strategy is null
070         */
071        public void setRegexMatcher(RegexMatcher matcher) {
072            if (matcher == null) {
073                throw new IllegalArgumentException("RegexMatcher must not be null.");
074            }
075            this.matcher = matcher;
076        }
077        
078        // --------------------------------------------------------- Public Methods
079    
080        /**
081         * Register a new Rule instance matching the specified pattern.
082         *
083         * @param pattern Nesting pattern to be matched for this Rule
084         * @param rule Rule instance to be registered
085         */
086        protected void registerRule(String pattern, Rule rule) {
087            registeredRules.add(new RegisteredRule(pattern, rule));
088        }
089    
090        /**
091         * Clear all existing Rule instance registrations.
092         */
093        public void clear() {
094            registeredRules.clear();
095        }
096    
097        /**
098         * Finds matching rules by using current regex matching strategy.
099         * The rule associated with each path that matches is added to the list of matches.
100         * The order of matching rules is the same order that they were added.
101         *
102         * @param namespaceURI Namespace URI for which to select matching rules,
103         *  or <code>null</code> to match regardless of namespace URI
104         * @param pattern Nesting pattern to be matched
105         * @return a list of matching <code>Rule</code>'s
106         */
107        public List<Rule> match(String namespaceURI, String pattern) {
108            //
109            // not a particularly quick implementation
110            // regex is probably going to be slower than string equality
111            // so probably should have a set of strings
112            // and test each only once
113            //
114            // XXX FIX ME - Time And Optimize
115            //
116            ArrayList<Rule> rules = new ArrayList<Rule>(registeredRules.size());
117            for (RegisteredRule rr : registeredRules) {
118                if (matcher.match(pattern, rr.pattern)) {
119                    rules.add(rr.rule);
120                }
121            }
122            return rules;
123        }
124    
125    
126        /**
127         * Return a List of all registered Rule instances, or a zero-length List
128         * if there are no registered Rule instances.  If more than one Rule
129         * instance has been registered, they <strong>must</strong> be returned
130         * in the order originally registered through the <code>add()</code>
131         * method.
132         */
133        public List<Rule> rules() {
134            ArrayList<Rule> rules = new ArrayList<Rule>(registeredRules.size());
135            for (RegisteredRule rr : registeredRules) {
136                rules.add(rr.rule);
137            }
138            return rules;
139        }
140        
141        /** Used to associate rules with paths in the rules list */
142        private class RegisteredRule {
143            String pattern;
144            Rule rule;
145            
146            RegisteredRule(String pattern, Rule rule) {
147                this.pattern = pattern;
148                this.rule = rule;
149            }
150        }
151    }