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 */ 017 package org.apache.commons.validator; 018 019 import java.io.Serializable; 020 import java.util.ArrayList; 021 import java.util.Collections; 022 import java.util.Iterator; 023 import java.util.List; 024 import java.util.Map; 025 026 import 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: 493905 $ $Date: 2007-01-08 03:11:38 +0100 (Mo, 08. Jan 2007) $ 039 */ 040 public class Form implements Serializable { 041 042 /** The name/key the set of validation rules is stored under. */ 043 protected String name = null; 044 045 /** 046 * List of <code>Field</code>s. Used to maintain the order they were added 047 * in although individual <code>Field</code>s can be retrieved using <code>Map</code> 048 * of <code>Field</code>s. 049 */ 050 protected List lFields = new ArrayList(); 051 052 /** 053 * Map of <code>Field</code>s keyed on their property value. 054 * 055 * @deprecated Subclasses should use getFieldMap() instead. 056 */ 057 protected FastHashMap hFields = new FastHashMap(); 058 059 /** 060 * The name/key of the form which this form extends from. 061 * 062 * @since Validator 1.2.0 063 */ 064 protected String inherit = null; 065 066 /** 067 * Whether or not the this <code>Form</code> was processed for replacing 068 * variables in strings with their values. 069 */ 070 private boolean processed = false; 071 072 /** 073 * Gets the name/key of the set of validation rules. 074 * 075 * @return The name value 076 */ 077 public String getName() { 078 return name; 079 } 080 081 /** 082 * Sets the name/key of the set of validation rules. 083 * 084 * @param name The new name value 085 */ 086 public void setName(String name) { 087 this.name = name; 088 } 089 090 /** 091 * Add a <code>Field</code> to the <code>Form</code>. 092 * 093 * @param f The field 094 */ 095 public void addField(Field f) { 096 this.lFields.add(f); 097 this.hFields.put(f.getKey(), f); 098 } 099 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 }