001 /* $Id: WithDefaultsRulesWrapper.java 992060 2010-09-02 19:09:47Z simonetripodi $
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 }