Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
Form |
|
| 2.125;2.125 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
3 | * contributor license agreements. See the NOTICE file distributed with | |
4 | * this work for additional information regarding copyright ownership. | |
5 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
6 | * (the "License"); you may not use this file except in compliance with | |
7 | * the License. You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, software | |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
15 | * limitations under the License. | |
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;// DEPRECATED | |
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: 1739361 $ | |
39 | */ | |
40 | //TODO mutable non-private fields | |
41 | 430 | public class Form implements Serializable { |
42 | ||
43 | private static final long serialVersionUID = 6445211789563796371L; | |
44 | ||
45 | /** The name/key the set of validation rules is stored under. */ | |
46 | 430 | protected String name = null; |
47 | ||
48 | /** | |
49 | * List of <code>Field</code>s. Used to maintain the order they were added | |
50 | * in although individual <code>Field</code>s can be retrieved using <code>Map</code> | |
51 | * of <code>Field</code>s. | |
52 | */ | |
53 | 430 | protected List<Field> lFields = new ArrayList<Field>(); |
54 | ||
55 | /** | |
56 | * Map of <code>Field</code>s keyed on their property value. | |
57 | * | |
58 | * @deprecated Subclasses should use getFieldMap() instead. | |
59 | */ | |
60 | 430 | @Deprecated |
61 | protected FastHashMap hFields = new FastHashMap(); // <String, Field> | |
62 | ||
63 | /** | |
64 | * The name/key of the form which this form extends from. | |
65 | * | |
66 | * @since Validator 1.2.0 | |
67 | */ | |
68 | 430 | protected String inherit = null; |
69 | ||
70 | /** | |
71 | * Whether or not the this <code>Form</code> was processed for replacing | |
72 | * variables in strings with their values. | |
73 | */ | |
74 | 430 | private boolean processed = false; |
75 | ||
76 | /** | |
77 | * Gets the name/key of the set of validation rules. | |
78 | * | |
79 | * @return The name value | |
80 | */ | |
81 | public String getName() { | |
82 | 970 | return name; |
83 | } | |
84 | ||
85 | /** | |
86 | * Sets the name/key of the set of validation rules. | |
87 | * | |
88 | * @param name The new name value | |
89 | */ | |
90 | public void setName(String name) { | |
91 | 430 | this.name = name; |
92 | 430 | } |
93 | ||
94 | /** | |
95 | * Add a <code>Field</code> to the <code>Form</code>. | |
96 | * | |
97 | * @param f The field | |
98 | */ | |
99 | public void addField(Field f) { | |
100 | 533 | this.lFields.add(f); |
101 | 533 | getFieldMap().put(f.getKey(), f); |
102 | 533 | } |
103 | ||
104 | /** | |
105 | * A <code>List</code> of <code>Field</code>s is returned as an unmodifiable | |
106 | * <code>List</code>. | |
107 | * | |
108 | * @return The fields value | |
109 | */ | |
110 | public List<Field> getFields() { | |
111 | 77 | return Collections.unmodifiableList(lFields); |
112 | } | |
113 | ||
114 | /** | |
115 | * Returns the Field with the given name or null if this Form has no such | |
116 | * field. | |
117 | * | |
118 | * @param fieldName The field name | |
119 | * @return The field value | |
120 | * @since Validator 1.1 | |
121 | */ | |
122 | public Field getField(String fieldName) { | |
123 | 100 | return getFieldMap().get(fieldName); |
124 | } | |
125 | ||
126 | /** | |
127 | * Returns true if this Form contains a Field with the given name. | |
128 | * | |
129 | * @param fieldName The field name | |
130 | * @return True if this form contains the field by the given name | |
131 | * @since Validator 1.1 | |
132 | */ | |
133 | public boolean containsField(String fieldName) { | |
134 | 70 | return getFieldMap().containsKey(fieldName); |
135 | } | |
136 | ||
137 | /** | |
138 | * Merges the given form into this one. For any field in <code>depends</code> | |
139 | * not present in this form, include it. <code>depends</code> has precedence | |
140 | * in the way the fields are ordered. | |
141 | * | |
142 | * @param depends the form we want to merge | |
143 | * @since Validator 1.2.0 | |
144 | */ | |
145 | protected void merge(Form depends) { | |
146 | ||
147 | 55 | List<Field> templFields = new ArrayList<Field>(); |
148 | @SuppressWarnings("unchecked") // FastHashMap is not generic | |
149 | 55 | Map<String, Field> temphFields = new FastHashMap(); |
150 | 55 | Iterator<Field> dependsIt = depends.getFields().iterator(); |
151 | 125 | while (dependsIt.hasNext()) { |
152 | 70 | Field defaultField = dependsIt.next(); |
153 | 70 | if (defaultField != null) { |
154 | 70 | String fieldKey = defaultField.getKey(); |
155 | 70 | if (!this.containsField(fieldKey)) { |
156 | 0 | templFields.add(defaultField); |
157 | 0 | temphFields.put(fieldKey, defaultField); |
158 | } | |
159 | else { | |
160 | 70 | Field old = getField(fieldKey); |
161 | 70 | getFieldMap().remove(fieldKey); |
162 | 70 | lFields.remove(old); |
163 | 70 | templFields.add(old); |
164 | 70 | temphFields.put(fieldKey, old); |
165 | } | |
166 | } | |
167 | 70 | } |
168 | 55 | lFields.addAll(0, templFields); |
169 | 55 | getFieldMap().putAll(temphFields); |
170 | 55 | } |
171 | ||
172 | /** | |
173 | * Processes all of the <code>Form</code>'s <code>Field</code>s. | |
174 | * | |
175 | * @param globalConstants A map of global constants | |
176 | * @param constants Local constants | |
177 | * @param forms Map of forms | |
178 | * @since Validator 1.2.0 | |
179 | */ | |
180 | protected void process(Map<String, String> globalConstants, Map<String, String> constants, Map<String, Form> forms) { | |
181 | 493 | if (isProcessed()) { |
182 | 63 | return; |
183 | } | |
184 | ||
185 | 430 | int n = 0;//we want the fields from its parent first |
186 | 430 | if (isExtending()) { |
187 | 16 | Form parent = forms.get(inherit); |
188 | 16 | if (parent != null) { |
189 | 16 | if (!parent.isProcessed()) { |
190 | //we want to go all the way up the tree | |
191 | 8 | parent.process(constants, globalConstants, forms); |
192 | } | |
193 | 16 | for (Iterator<Field> i = parent.getFields().iterator(); i.hasNext(); ) { |
194 | 24 | Field f = i.next(); |
195 | //we want to be able to override any fields we like | |
196 | 24 | if (getFieldMap().get(f.getKey()) == null) { |
197 | 8 | lFields.add(n, f); |
198 | 8 | getFieldMap().put(f.getKey(), f); |
199 | 8 | n++; |
200 | } | |
201 | 24 | } |
202 | } | |
203 | } | |
204 | 430 | hFields.setFast(true); |
205 | //no need to reprocess parent's fields, we iterate from 'n' | |
206 | 430 | for (Iterator<Field> i = lFields.listIterator(n); i.hasNext(); ) { |
207 | 533 | Field f = i.next(); |
208 | 533 | f.process(globalConstants, constants); |
209 | 533 | } |
210 | ||
211 | 430 | processed = true; |
212 | 430 | } |
213 | ||
214 | /** | |
215 | * Returns a string representation of the object. | |
216 | * | |
217 | * @return string representation | |
218 | */ | |
219 | @Override | |
220 | public String toString() { | |
221 | 0 | StringBuilder results = new StringBuilder(); |
222 | ||
223 | 0 | results.append("Form: "); |
224 | 0 | results.append(name); |
225 | 0 | results.append("\n"); |
226 | ||
227 | 0 | for (Iterator<Field> i = lFields.iterator(); i.hasNext(); ) { |
228 | 0 | results.append("\tField: \n"); |
229 | 0 | results.append(i.next()); |
230 | 0 | results.append("\n"); |
231 | } | |
232 | ||
233 | 0 | return results.toString(); |
234 | } | |
235 | ||
236 | /** | |
237 | * Validate all Fields in this Form on the given page and below. | |
238 | * | |
239 | * @param params A Map of parameter class names to parameter | |
240 | * values to pass into validation methods. | |
241 | * @param actions A Map of validator names to ValidatorAction | |
242 | * objects. | |
243 | * @param page Fields on pages higher than this will not be | |
244 | * validated. | |
245 | * @return A ValidatorResults object containing all | |
246 | * validation messages. | |
247 | * @throws ValidatorException | |
248 | */ | |
249 | ValidatorResults validate(Map<String, Object> params, Map<String, ValidatorAction> actions, int page) | |
250 | throws ValidatorException { | |
251 | 0 | return validate(params, actions, page, null); |
252 | } | |
253 | ||
254 | /** | |
255 | * Validate all Fields in this Form on the given page and below. | |
256 | * | |
257 | * @param params A Map of parameter class names to parameter | |
258 | * values to pass into validation methods. | |
259 | * @param actions A Map of validator names to ValidatorAction | |
260 | * objects. | |
261 | * @param page Fields on pages higher than this will not be | |
262 | * validated. | |
263 | * @return A ValidatorResults object containing all | |
264 | * validation messages. | |
265 | * @throws ValidatorException | |
266 | * @since 1.2.0 | |
267 | */ | |
268 | ValidatorResults validate(Map<String, Object> params, Map<String, ValidatorAction> actions, int page, String fieldName) | |
269 | throws ValidatorException { | |
270 | 125 | ValidatorResults results = new ValidatorResults(); |
271 | 125 | params.put(Validator.VALIDATOR_RESULTS_PARAM, results); |
272 | ||
273 | // Only validate a single field if specified | |
274 | 125 | if (fieldName != null) { |
275 | 1 | Field field = getFieldMap().get(fieldName); |
276 | ||
277 | 1 | if (field == null) { |
278 | 0 | throw new ValidatorException("Unknown field "+fieldName+" in form "+getName()); |
279 | } | |
280 | 1 | params.put(Validator.FIELD_PARAM, field); |
281 | ||
282 | 1 | if (field.getPage() <= page) { |
283 | 1 | results.merge(field.validate(params, actions)); |
284 | } | |
285 | 1 | } else { |
286 | 124 | Iterator<Field> fields = this.lFields.iterator(); |
287 | 312 | while (fields.hasNext()) { |
288 | 189 | Field field = fields.next(); |
289 | ||
290 | 189 | params.put(Validator.FIELD_PARAM, field); |
291 | ||
292 | 189 | if (field.getPage() <= page) { |
293 | 189 | results.merge(field.validate(params, actions)); |
294 | } | |
295 | 188 | } |
296 | } | |
297 | ||
298 | 124 | return results; |
299 | } | |
300 | ||
301 | /** | |
302 | * Whether or not the this <code>Form</code> was processed for replacing | |
303 | * variables in strings with their values. | |
304 | * | |
305 | * @return The processed value | |
306 | * @since Validator 1.2.0 | |
307 | */ | |
308 | public boolean isProcessed() { | |
309 | 509 | return processed; |
310 | } | |
311 | ||
312 | /** | |
313 | * Gets the name/key of the parent set of validation rules. | |
314 | * | |
315 | * @return The extends value | |
316 | * @since Validator 1.2.0 | |
317 | */ | |
318 | public String getExtends() { | |
319 | 0 | return inherit; |
320 | } | |
321 | ||
322 | /** | |
323 | * Sets the name/key of the parent set of validation rules. | |
324 | * | |
325 | * @param inherit The new extends value | |
326 | * @since Validator 1.2.0 | |
327 | */ | |
328 | public void setExtends(String inherit) { | |
329 | 16 | this.inherit = inherit; |
330 | 16 | } |
331 | ||
332 | /** | |
333 | * Get extends flag. | |
334 | * | |
335 | * @return The extending value | |
336 | * @since Validator 1.2.0 | |
337 | */ | |
338 | public boolean isExtending() { | |
339 | 430 | return inherit != null; |
340 | } | |
341 | ||
342 | /** | |
343 | * Returns a Map of String field keys to Field objects. | |
344 | * | |
345 | * @return The fieldMap value | |
346 | * @since Validator 1.2.0 | |
347 | */ | |
348 | @SuppressWarnings("unchecked") // FastHashMap is not generic | |
349 | protected Map<String, Field> getFieldMap() { | |
350 | 861 | return hFields; |
351 | } | |
352 | } |