    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    }