001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.validator; 018 019import java.io.Serializable; 020import java.util.ArrayList; 021import java.util.Collections; 022import java.util.Iterator; 023import java.util.List; 024import java.util.Map; 025 026import org.apache.commons.collections.FastHashMap;// DEPRECATED 027 028/** 029 * <p> 030 * 031 * This contains a set of validation rules for a form/JavaBean. The information 032 * is contained in a list of <code>Field</code> objects. Instances of this class 033 * are configured with a <form> xml element. </p> <p> 034 * 035 * The use of FastHashMap is deprecated and will be replaced in a future 036 * release. </p> 037 * 038 * @version $Revision: 1227719 $ $Date: 2012-01-05 12:45:51 -0500 (Thu, 05 Jan 2012) $ 039 */ 040public class Form implements Serializable { 041 042 private static final long serialVersionUID = 6445211789563796371L; 043 044 /** The name/key the set of validation rules is stored under. */ 045 protected String name = null; 046 047 /** 048 * List of <code>Field</code>s. Used to maintain the order they were added 049 * in although individual <code>Field</code>s can be retrieved using <code>Map</code> 050 * of <code>Field</code>s. 051 */ 052 protected List lFields = new ArrayList(); 053 054 /** 055 * Map of <code>Field</code>s keyed on their property value. 056 * 057 * @deprecated Subclasses should use getFieldMap() instead. 058 */ 059 protected FastHashMap hFields = new FastHashMap(); 060 061 /** 062 * The name/key of the form which this form extends from. 063 * 064 * @since Validator 1.2.0 065 */ 066 protected String inherit = null; 067 068 /** 069 * Whether or not the this <code>Form</code> was processed for replacing 070 * variables in strings with their values. 071 */ 072 private boolean processed = false; 073 074 /** 075 * Gets the name/key of the set of validation rules. 076 * 077 * @return The name value 078 */ 079 public String getName() { 080 return name; 081 } 082 083 /** 084 * Sets the name/key of the set of validation rules. 085 * 086 * @param name The new name value 087 */ 088 public void setName(String name) { 089 this.name = name; 090 } 091 092 /** 093 * Add a <code>Field</code> to the <code>Form</code>. 094 * 095 * @param f The field 096 */ 097 public void addField(Field f) { 098 this.lFields.add(f); 099 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}