    001    /* $Id: WithDefaultsRulesWrapper.java 729104 2008-12-23 20:45:23Z 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><code>Rules</code> <em>Decorator</em> that returns default rules
    026     * when no matches are returned by the wrapped implementation.</p>
    027     *
    028     * <p>This allows default <code>Rule</code> instances to be added to any
    029     * existing <code>Rules</code> implementation. These default <code>Rule</code>
    030     * instances will be returned for any match for which the wrapped
    031     * implementation does not return any matches.</p>
    032     * <p> For example,
    033     * <pre>
    034     *   Rule alpha;
    035     *   ...
    036     *   WithDefaultsRulesWrapper rules = new WithDefaultsRulesWrapper(new BaseRules());
    037     *   rules.addDefault(alpha);
    038     *   ...
    039     *   digester.setRules(rules);
    040     *   ...
    041     * </pre>
    042     * when a pattern does not match any other rule, then rule alpha will be called.
    043     * </p>
    044     * <p><code>WithDefaultsRulesWrapper</code> follows the <em>Decorator</em> pattern.</p>
    045     *
    046     * @since 1.6
    047     */
    048
    049    public class WithDefaultsRulesWrapper implements Rules {
    050
    051        // --------------------------------------------------------- Fields
    052
    053        /** The Rules implementation that this class wraps. */
    054        private Rules wrappedRules;
    055        /** Rules to be fired when the wrapped implementations returns none. */
    056        private List<Rule> defaultRules = new ArrayList<Rule>();
    057        /** All rules (preserves order in which they were originally added) */
    058        private List<Rule> allRules = new ArrayList<Rule>();
    059
    060        // --------------------------------------------------------- Constructor
    061
    062        /**
    063         * Base constructor.
    064         *
    065         * @param wrappedRules the wrapped <code>Rules</code> implementation, not null
    066         * @throws IllegalArgumentException when <code>wrappedRules</code> is null
    067         */
    068        public WithDefaultsRulesWrapper(Rules wrappedRules) {
    069            if (wrappedRules == null) {
    070                throw new IllegalArgumentException("Wrapped rules must not be null");
    071            }
    072            this.wrappedRules = wrappedRules;
    073        }
    074
    075        // --------------------------------------------------------- Properties
    076
    077        /** Gets digester using these Rules */
    078        public Digester getDigester() {
    079            return wrappedRules.getDigester();
    080        }
    081
    082        /** Sets digeseter using these Rules */
    083        public void setDigester(Digester digester) {
    084            wrappedRules.setDigester(digester);
    085            for (Rule rule : defaultRules) {
    086                rule.setDigester(digester);
    087            }
    088        }
    089
    090        /** Gets namespace to apply to Rule's added */
    091        public String getNamespaceURI() {
    092            return wrappedRules.getNamespaceURI();
    093        }
    094
    095        /** Sets namespace to apply to Rule's added subsequently */
    096        public void setNamespaceURI(String namespaceURI) {
    097            wrappedRules.setNamespaceURI(namespaceURI);
    098        }
    099
    100        /** Gets Rule's which will be fired when the wrapped implementation returns no matches */
    101        public List<Rule> getDefaults() {
    102            return defaultRules;
    103        }
    104
    105        // --------------------------------------------------------- Public Methods
    106
    107        public List<Rule> match(String pattern) {
    108            return match("", pattern);
    109        }
    110
    111        /**
    112         * Return list of rules matching given pattern.
    113         * If wrapped implementation returns any matches return those.
    114         * Otherwise, return default matches.
    115         */
    116        public List<Rule> match(String namespaceURI, String pattern) {
    117            List<Rule> matches = wrappedRules.match(namespaceURI, pattern);
    118            if (matches ==  null || matches.isEmpty()) {
    119                // a little bit of defensive programming
    120                return new ArrayList<Rule>(defaultRules);
    121            }
    122            // otherwise
    123            return matches;
    124        }
    125
    126        /** Adds a rule to be fired when wrapped implementation returns no matches */
    127        public void addDefault(Rule rule) {
    128            // set up rule
    129            if (wrappedRules.getDigester() != null) {
    130                rule.setDigester(wrappedRules.getDigester());
    131            }
    132
    133            if (wrappedRules.getNamespaceURI() != null) {
    134                rule.setNamespaceURI(wrappedRules.getNamespaceURI());
    135            }
    136
    137            defaultRules.add(rule);
    138            allRules.add(rule);
    139        }
    140
    141        /** Gets all rules */
    142        public List<Rule> rules() {
    143            return allRules;
    144        }
    145
    146        /** Clears all Rule's */
    147        public void clear() {
    148            wrappedRules.clear();
    149            allRules.clear();
    150            defaultRules.clear();
    151        }
    152
    153        /**
    154         * Adds a Rule to be fired on given pattern.
    155         * Pattern matching is delegated to wrapped implementation.
    156         */
    157        public void add(String pattern, Rule rule) {
    158            wrappedRules.add(pattern, rule);
    159            allRules.add(rule);
    160        }
    161    }