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 * <code>Rules</code> <em>Decorator</em> that returns default rules when no matches are returned by the wrapped
030 * implementation.
031 * </p>
032 * <p>
033 * This allows default <code>Rule</code> instances to be added to any existing <code>Rules</code> implementation. These
034 * default <code>Rule</code> instances will be returned for any match for which the wrapped implementation does not
035 * return any matches.
036 * </p>
037 * <p>
038 * For example,
039 *
040 * <pre>
041 * Rule alpha;
042 * ...
043 * WithDefaultsRulesWrapper rules = new WithDefaultsRulesWrapper(new BaseRules());
044 * rules.addDefault(alpha);
045 * ...
046 * digester.setRules(rules);
047 * ...
048 * </pre>
049 *
050 * when a pattern does not match any other rule, then rule alpha will be called.
051 * </p>
052 * <p>
053 * <code>WithDefaultsRulesWrapper</code> follows the <em>Decorator</em> pattern.
054 * </p>
055 *
056 * @since 1.6
057 */
058 public class WithDefaultsRulesWrapper
059 implements Rules
060 {
061
062 // --------------------------------------------------------- Fields
063
064 /** The Rules implementation that this class wraps. */
065 private Rules wrappedRules;
066
067 /** Rules to be fired when the wrapped implementations returns none. */
068 private List<Rule> defaultRules = new ArrayList<Rule>();
069
070 /** All rules (preserves order in which they were originally added) */
071 private List<Rule> allRules = new ArrayList<Rule>();
072
073 // --------------------------------------------------------- Constructor
074
075 /**
076 * Base constructor.
077 *
078 * @param wrappedRules the wrapped <code>Rules</code> implementation, not null
079 */
080 public WithDefaultsRulesWrapper( Rules wrappedRules )
081 {
082 if ( wrappedRules == null )
083 {
084 throw new IllegalArgumentException( "Wrapped rules must not be null" );
085 }
086 this.wrappedRules = wrappedRules;
087 }
088
089 // --------------------------------------------------------- Properties
090
091 /**
092 * {@inheritDoc}
093 */
094 public Digester getDigester()
095 {
096 return wrappedRules.getDigester();
097 }
098
099 /**
100 * {@inheritDoc}
101 */
102 public void setDigester( Digester digester )
103 {
104 wrappedRules.setDigester( digester );
105 for ( Rule rule : defaultRules )
106 {
107 rule.setDigester( digester );
108 }
109 }
110
111 /**
112 * {@inheritDoc}
113 */
114 public String getNamespaceURI()
115 {
116 return wrappedRules.getNamespaceURI();
117 }
118
119 /**
120 * {@inheritDoc}
121 */
122 public void setNamespaceURI( String namespaceURI )
123 {
124 wrappedRules.setNamespaceURI( namespaceURI );
125 }
126
127 /**
128 * Gets Rule's which will be fired when the wrapped implementation returns no matches
129 *
130 * @return Rule's which will be fired when the wrapped implementation returns no matches
131 **/
132 public List<Rule> getDefaults()
133 {
134 return defaultRules;
135 }
136
137 // --------------------------------------------------------- Public Methods
138
139 /**
140 * {@inheritDoc}
141 */
142 public List<Rule> match( String namespaceURI, String pattern, String name, Attributes attributes )
143 {
144 List<Rule> matches = wrappedRules.match( namespaceURI, pattern, name, attributes );
145 if ( matches == null || matches.isEmpty() )
146 {
147 // a little bit of defensive programming
148 return new ArrayList<Rule>( defaultRules );
149 }
150 // otherwise
151 return matches;
152 }
153
154 /**
155 * Adds a rule to be fired when wrapped implementation returns no matches
156 *
157 * @param rule a Rule to be fired when wrapped implementation returns no matches
158 **/
159 public void addDefault( Rule rule )
160 {
161 // set up rule
162 if ( wrappedRules.getDigester() != null )
163 {
164 rule.setDigester( wrappedRules.getDigester() );
165 }
166
167 if ( wrappedRules.getNamespaceURI() != null )
168 {
169 rule.setNamespaceURI( wrappedRules.getNamespaceURI() );
170 }
171
172 defaultRules.add( rule );
173 allRules.add( rule );
174 }
175
176 /**
177 * {@inheritDoc}
178 */
179 public List<Rule> rules()
180 {
181 return allRules;
182 }
183
184 /**
185 * {@inheritDoc}
186 */
187 public void clear()
188 {
189 wrappedRules.clear();
190 allRules.clear();
191 defaultRules.clear();
192 }
193
194 /**
195 * {@inheritDoc}
196 */
197 public void add( String pattern, Rule rule )
198 {
199 wrappedRules.add( pattern, rule );
200 allRules.add( rule );
201 }
202
203 }