KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > validator > ValidatorResources


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

21
22 package org.apache.commons.validator;
23
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.io.Serializable JavaDoc;
27 import java.net.URL JavaDoc;
28 import java.util.ArrayList JavaDoc;
29 import java.util.Collections JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Locale JavaDoc;
33 import java.util.Map JavaDoc;
34
35 import org.apache.commons.collections.FastHashMap; // DEPRECATED
36
import org.apache.commons.digester.Digester;
37 import org.apache.commons.digester.xmlrules.DigesterLoader;
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40
41 import org.xml.sax.SAXException JavaDoc;
42
43 /**
44  * <p>
45  * General purpose class for storing <code>FormSet</code> objects based
46  * on their associated <code>Locale</code>. Instances of this class are usually
47  * configured through a validation.xml file that is parsed in a constructor.
48  * </p>
49  *
50  * <p><strong>Note</strong> - Classes that extend this class
51  * must be Serializable so that instances may be used in distributable
52  * application server environments.</p>
53  *
54  * <p>
55  * The use of FastHashMap is deprecated and will be replaced in a future
56  * release.
57  * </p>
58  */

59 public class ValidatorResources implements Serializable JavaDoc {
60
61     /**
62      * The set of public identifiers, and corresponding resource names, for
63      * the versions of the configuration file DTDs that we know about. There
64      * <strong>MUST</strong> be an even number of Strings in this list!
65      */

66     private static final String JavaDoc registrations[] = {
67         "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN",
68         "/org/apache/commons/validator/resources/validator_1_0.dtd",
69         "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0.1//EN",
70         "/org/apache/commons/validator/resources/validator_1_0_1.dtd",
71         "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1//EN",
72         "/org/apache/commons/validator/resources/validator_1_1.dtd",
73         "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.2.0//EN",
74         "/org/apache/commons/validator/resources/validator_1_2_0.dtd"
75     };
76
77     private static final Log log = LogFactory.getLog(ValidatorResources.class);
78
79     /**
80      * <code>Map</code> of <code>FormSet</code>s stored under
81      * a <code>Locale</code> key.
82      * @deprecated Subclasses should use getFormSets() instead.
83      */

84     protected FastHashMap hFormSets = new FastHashMap();
85
86     /**
87      * <code>Map</code> of global constant values with
88      * the name of the constant as the key.
89      * @deprecated Subclasses should use getConstants() instead.
90      */

91     protected FastHashMap hConstants = new FastHashMap();
92
93     /**
94      * <code>Map</code> of <code>ValidatorAction</code>s with
95      * the name of the <code>ValidatorAction</code> as the key.
96      * @deprecated Subclasses should use getActions() instead.
97      */

98     protected FastHashMap hActions = new FastHashMap();
99
100     /**
101      * The default locale on our server.
102      */

103     protected static Locale JavaDoc defaultLocale = Locale.getDefault();
104
105     /**
106      * Create an empty ValidatorResources object.
107      */

108     public ValidatorResources() {
109         super();
110     }
111
112     /**
113      * Create a ValidatorResources object from an InputStream.
114      *
115      * @param in InputStream to a validation.xml configuration file. It's the client's
116      * responsibility to close this stream.
117      * @throws IOException
118      * @throws SAXException if the validation XML files are not valid or well
119      * formed.
120      * @since Validator 1.1
121      */

122     public ValidatorResources(InputStream JavaDoc in) throws IOException JavaDoc, SAXException JavaDoc {
123         this(new InputStream JavaDoc[]{in});
124     }
125
126     /**
127      * Create a ValidatorResources object from an InputStream.
128      *
129      * @param streams An array of InputStreams to several validation.xml
130      * configuration files that will be read in order and merged into this object.
131      * It's the client's responsibility to close these streams.
132      * @throws IOException
133      * @throws SAXException if the validation XML files are not valid or well
134      * formed.
135      * @since Validator 1.1
136      */

137     public ValidatorResources(InputStream JavaDoc[] streams)
138             throws IOException JavaDoc, SAXException JavaDoc {
139
140         super();
141
142         URL JavaDoc rulesUrl = this.getClass().getResource("digester-rules.xml");
143         Digester digester = DigesterLoader.createDigester(rulesUrl);
144         digester.setNamespaceAware(true);
145         digester.setValidating(true);
146         digester.setUseContextClassLoader(true);
147
148         // register DTDs
149
for (int i = 0; i < registrations.length; i += 2) {
150             URL JavaDoc url = this.getClass().getResource(registrations[i + 1]);
151             if (url != null) {
152                 digester.register(registrations[i], url.toString());
153             }
154         }
155
156         for (int i = 0; i < streams.length; i++) {
157             digester.push(this);
158             digester.parse(streams[i]);
159         }
160
161         this.process();
162     }
163
164     /**
165      * Add a <code>FormSet</code> to this <code>ValidatorResources</code>
166      * object. It will be associated with the <code>Locale</code> of the
167      * <code>FormSet</code>.
168      * @since Validator 1.1
169      */

170     public void addFormSet(FormSet fs) {
171         String JavaDoc key = this.buildKey(fs);
172         List JavaDoc formsets = (List JavaDoc) hFormSets.get(key);
173
174         if (formsets == null) {
175             formsets = new ArrayList JavaDoc();
176             hFormSets.put(key, formsets);
177         }
178
179         if (!formsets.contains(fs)) {
180             if (log.isDebugEnabled()) {
181                 log.debug("Adding FormSet '" + fs.toString() + "'.");
182             }
183             formsets.add(fs);
184         }
185     }
186
187     /**
188      * Add a global constant to the resource.
189      */

190     public void addConstant(String JavaDoc name, String JavaDoc value) {
191         if (log.isDebugEnabled()) {
192             log.debug("Adding Global Constant: " + name + "," + value);
193         }
194
195         this.hConstants.put(name, value);
196     }
197
198     /**
199      * Add a <code>ValidatorAction</code> to the resource. It also creates an
200      * instance of the class based on the <code>ValidatorAction</code>s
201      * classname and retrieves the <code>Method</code> instance and sets them
202      * in the <code>ValidatorAction</code>.
203      */

204     public void addValidatorAction(ValidatorAction va) {
205         va.init();
206
207         this.hActions.put(va.getName(), va);
208
209         if (log.isDebugEnabled()) {
210             log.debug("Add ValidatorAction: " + va.getName() + "," + va.getClassname());
211         }
212     }
213
214     /**
215      * Get a <code>ValidatorAction</code> based on it's name.
216      */

217     public ValidatorAction getValidatorAction(String JavaDoc key) {
218         return (ValidatorAction) hActions.get(key);
219     }
220
221     /**
222      * Get an unmodifiable <code>Map</code> of the <code>ValidatorAction</code>s.
223      */

224     public Map JavaDoc getValidatorActions() {
225         return Collections.unmodifiableMap(hActions);
226     }
227
228     /**
229      * Builds a key to store the <code>FormSet</code> under based on it's
230      * language, country, and variant values.
231      */

232     protected String JavaDoc buildKey(FormSet fs) {
233         String JavaDoc locale =
234                 this.buildLocale(fs.getLanguage(), fs.getCountry(), fs.getVariant());
235
236         if (locale.length() == 0) {
237             locale = defaultLocale.toString();
238         }
239
240         return locale;
241     }
242
243     /**
244      * Assembles a Locale code from the given parts.
245      */

246     private String JavaDoc buildLocale(String JavaDoc lang, String JavaDoc country, String JavaDoc variant) {
247         String JavaDoc key = ((lang != null && lang.length() > 0) ? lang : "");
248         key += ((country != null && country.length() > 0) ? "_" + country : "");
249         key += ((variant != null && variant.length() > 0) ? "_" + variant : "");
250         return key;
251     }
252
253     /**
254      * <p>Gets a <code>Form</code> based on the name of the form and the
255      * <code>Locale</code> that most closely matches the <code>Locale</code>
256      * passed in. The order of <code>Locale</code> matching is:</p>
257      * <ol>
258      * <li>language + country + variant</li>
259      * <li>language + country</li>
260      * <li>language</li>
261      * <li>default locale</li>
262      * </ol>
263      * @since Validator 1.1
264      */

265     public Form getForm(Locale JavaDoc locale, String JavaDoc formKey) {
266         return this.getForm(locale.getLanguage(), locale.getCountry(), locale
267                 .getVariant(), formKey);
268     }
269
270     /**
271      * <p>Gets a <code>Form</code> based on the name of the form and the
272      * <code>Locale</code> that most closely matches the <code>Locale</code>
273      * passed in. The order of <code>Locale</code> matching is:</p>
274      * <ol>
275      * <li>language + country + variant</li>
276      * <li>language + country</li>
277      * <li>language</li>
278      * <li>default locale</li>
279      * </ol>
280      * @since Validator 1.1
281      */

282     public Form getForm(String JavaDoc language, String JavaDoc country, String JavaDoc variant,
283             String JavaDoc formKey) {
284
285         String JavaDoc key = this.buildLocale(language, country, variant);
286
287         List JavaDoc v = (List JavaDoc) hFormSets.get(key);
288
289         if (v == null) {
290             key = (language != null && language.length() > 0) ? language : "";
291             key += (country != null && country.length() > 0) ? "_" + country : "";
292             v = (List JavaDoc) hFormSets.get(key);
293         }
294
295         if (v == null) {
296             key = (language != null && language.length() > 0) ? language : "";
297             v = (List JavaDoc) hFormSets.get(key);
298         }
299
300         if (v == null) {
301             key = defaultLocale.toString();
302             v = (List JavaDoc) hFormSets.get(key);
303         }
304
305         if (v == null) {
306             return null;
307         }
308
309         Iterator JavaDoc formsets = v.iterator();
310         while (formsets.hasNext()) {
311             FormSet set = (FormSet) formsets.next();
312
313             if ((set != null) && (set.getForm(formKey) != null)) {
314                 return set.getForm(formKey);
315             }
316
317         }
318         return null;
319     }
320
321     /**
322      * Process the <code>ValidatorResources</code> object. Currently sets the
323      * <code>FastHashMap</code>s to the 'fast' mode and call the processes all
324      * other resources. <strong>Note</strong>: The framework calls this automatically
325      * when ValidatorResources is created from an XML file. If you create an instance
326      * of this class by hand you <strong>must</strong> call this method when finished.
327      */

328     public void process() {
329         hFormSets.setFast(true);
330         hConstants.setFast(true);
331         hActions.setFast(true);
332
333         this.processForms();
334     }
335
336     /**
337      * <p>Process the <code>Form</code> objects. This clones the <code>Field</code>s
338      * that don't exist in a <code>FormSet</code> compared to the default
339      * <code>FormSet</code>.</p>
340      */

341     private void processForms() {
342         //hFormSets.put(buildKey(fs), fs);
343
String JavaDoc defaultKey = defaultLocale.toString();
344
345         // Loop through FormSets
346
for (Iterator JavaDoc i = hFormSets.keySet().iterator(); i.hasNext();) {
347             String JavaDoc key = (String JavaDoc) i.next();
348             // Skip default FormSet
349
if (key.equals(defaultKey)) {
350                 continue;
351             }
352             List JavaDoc formsets = (List JavaDoc) hFormSets.get(key);
353             Iterator JavaDoc formsetsIterator = formsets.iterator();
354             while (formsetsIterator.hasNext()) {
355                 FormSet fs = (FormSet) formsetsIterator.next();
356
357                 // Loop through Forms and copy/clone fields from default locale
358
for (Iterator JavaDoc x = fs.getForms().keySet().iterator(); x.hasNext();) {
359                     String JavaDoc formKey = (String JavaDoc) x.next();
360                     Form form = (Form) fs.getForms().get(formKey);
361                     // Create a new Form object so the order from the default is
362
// maintained (very noticable in the JavaScript).
363
Form newForm = new Form();
364                     newForm.setName(form.getName());
365
366                     // Loop through the default locale form's fields
367
// If they don't exist in the current locale's form, then clone them.
368
Form defaultForm = this.getForm(defaultLocale, formKey);
369
370                     Iterator JavaDoc defaultFields = defaultForm.getFields().iterator();
371                     while (defaultFields.hasNext()) {
372                         Field defaultField = (Field) defaultFields.next();
373                         String JavaDoc fieldKey = defaultField.getKey();
374
375                         if (form.containsField(fieldKey)) {
376                             newForm.addField(form.getField(fieldKey));
377
378                         } else {
379                             Field field =
380                                     getClosestLocaleField(fs, formKey, fieldKey);
381
382                             newForm.addField((Field) field.clone());
383                         }
384                     }
385
386                     fs.addForm(newForm);
387                 }
388             }
389         }
390
391         // Process Fully Constructed FormSets
392
for (Iterator JavaDoc i = hFormSets.values().iterator(); i.hasNext();) {
393             List JavaDoc formsets = (List JavaDoc) i.next();
394             Iterator JavaDoc formsetsIterator = formsets.iterator();
395             while (formsetsIterator.hasNext()) {
396                 FormSet fs = (FormSet) formsetsIterator.next();
397
398                 if (!fs.isProcessed()) {
399                     fs.process(hConstants);
400                 }
401             }
402         }
403     }
404
405     /**
406      * Retrieves the closest matching <code>Field</code> based
407      * on <code>FormSet</code>'s locale. This is used when
408      * constructing a clone, field by field, of partial
409      * <code>FormSet</code>.
410      */

411     protected Field getClosestLocaleField(FormSet fs, String JavaDoc formKey,
412             String JavaDoc fieldKey) {
413
414         Field field = null;
415         String JavaDoc language = fs.getLanguage();
416         String JavaDoc country = fs.getCountry();
417         String JavaDoc variant = fs.getVariant();
418
419         if (!GenericValidator.isBlankOrNull(language)
420                 && !GenericValidator.isBlankOrNull(country)
421                 && !GenericValidator.isBlankOrNull(variant)) {
422
423             Form form = this.getForm(language, country, variant, formKey);
424             field = form.getField(fieldKey);
425         }
426
427         if (field == null) {
428             if (!GenericValidator.isBlankOrNull(language)
429                     && !GenericValidator.isBlankOrNull(country)) {
430
431                 Form form = this.getForm(language, country, null, formKey);
432                 field = form.getField(fieldKey);
433             }
434         }
435
436         if (field == null) {
437             if (!GenericValidator.isBlankOrNull(language)) {
438                 Form form = this.getForm(language, null, null, formKey);
439                 field = form.getField(fieldKey);
440             }
441         }
442
443         if (field == null) {
444             Form form = this.getForm(defaultLocale, formKey);
445             field = form.getField(fieldKey);
446         }
447
448         return field;
449     }
450
451     /**
452      * Returns a Map of String locale keys to Lists of their FormSets.
453      * @since Validator 1.2.0
454      */

455     protected Map JavaDoc getFormSets() {
456         return hFormSets;
457     }
458
459     /**
460      * Returns a Map of String constant names to their String values.
461      * @since Validator 1.2.0
462      */

463     protected Map JavaDoc getConstants() {
464         return hConstants;
465     }
466
467     /**
468      * Returns a Map of String ValidatorAction names to their ValidatorAction.
469      * @since Validator 1.2.0
470      */

471     protected Map JavaDoc getActions() {
472         return hActions;
473     }
474
475 }
476
Popular Tags