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