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