KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > digester > RulesBase


1 /* $Id: RulesBase.java 155412 2005-02-26 12:58:36Z dirkv $
2  *
3  * Copyright 2001-2004 The Apache Software Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18
19 package org.apache.commons.digester;
20
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26
27
28 /**
29  * <p>Default implementation of the <code>Rules</code> interface that supports
30  * the standard rule matching behavior. This class can also be used as a
31  * base class for specialized <code>Rules</code> implementations.</p>
32  *
33  * <p>The matching policies implemented by this class support two different
34  * types of pattern matching rules:</p>
35  * <ul>
36  * <li><em>Exact Match</em> - A pattern "a/b/c" exactly matches a
37  * <code>&lt;c&gt;</code> element, nested inside a <code>&lt;b&gt;</code>
38  * element, which is nested inside an <code>&lt;a&gt;</code> element.</li>
39  * <li><em>Tail Match</em> - A pattern "&#42;/a/b" matches a
40  * <code>&lt;b&gt;</code> element, nested inside an <code>&lt;a&gt;</code>
41  * element, no matter how deeply the pair is nested.</li>
42  * </ul>
43  *
44  * <p>Note that wildcard patterns are ignored if an explicit match can be found
45  * (and when multiple wildcard patterns match, only the longest, ie most
46  * explicit, pattern is considered a match).</p>
47  *
48  * <p>See the package documentation for package org.apache.commons.digester
49  * for more information.</p>
50  */

51
52 public class RulesBase implements Rules {
53
54
55     // ----------------------------------------------------- Instance Variables
56

57
58     /**
59      * The set of registered Rule instances, keyed by the matching pattern.
60      * Each value is a List containing the Rules for that pattern, in the
61      * order that they were orginally registered.
62      */

63     protected HashMap JavaDoc cache = new HashMap JavaDoc();
64
65
66     /**
67      * The Digester instance with which this Rules instance is associated.
68      */

69     protected Digester digester = null;
70
71
72     /**
73      * The namespace URI for which subsequently added <code>Rule</code>
74      * objects are relevant, or <code>null</code> for matching independent
75      * of namespaces.
76      */

77     protected String JavaDoc namespaceURI = null;
78
79
80     /**
81      * The set of registered Rule instances, in the order that they were
82      * originally registered.
83      */

84     protected ArrayList JavaDoc rules = new ArrayList JavaDoc();
85
86
87     // ------------------------------------------------------------- Properties
88

89
90     /**
91      * Return the Digester instance with which this Rules instance is
92      * associated.
93      */

94     public Digester getDigester() {
95
96         return (this.digester);
97
98     }
99
100
101     /**
102      * Set the Digester instance with which this Rules instance is associated.
103      *
104      * @param digester The newly associated Digester instance
105      */

106     public void setDigester(Digester digester) {
107
108         this.digester = digester;
109         Iterator JavaDoc items = rules.iterator();
110         while (items.hasNext()) {
111             Rule item = (Rule) items.next();
112             item.setDigester(digester);
113         }
114
115     }
116
117
118     /**
119      * Return the namespace URI that will be applied to all subsequently
120      * added <code>Rule</code> objects.
121      */

122     public String JavaDoc getNamespaceURI() {
123
124         return (this.namespaceURI);
125
126     }
127
128
129     /**
130      * Set the namespace URI that will be applied to all subsequently
131      * added <code>Rule</code> objects.
132      *
133      * @param namespaceURI Namespace URI that must match on all
134      * subsequently added rules, or <code>null</code> for matching
135      * regardless of the current namespace URI
136      */

137     public void setNamespaceURI(String JavaDoc namespaceURI) {
138
139         this.namespaceURI = namespaceURI;
140
141     }
142
143
144     // --------------------------------------------------------- Public Methods
145

146
147     /**
148      * Register a new Rule instance matching the specified pattern.
149      *
150      * @param pattern Nesting pattern to be matched for this Rule
151      * @param rule Rule instance to be registered
152      */

153     public void add(String JavaDoc pattern, Rule rule) {
154         // to help users who accidently add '/' to the end of their patterns
155
int patternLength = pattern.length();
156         if (patternLength>1 && pattern.endsWith("/")) {
157             pattern = pattern.substring(0, patternLength-1);
158         }
159         
160         
161         List JavaDoc list = (List JavaDoc) cache.get(pattern);
162         if (list == null) {
163             list = new ArrayList JavaDoc();
164             cache.put(pattern, list);
165         }
166         list.add(rule);
167         rules.add(rule);
168         if (this.digester != null) {
169             rule.setDigester(this.digester);
170         }
171         if (this.namespaceURI != null) {
172             rule.setNamespaceURI(this.namespaceURI);
173         }
174
175     }
176
177
178     /**
179      * Clear all existing Rule instance registrations.
180      */

181     public void clear() {
182
183         cache.clear();
184         rules.clear();
185
186     }
187
188
189     /**
190      * Return a List of all registered Rule instances that match the specified
191      * nesting pattern, or a zero-length List if there are no matches. If more
192      * than one Rule instance matches, they <strong>must</strong> be returned
193      * in the order originally registered through the <code>add()</code>
194      * method.
195      *
196      * @param pattern Nesting pattern to be matched
197      *
198      * @deprecated Call match(namespaceURI,pattern) instead.
199      */

200     public List JavaDoc match(String JavaDoc pattern) {
201
202         return (match(null, pattern));
203
204     }
205
206
207     /**
208      * Return a List of all registered Rule instances that match the specified
209      * nesting pattern, or a zero-length List if there are no matches. If more
210      * than one Rule instance matches, they <strong>must</strong> be returned
211      * in the order originally registered through the <code>add()</code>
212      * method.
213      *
214      * @param namespaceURI Namespace URI for which to select matching rules,
215      * or <code>null</code> to match regardless of namespace URI
216      * @param pattern Nesting pattern to be matched
217      */

218     public List JavaDoc match(String JavaDoc namespaceURI, String JavaDoc pattern) {
219
220         // List rulesList = (List) this.cache.get(pattern);
221
List JavaDoc rulesList = lookup(namespaceURI, pattern);
222         if ((rulesList == null) || (rulesList.size() < 1)) {
223             // Find the longest key, ie more discriminant
224
String JavaDoc longKey = "";
225             Iterator JavaDoc keys = this.cache.keySet().iterator();
226             while (keys.hasNext()) {
227                 String JavaDoc key = (String JavaDoc) keys.next();
228                 if (key.startsWith("*/")) {
229                     if (pattern.equals(key.substring(2)) ||
230                         pattern.endsWith(key.substring(1))) {
231                         if (key.length() > longKey.length()) {
232                             // rulesList = (List) this.cache.get(key);
233
rulesList = lookup(namespaceURI, key);
234                             longKey = key;
235                         }
236                     }
237                 }
238             }
239         }
240         if (rulesList == null) {
241             rulesList = new ArrayList JavaDoc();
242         }
243         return (rulesList);
244
245     }
246
247
248     /**
249      * Return a List of all registered Rule instances, or a zero-length List
250      * if there are no registered Rule instances. If more than one Rule
251      * instance has been registered, they <strong>must</strong> be returned
252      * in the order originally registered through the <code>add()</code>
253      * method.
254      */

255     public List JavaDoc rules() {
256
257         return (this.rules);
258
259     }
260
261
262     // ------------------------------------------------------ Protected Methods
263

264
265     /**
266      * Return a List of Rule instances for the specified pattern that also
267      * match the specified namespace URI (if any). If there are no such
268      * rules, return <code>null</code>.
269      *
270      * @param namespaceURI Namespace URI to match, or <code>null</code> to
271      * select matching rules regardless of namespace URI
272      * @param pattern Pattern to be matched
273      */

274     protected List JavaDoc lookup(String JavaDoc namespaceURI, String JavaDoc pattern) {
275
276         // Optimize when no namespace URI is specified
277
List JavaDoc list = (List JavaDoc) this.cache.get(pattern);
278         if (list == null) {
279             return (null);
280         }
281         if ((namespaceURI == null) || (namespaceURI.length() == 0)) {
282             return (list);
283         }
284
285         // Select only Rules that match on the specified namespace URI
286
ArrayList JavaDoc results = new ArrayList JavaDoc();
287         Iterator JavaDoc items = list.iterator();
288         while (items.hasNext()) {
289             Rule item = (Rule) items.next();
290             if ((namespaceURI.equals(item.getNamespaceURI())) ||
291                     (item.getNamespaceURI() == null)) {
292                 results.add(item);
293             }
294         }
295         return (results);
296
297     }
298
299
300 }
301
Popular Tags