View Javadoc

1   /*
2    * $Id: Form.java 280974 2005-09-15 00:06:59Z niallp $
3    * $Rev: 280974 $
4    * $Date: 2005-09-15 01:06:59 +0100 (Thu, 15 Sep 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.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;// DEPRECATED
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 &lt;form&gt; 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;//we want the fields from its parent first
183         if (isExtending()) {
184             Form parent = (Form) forms.get(inherit);
185             if (parent != null) {
186                 if (!parent.isProcessed()) {
187                     //we want to go all the way up the tree
188                     parent.process(constants, globalConstants, forms);
189                 }
190                 for (Iterator i = parent.getFields().iterator(); i.hasNext(); ) {
191                     Field f = (Field) i.next();
192                     //we want to be able to override any fields we like
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         //no need to reprocess parent's fields, we iterate from 'n'
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         // Only validate a single field if specified
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 }