1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 <formset> 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) {
156
157 pForm.merge((Form) dForms.get(key));
158 }
159 else {
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 }