View Javadoc

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 &lt;form&gt; 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;//we want the fields from its parent first
181         if (isExtending()) {
182             Form parent = (Form) forms.get(inherit);
183             if (parent != null) {
184                 if (!parent.isProcessed()) {
185                     //we want to go all the way up the tree
186                     parent.process(constants, globalConstants, forms);
187                 }
188                 for (Iterator i = parent.getFields().iterator(); i.hasNext(); ) {
189                     Field f = (Field) i.next();
190                     //we want to be able to override any fields we like
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         //no need to reprocess parent's fields, we iterate from 'n'
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         // Only validate a single field if specified
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 }