| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| Form |
|
| 2.125;2.125 |
| 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 <form> 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: 1739361 $ | |
| 39 | */ | |
| 40 | //TODO mutable non-private fields | |
| 41 | 430 | public class Form implements Serializable { |
| 42 | ||
| 43 | private static final long serialVersionUID = 6445211789563796371L; | |
| 44 | ||
| 45 | /** The name/key the set of validation rules is stored under. */ | |
| 46 | 430 | protected String name = null; |
| 47 | ||
| 48 | /** | |
| 49 | * List of <code>Field</code>s. Used to maintain the order they were added | |
| 50 | * in although individual <code>Field</code>s can be retrieved using <code>Map</code> | |
| 51 | * of <code>Field</code>s. | |
| 52 | */ | |
| 53 | 430 | protected List<Field> lFields = new ArrayList<Field>(); |
| 54 | ||
| 55 | /** | |
| 56 | * Map of <code>Field</code>s keyed on their property value. | |
| 57 | * | |
| 58 | * @deprecated Subclasses should use getFieldMap() instead. | |
| 59 | */ | |
| 60 | 430 | @Deprecated |
| 61 | protected FastHashMap hFields = new FastHashMap(); // <String, Field> | |
| 62 | ||
| 63 | /** | |
| 64 | * The name/key of the form which this form extends from. | |
| 65 | * | |
| 66 | * @since Validator 1.2.0 | |
| 67 | */ | |
| 68 | 430 | protected String inherit = null; |
| 69 | ||
| 70 | /** | |
| 71 | * Whether or not the this <code>Form</code> was processed for replacing | |
| 72 | * variables in strings with their values. | |
| 73 | */ | |
| 74 | 430 | private boolean processed = false; |
| 75 | ||
| 76 | /** | |
| 77 | * Gets the name/key of the set of validation rules. | |
| 78 | * | |
| 79 | * @return The name value | |
| 80 | */ | |
| 81 | public String getName() { | |
| 82 | 970 | return name; |
| 83 | } | |
| 84 | ||
| 85 | /** | |
| 86 | * Sets the name/key of the set of validation rules. | |
| 87 | * | |
| 88 | * @param name The new name value | |
| 89 | */ | |
| 90 | public void setName(String name) { | |
| 91 | 430 | this.name = name; |
| 92 | 430 | } |
| 93 | ||
| 94 | /** | |
| 95 | * Add a <code>Field</code> to the <code>Form</code>. | |
| 96 | * | |
| 97 | * @param f The field | |
| 98 | */ | |
| 99 | public void addField(Field f) { | |
| 100 | 533 | this.lFields.add(f); |
| 101 | 533 | getFieldMap().put(f.getKey(), f); |
| 102 | 533 | } |
| 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 | 77 | 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 | 100 | 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 | 70 | 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 | 55 | List<Field> templFields = new ArrayList<Field>(); |
| 148 | @SuppressWarnings("unchecked") // FastHashMap is not generic | |
| 149 | 55 | Map<String, Field> temphFields = new FastHashMap(); |
| 150 | 55 | Iterator<Field> dependsIt = depends.getFields().iterator(); |
| 151 | 125 | while (dependsIt.hasNext()) { |
| 152 | 70 | Field defaultField = dependsIt.next(); |
| 153 | 70 | if (defaultField != null) { |
| 154 | 70 | String fieldKey = defaultField.getKey(); |
| 155 | 70 | if (!this.containsField(fieldKey)) { |
| 156 | 0 | templFields.add(defaultField); |
| 157 | 0 | temphFields.put(fieldKey, defaultField); |
| 158 | } | |
| 159 | else { | |
| 160 | 70 | Field old = getField(fieldKey); |
| 161 | 70 | getFieldMap().remove(fieldKey); |
| 162 | 70 | lFields.remove(old); |
| 163 | 70 | templFields.add(old); |
| 164 | 70 | temphFields.put(fieldKey, old); |
| 165 | } | |
| 166 | } | |
| 167 | 70 | } |
| 168 | 55 | lFields.addAll(0, templFields); |
| 169 | 55 | getFieldMap().putAll(temphFields); |
| 170 | 55 | } |
| 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 | 493 | if (isProcessed()) { |
| 182 | 63 | return; |
| 183 | } | |
| 184 | ||
| 185 | 430 | int n = 0;//we want the fields from its parent first |
| 186 | 430 | if (isExtending()) { |
| 187 | 16 | Form parent = forms.get(inherit); |
| 188 | 16 | if (parent != null) { |
| 189 | 16 | if (!parent.isProcessed()) { |
| 190 | //we want to go all the way up the tree | |
| 191 | 8 | parent.process(constants, globalConstants, forms); |
| 192 | } | |
| 193 | 16 | for (Iterator<Field> i = parent.getFields().iterator(); i.hasNext(); ) { |
| 194 | 24 | Field f = i.next(); |
| 195 | //we want to be able to override any fields we like | |
| 196 | 24 | if (getFieldMap().get(f.getKey()) == null) { |
| 197 | 8 | lFields.add(n, f); |
| 198 | 8 | getFieldMap().put(f.getKey(), f); |
| 199 | 8 | n++; |
| 200 | } | |
| 201 | 24 | } |
| 202 | } | |
| 203 | } | |
| 204 | 430 | hFields.setFast(true); |
| 205 | //no need to reprocess parent's fields, we iterate from 'n' | |
| 206 | 430 | for (Iterator<Field> i = lFields.listIterator(n); i.hasNext(); ) { |
| 207 | 533 | Field f = i.next(); |
| 208 | 533 | f.process(globalConstants, constants); |
| 209 | 533 | } |
| 210 | ||
| 211 | 430 | processed = true; |
| 212 | 430 | } |
| 213 | ||
| 214 | /** | |
| 215 | * Returns a string representation of the object. | |
| 216 | * | |
| 217 | * @return string representation | |
| 218 | */ | |
| 219 | @Override | |
| 220 | public String toString() { | |
| 221 | 0 | StringBuilder results = new StringBuilder(); |
| 222 | ||
| 223 | 0 | results.append("Form: "); |
| 224 | 0 | results.append(name); |
| 225 | 0 | results.append("\n"); |
| 226 | ||
| 227 | 0 | for (Iterator<Field> i = lFields.iterator(); i.hasNext(); ) { |
| 228 | 0 | results.append("\tField: \n"); |
| 229 | 0 | results.append(i.next()); |
| 230 | 0 | results.append("\n"); |
| 231 | } | |
| 232 | ||
| 233 | 0 | 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 | 0 | 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 | 125 | ValidatorResults results = new ValidatorResults(); |
| 271 | 125 | params.put(Validator.VALIDATOR_RESULTS_PARAM, results); |
| 272 | ||
| 273 | // Only validate a single field if specified | |
| 274 | 125 | if (fieldName != null) { |
| 275 | 1 | Field field = getFieldMap().get(fieldName); |
| 276 | ||
| 277 | 1 | if (field == null) { |
| 278 | 0 | throw new ValidatorException("Unknown field "+fieldName+" in form "+getName()); |
| 279 | } | |
| 280 | 1 | params.put(Validator.FIELD_PARAM, field); |
| 281 | ||
| 282 | 1 | if (field.getPage() <= page) { |
| 283 | 1 | results.merge(field.validate(params, actions)); |
| 284 | } | |
| 285 | 1 | } else { |
| 286 | 124 | Iterator<Field> fields = this.lFields.iterator(); |
| 287 | 312 | while (fields.hasNext()) { |
| 288 | 189 | Field field = fields.next(); |
| 289 | ||
| 290 | 189 | params.put(Validator.FIELD_PARAM, field); |
| 291 | ||
| 292 | 189 | if (field.getPage() <= page) { |
| 293 | 189 | results.merge(field.validate(params, actions)); |
| 294 | } | |
| 295 | 188 | } |
| 296 | } | |
| 297 | ||
| 298 | 124 | 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 | 509 | 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 | 0 | 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 | 16 | this.inherit = inherit; |
| 330 | 16 | } |
| 331 | ||
| 332 | /** | |
| 333 | * Get extends flag. | |
| 334 | * | |
| 335 | * @return The extending value | |
| 336 | * @since Validator 1.2.0 | |
| 337 | */ | |
| 338 | public boolean isExtending() { | |
| 339 | 430 | 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 | 861 | return hFields; |
| 351 | } | |
| 352 | } |