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.ArrayList;
25 import java.util.Collections;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.apache.commons.collections.FastHashMap;
31
32 /***
33 * <p>
34 *
35 * This contains a set of validation rules for a form/JavaBean. The information
36 * is contained in a list of <code>Field</code> objects. Instances of this class
37 * are configured with a <form> xml element. </p> <p>
38 *
39 * The use of FastHashMap is deprecated and will be replaced in a future
40 * release. </p>
41 */
42 public class Form implements Serializable {
43
44 /*** The name/key the set of validation rules is stored under. */
45 protected String name = null;
46
47 /***
48 * List of <code>Field</code>s. Used to maintain the order they were added
49 * in although individual <code>Field</code>s can be retrieved using <code>Map</code>
50 * of <code>Field</code>s.
51 */
52 protected List lFields = new ArrayList();
53
54 /***
55 * Map of <code>Field</code>s keyed on their property value.
56 *
57 * @deprecated Subclasses should use getFieldMap() instead.
58 */
59 protected FastHashMap hFields = new FastHashMap();
60
61 /***
62 * The name/key of the form which this form extends from.
63 *
64 * @since Validator 1.2.0
65 */
66 protected String inherit = null;
67
68 /***
69 * Whether or not the this <code>Form</code> was processed for replacing
70 * variables in strings with their values.
71 */
72 private boolean processed = false;
73
74 /***
75 * Gets the name/key of the set of validation rules.
76 *
77 * @return The name value
78 */
79 public String getName() {
80 return name;
81 }
82
83 /***
84 * Sets the name/key of the set of validation rules.
85 *
86 * @param name The new name value
87 */
88 public void setName(String name) {
89 this.name = name;
90 }
91
92 /***
93 * Add a <code>Field</code> to the <code>Form</code>.
94 *
95 * @param f The field
96 */
97 public void addField(Field f) {
98 this.lFields.add(f);
99 this.hFields.put(f.getKey(), f);
100 }
101
102 /***
103 * A <code>List</code> of <code>Field</code>s is returned as an unmodifiable
104 * <code>List</code>.
105 *
106 * @return The fields value
107 */
108 public List getFields() {
109 return Collections.unmodifiableList(lFields);
110 }
111
112 /***
113 * Returns the Field with the given name or null if this Form has no such
114 * field.
115 *
116 * @param fieldName The field name
117 * @return The field value
118 * @since Validator 1.1
119 */
120 public Field getField(String fieldName) {
121 return (Field) this.hFields.get(fieldName);
122 }
123
124 /***
125 * Returns true if this Form contains a Field with the given name.
126 *
127 * @param fieldName The field name
128 * @return True if this form contains the field by the given name
129 * @since Validator 1.1
130 */
131 public boolean containsField(String fieldName) {
132 return this.hFields.containsKey(fieldName);
133 }
134
135 /***
136 * Merges the given form into this one. For any field in <code>depends</code>
137 * not present in this form, include it. <code>depends</code> has precedence
138 * in the way the fields are ordered.
139 *
140 * @param depends the form we want to merge
141 * @since Validator 1.2.0
142 */
143 protected void merge(Form depends) {
144
145 List templFields = new ArrayList();
146 Map temphFields = new FastHashMap();
147 Iterator dependsIt = depends.getFields().iterator();
148 while (dependsIt.hasNext()) {
149 Field defaultField = (Field) dependsIt.next();
150 if (defaultField != null) {
151 String fieldKey = defaultField.getKey();
152 if (!this.containsField(fieldKey)) {
153 templFields.add(defaultField);
154 temphFields.put(fieldKey, defaultField);
155 }
156 else {
157 Field old = getField(fieldKey);
158 hFields.remove(fieldKey);
159 lFields.remove(old);
160 templFields.add(old);
161 temphFields.put(fieldKey, old);
162 }
163 }
164 }
165 lFields.addAll(0, templFields);
166 hFields.putAll(temphFields);
167 }
168
169 /***
170 * Processes all of the <code>Form</code>'s <code>Field</code>s.
171 *
172 * @param globalConstants A map of global constants
173 * @param constants Local constants
174 * @param forms Map of forms
175 * @since Validator 1.2.0
176 */
177 protected void process(Map globalConstants, Map constants, Map forms) {
178 if (isProcessed()) {
179 return;
180 }
181
182 int n = 0;
183 if (isExtending()) {
184 Form parent = (Form) forms.get(inherit);
185 if (parent != null) {
186 if (!parent.isProcessed()) {
187
188 parent.process(constants, globalConstants, forms);
189 }
190 for (Iterator i = parent.getFields().iterator(); i.hasNext(); ) {
191 Field f = (Field) i.next();
192
193 if (hFields.get(f.getKey()) == null) {
194 lFields.add(n, f);
195 hFields.put(f.getKey(), f);
196 n++;
197 }
198 }
199 }
200 }
201 hFields.setFast(true);
202
203 for (Iterator i = lFields.listIterator(n); i.hasNext(); ) {
204 Field f = (Field) i.next();
205 f.process(globalConstants, constants);
206 }
207
208 processed = true;
209 }
210
211 /***
212 * Returns a string representation of the object.
213 *
214 * @return string representation
215 */
216 public String toString() {
217 StringBuffer results = new StringBuffer();
218
219 results.append("Form: ");
220 results.append(name);
221 results.append("\n");
222
223 for (Iterator i = lFields.iterator(); i.hasNext(); ) {
224 results.append("\tField: \n");
225 results.append(i.next());
226 results.append("\n");
227 }
228
229 return results.toString();
230 }
231
232 /***
233 * Validate all Fields in this Form on the given page and below.
234 *
235 * @param params A Map of parameter class names to parameter
236 * values to pass into validation methods.
237 * @param actions A Map of validator names to ValidatorAction
238 * objects.
239 * @param page Fields on pages higher than this will not be
240 * validated.
241 * @return A ValidatorResults object containing all
242 * validation messages.
243 * @throws ValidatorException
244 */
245 ValidatorResults validate(Map params, Map actions, int page)
246 throws ValidatorException {
247 return validate(params, actions, page, null);
248 }
249
250 /***
251 * Validate all Fields in this Form on the given page and below.
252 *
253 * @param params A Map of parameter class names to parameter
254 * values to pass into validation methods.
255 * @param actions A Map of validator names to ValidatorAction
256 * objects.
257 * @param page Fields on pages higher than this will not be
258 * validated.
259 * @return A ValidatorResults object containing all
260 * validation messages.
261 * @throws ValidatorException
262 * @since 1.2.0
263 */
264 ValidatorResults validate(Map params, Map actions, int page, String fieldName)
265 throws ValidatorException {
266
267 ValidatorResults results = new ValidatorResults();
268 params.put(Validator.VALIDATOR_RESULTS_PARAM, results);
269
270
271 if (fieldName != null) {
272 Field field = (Field) this.hFields.get(fieldName);
273
274 if (field == null) {
275 throw new ValidatorException("Unknown field "+fieldName+" in form "+getName());
276 }
277 params.put(Validator.FIELD_PARAM, field);
278
279 if (field.getPage() <= page) {
280 results.merge(field.validate(params, actions));
281 }
282 } else {
283 Iterator fields = this.lFields.iterator();
284 while (fields.hasNext()) {
285 Field field = (Field) fields.next();
286
287 params.put(Validator.FIELD_PARAM, field);
288
289 if (field.getPage() <= page) {
290 results.merge(field.validate(params, actions));
291 }
292 }
293 }
294
295 return results;
296 }
297
298 /***
299 * Whether or not the this <code>Form</code> was processed for replacing
300 * variables in strings with their values.
301 *
302 * @return The processed value
303 * @since Validator 1.2.0
304 */
305 public boolean isProcessed() {
306 return processed;
307 }
308
309 /***
310 * Gets the name/key of the parent set of validation rules.
311 *
312 * @return The extends value
313 * @since Validator 1.2.0
314 */
315 public String getExtends() {
316 return inherit;
317 }
318
319 /***
320 * Sets the name/key of the parent set of validation rules.
321 *
322 * @param inherit The new extends value
323 * @since Validator 1.2.0
324 */
325 public void setExtends(String inherit) {
326 this.inherit = inherit;
327 }
328
329 /***
330 * Get extends flag.
331 *
332 * @return The extending value
333 * @since Validator 1.2.0
334 */
335 public boolean isExtending() {
336 return inherit != null;
337 }
338
339 /***
340 * Returns a Map of String field keys to Field objects.
341 *
342 * @return The fieldMap value
343 * @since Validator 1.2.0
344 */
345 protected Map getFieldMap() {
346 return hFields;
347 }
348 }