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$ 039 */ 040//TODO mutable non-private fields 041public class Form implements Serializable { 042 043 private static final long serialVersionUID = 6445211789563796371L; 044 045 /** The name/key the set of validation rules is stored under. */ 046 protected String name = null; 047 048 /** 049 * List of <code>Field</code>s. Used to maintain the order they were added 050 * in although individual <code>Field</code>s can be retrieved using <code>Map</code> 051 * of <code>Field</code>s. 052 */ 053 protected List<Field> lFields = new ArrayList<Field>(); 054 055 /** 056 * Map of <code>Field</code>s keyed on their property value. 057 * 058 * @deprecated Subclasses should use getFieldMap() instead. 059 */ 060 @Deprecated 061 protected FastHashMap hFields = new FastHashMap(); // <String, Field> 062 063 /** 064 * The name/key of the form which this form extends from. 065 * 066 * @since Validator 1.2.0 067 */ 068 protected String inherit = null; 069 070 /** 071 * Whether or not the this <code>Form</code> was processed for replacing 072 * variables in strings with their values. 073 */ 074 private boolean processed = false; 075 076 /** 077 * Gets the name/key of the set of validation rules. 078 * 079 * @return The name value 080 */ 081 public String getName() { 082 return name; 083 } 084 085 /** 086 * Sets the name/key of the set of validation rules. 087 * 088 * @param name The new name value 089 */ 090 public void setName(String name) { 091 this.name = name; 092 } 093 094 /** 095 * Add a <code>Field</code> to the <code>Form</code>. 096 * 097 * @param f The field 098 */ 099 public void addField(Field f) { 100 this.lFields.add(f); 101 getFieldMap().put(f.getKey(), f); 102 } 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 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 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 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 List<Field> templFields = new ArrayList<Field>(); 148 @SuppressWarnings("unchecked") // FastHashMap is not generic 149 Map<String, Field> temphFields = new FastHashMap(); 150 Iterator<Field> dependsIt = depends.getFields().iterator(); 151 while (dependsIt.hasNext()) { 152 Field defaultField = dependsIt.next(); 153 if (defaultField != null) { 154 String fieldKey = defaultField.getKey(); 155 if (!this.containsField(fieldKey)) { 156 templFields.add(defaultField); 157 temphFields.put(fieldKey, defaultField); 158 } 159 else { 160 Field old = getField(fieldKey); 161 getFieldMap().remove(fieldKey); 162 lFields.remove(old); 163 templFields.add(old); 164 temphFields.put(fieldKey, old); 165 } 166 } 167 } 168 lFields.addAll(0, templFields); 169 getFieldMap().putAll(temphFields); 170 } 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 if (isProcessed()) { 182 return; 183 } 184 185 int n = 0;//we want the fields from its parent first 186 if (isExtending()) { 187 Form parent = forms.get(inherit); 188 if (parent != null) { 189 if (!parent.isProcessed()) { 190 //we want to go all the way up the tree 191 parent.process(constants, globalConstants, forms); 192 } 193 for (Iterator<Field> i = parent.getFields().iterator(); i.hasNext(); ) { 194 Field f = i.next(); 195 //we want to be able to override any fields we like 196 if (getFieldMap().get(f.getKey()) == null) { 197 lFields.add(n, f); 198 getFieldMap().put(f.getKey(), f); 199 n++; 200 } 201 } 202 } 203 } 204 hFields.setFast(true); 205 //no need to reprocess parent's fields, we iterate from 'n' 206 for (Iterator<Field> i = lFields.listIterator(n); i.hasNext(); ) { 207 Field f = i.next(); 208 f.process(globalConstants, constants); 209 } 210 211 processed = true; 212 } 213 214 /** 215 * Returns a string representation of the object. 216 * 217 * @return string representation 218 */ 219 @Override 220 public String toString() { 221 StringBuilder results = new StringBuilder(); 222 223 results.append("Form: "); 224 results.append(name); 225 results.append("\n"); 226 227 for (Iterator<Field> i = lFields.iterator(); i.hasNext(); ) { 228 results.append("\tField: \n"); 229 results.append(i.next()); 230 results.append("\n"); 231 } 232 233 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 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 ValidatorResults results = new ValidatorResults(); 271 params.put(Validator.VALIDATOR_RESULTS_PARAM, results); 272 273 // Only validate a single field if specified 274 if (fieldName != null) { 275 Field field = getFieldMap().get(fieldName); 276 277 if (field == null) { 278 throw new ValidatorException("Unknown field "+fieldName+" in form "+getName()); 279 } 280 params.put(Validator.FIELD_PARAM, field); 281 282 if (field.getPage() <= page) { 283 results.merge(field.validate(params, actions)); 284 } 285 } else { 286 Iterator<Field> fields = this.lFields.iterator(); 287 while (fields.hasNext()) { 288 Field field = fields.next(); 289 290 params.put(Validator.FIELD_PARAM, field); 291 292 if (field.getPage() <= page) { 293 results.merge(field.validate(params, actions)); 294 } 295 } 296 } 297 298 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 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 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 this.inherit = inherit; 330 } 331 332 /** 333 * Get extends flag. 334 * 335 * @return The extending value 336 * @since Validator 1.2.0 337 */ 338 public boolean isExtending() { 339 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 return hFields; 351 } 352}