View Javadoc

1   /*
2    * $Id: FormSet.java 293498 2005-10-04 02:59:43Z niallp $
3    * $Rev: 293498 $
4    * $Date: 2005-10-04 03:59:43 +0100 (Tue, 04 Oct 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  package org.apache.commons.validator;
22  
23  import java.io.Serializable;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.Map;
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  
31  /***
32   * Holds a set of <code>Form</code>s stored associated with a <code>Locale</code>
33   * based on the country, language, and variant specified. Instances of this
34   * class are configured with a &lt;formset&gt; xml element.
35   */
36  public class FormSet implements Serializable {
37  
38      /*** Logging */
39      private static final Log log = LogFactory.getLog(FormSet.class);
40  
41      /***
42       * Whether or not the this <code>FormSet</code> was processed for replacing
43       * variables in strings with their values.
44       */
45      private boolean processed = false;
46  
47      /*** Language component of <code>Locale</code> (required). */
48      private String language = null;
49  
50      /*** Country component of <code>Locale</code> (optional). */
51      private String country = null;
52  
53      /*** Variant component of <code>Locale</code> (optional). */
54      private String variant = null;
55  
56      /***
57       * A <code>Map</code> of <code>Form</code>s using the name field of the
58       * <code>Form</code> as the key.
59       */
60      private Map forms = new HashMap();
61  
62      /***
63       * A <code>Map</code> of <code>Constant</code>s using the name field of the
64       * <code>Constant</code> as the key.
65       */
66      private Map constants = new HashMap();
67  
68      /***
69       * This is the type of <code>FormSet</code>s where no locale is specified.
70       */
71      protected final static int GLOBAL_FORMSET = 1;
72  
73      /***
74       * This is the type of <code>FormSet</code>s where only language locale is
75       * specified.
76       */
77      protected final static int LANGUAGE_FORMSET = 2;
78  
79      /***
80       * This is the type of <code>FormSet</code>s where only language and country
81       * locale are specified.
82       */
83      protected final static int COUNTRY_FORMSET = 3;
84  
85      /***
86       * This is the type of <code>FormSet</code>s where full locale has been set.
87       */
88      protected final static int VARIANT_FORMSET = 4;
89  
90      /***
91       * Flag indicating if this formSet has been merged with its parent (higher
92       * rank in Locale hierarchy).
93       */
94      private boolean merged;
95  
96      /***
97       * Has this formSet been merged?
98       *
99       * @return   true if it has been merged
100      * @since    Validator 1.2.0
101      */
102     protected boolean isMerged() {
103         return merged;
104     }
105 
106     /***
107      * Returns the type of <code>FormSet</code>:<code>GLOBAL_FORMSET</code>,
108      * <code>LANGUAGE_FORMSET</code>,<code>COUNTRY_FORMSET</code> or <code>VARIANT_FORMSET</code>
109      * .
110      *
111      * @return                       The type value
112      * @since                        Validator 1.2.0
113      * @throws NullPointerException  if there is inconsistency in the locale
114      *      definition (not sure about this)
115      */
116     protected int getType() {
117         if (getVariant() != null) {
118             if (getLanguage() == null || getCountry() == null) {
119                 throw new NullPointerException(
120                     "When variant is specified, country and language must be specified.");
121             }
122             return VARIANT_FORMSET;
123         }
124         else if (getCountry() != null) {
125             if (getLanguage() == null) {
126                 throw new NullPointerException(
127                     "When country is specified, language must be specified.");
128             }
129             return COUNTRY_FORMSET;
130         }
131         else if (getLanguage() != null) {
132             return LANGUAGE_FORMSET;
133         }
134         else {
135             return GLOBAL_FORMSET;
136         }
137     }
138 
139     /***
140      * Merges the given <code>FormSet</code> into this one. If any of <code>depends</code>
141      * s <code>Forms</code> are not in this <code>FormSet</code> then, include
142      * them, else merge both <code>Forms</code>. Theoretically we should only
143      * merge a "parent" formSet.
144      *
145      * @param depends  FormSet to be merged
146      * @since          Validator 1.2.0
147      */
148     protected void merge(FormSet depends) {
149         if (depends != null) {
150             Map pForms = getForms();
151             Map dForms = depends.getForms();
152             for (Iterator it = dForms.keySet().iterator(); it.hasNext(); ) {
153                 Object key = it.next();
154                 Form pForm = (Form) pForms.get(key);
155                 if (pForm != null) {//merge, but principal 'rules', don't overwrite
156                     // anything
157                     pForm.merge((Form) dForms.get(key));
158                 }
159                 else {//just add
160                     addForm((Form) dForms.get(key));
161                 }
162             }
163         }
164         merged = true;
165     }
166 
167     /***
168      * Whether or not the this <code>FormSet</code> was processed for replacing
169      * variables in strings with their values.
170      *
171      * @return   The processed value
172      */
173     public boolean isProcessed() {
174         return processed;
175     }
176 
177     /***
178      * Gets the equivalent of the language component of <code>Locale</code>.
179      *
180      * @return   The language value
181      */
182     public String getLanguage() {
183         return language;
184     }
185 
186     /***
187      * Sets the equivalent of the language component of <code>Locale</code>.
188      *
189      * @param language  The new language value
190      */
191     public void setLanguage(String language) {
192         this.language = language;
193     }
194 
195     /***
196      * Gets the equivalent of the country component of <code>Locale</code>.
197      *
198      * @return   The country value
199      */
200     public String getCountry() {
201         return country;
202     }
203 
204     /***
205      * Sets the equivalent of the country component of <code>Locale</code>.
206      *
207      * @param country  The new country value
208      */
209     public void setCountry(String country) {
210         this.country = country;
211     }
212 
213     /***
214      * Gets the equivalent of the variant component of <code>Locale</code>.
215      *
216      * @return   The variant value
217      */
218     public String getVariant() {
219         return variant;
220     }
221 
222     /***
223      * Sets the equivalent of the variant component of <code>Locale</code>.
224      *
225      * @param variant  The new variant value
226      */
227     public void setVariant(String variant) {
228         this.variant = variant;
229     }
230 
231     /***
232      * Add a <code>Constant</code> to the locale level.
233      *
234      * @param name   The constant name
235      * @param value  The constant value
236      */
237     public void addConstant(String name, String value) {
238 
239         if (constants.containsKey(name)) {
240             log.error("Constant '" + name +  "' already exists in FormSet["
241                       + this.displayKey() + "] - ignoring.");
242                        
243         } else {
244             constants.put(name, value);
245         }
246 
247     }
248 
249     /***
250      * Add a <code>Form</code> to the <code>FormSet</code>.
251      *
252      * @param f  The form
253      */
254     public void addForm(Form f) {
255 
256         String formName = f.getName();
257         if (forms.containsKey(formName)) {
258             log.error("Form '" + formName + "' already exists in FormSet[" 
259                       + this.displayKey() + "] - ignoring.");
260                        
261         } else {
262             forms.put(f.getName(), f);
263         }
264 
265     }
266 
267     /***
268      * Retrieve a <code>Form</code> based on the form name.
269      *
270      * @param formName  The form name
271      * @return          The form
272      */
273     public Form getForm(String formName) {
274         return (Form) this.forms.get(formName);
275     }
276 
277     /***
278      * A <code>Map</code> of <code>Form</code>s is returned as an unmodifiable
279      * <code>Map</code> with the key based on the form name.
280      *
281      * @return   The forms map
282      */
283     public Map getForms() {
284         return Collections.unmodifiableMap(forms);
285     }
286 
287     /***
288      * Processes all of the <code>Form</code>s.
289      *
290      * @param globalConstants  Global constants
291      */
292     synchronized void process(Map globalConstants) {
293         for (Iterator i = forms.values().iterator(); i.hasNext(); ) {
294             Form f = (Form) i.next();
295             f.process(globalConstants, constants, forms);
296         }
297 
298         processed = true;
299     }
300 
301     /***
302      * Returns a string representation of the object's key.
303      *
304      * @return   A string representation of the key
305      */
306     public String displayKey() {
307         StringBuffer results = new StringBuffer();
308         if (language != null && language.length() > 0) {
309             results.append("language=");
310             results.append(language);
311         }
312         if (country != null && country.length() > 0) {
313             if (results.length() > 0) {
314                results.append(", ");
315             }
316             results.append("country=");
317             results.append(country);
318         }
319         if (variant != null && variant.length() > 0) {
320             if (results.length() > 0) {
321                results.append(", ");
322             }
323             results.append("variant=");
324             results.append(variant );
325         }
326         if (results.length() == 0) {
327            results.append("default");
328         }
329 
330         return results.toString();
331     }
332 
333     /***
334      * Returns a string representation of the object.
335      *
336      * @return   A string representation
337      */
338     public String toString() {
339         StringBuffer results = new StringBuffer();
340 
341         results.append("FormSet: language=");
342         results.append(language);
343         results.append("  country=");
344         results.append(country);
345         results.append("  variant=");
346         results.append(variant);
347         results.append("\n");
348 
349         for (Iterator i = getForms().values().iterator(); i.hasNext(); ) {
350             results.append("   ");
351             results.append(i.next());
352             results.append("\n");
353         }
354 
355         return results.toString();
356     }
357 
358 }