Coverage report

| %line | %branch
--- | --- | ---
org.apache.commons.validator.Field |
61% |
88% |

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.lang.reflect.InvocationTargetException;
21 |  |
     import java.util.ArrayList;
22 |  |
     import java.util.Collection;
23 |  |
     import java.util.Collections;
24 |  |
     import java.util.HashMap;
25 |  |
     import java.util.Iterator;
26 |  |
     import java.util.List;
27 |  |
     import java.util.Map;
28 |  |
     import java.util.StringTokenizer;
29 |  |
30 |  |
     import org.apache.commons.beanutils.PropertyUtils;
31 |  |
     import org.apache.commons.collections.FastHashMap; // DEPRECATED
32 |  |
     import org.apache.commons.validator.util.ValidatorUtils;
33 |  |
34 |  |
     /**
35 |  |
      * This contains the list of pluggable validators to run on a field and any
36 |  |
      * message information and variables to perform the validations and generate
37 |  |
      * error messages.  Instances of this class are configured with a
38 |  |
      * &lt;field&gt; xml element.
39 |  |
      * <p>
40 |  |
      * The use of FastHashMap is deprecated and will be replaced in a future
41 |  |
      * release.
42 |  |
      * </p>
43 |  |
      *
44 |  |
      * @version $Revision: 478334 $ $Date: 2006-11-22 21:31:54 +0000 (Wed, 22 Nov 2006) $
45 |  |
      * @see org.apache.commons.validator.Form
46 |  |
      */
47 | 1044 |
     public class Field implements Cloneable, Serializable {
48 |  |
49 |  |
         /**
50 |  |
          * This is the value that will be used as a key if the <code>Arg</code>
51 |  |
          * name field has no value.
52 |  |
          */
53 |  |
         private static final String DEFAULT_ARG =
54 |  |
                 "org.apache.commons.validator.Field.DEFAULT";
55 |  |
56 |  |
         /**
57 |  |
          * This indicates an indexed property is being referenced.
58 |  |
          */
59 |  |
         public static final String TOKEN_INDEXED = "[]";
60 |  |
61 |  |
         /**
62 |  |
          * The start of a token.
63 |  |
          */
64 |  |
         protected static final String TOKEN_START = "${";
65 |  |
66 |  |
         /**
67 |  |
          * The end of a token.
68 |  |
          */
69 |  |
         protected static final String TOKEN_END = "}";
70 |  |
71 |  |
         /**
72 |  |
          * A Vriable token.
73 |  |
          */
74 |  |
         protected static final String TOKEN_VAR = "var:";
75 |  |
76 |  |
         /**
77 |  |
          * The Field's property name.
78 |  |
          */
79 | 522 |
         protected String property = null;
80 |  |
81 |  |
         /**
82 |  |
          * The Field's indexed property name.
83 |  |
          */
84 | 522 |
         protected String indexedProperty = null;
85 |  |
86 |  |
         /**
87 |  |
          * The Field's indexed list property name.
88 |  |
          */
89 | 522 |
         protected String indexedListProperty = null;
90 |  |
91 |  |
         /**
92 |  |
          * The Field's unique key.
93 |  |
          */
94 | 522 |
         protected String key = null;
95 |  |
96 |  |
         /**
97 |  |
          * A comma separated list of validator's this field depends on.
98 |  |
          */
99 | 522 |
         protected String depends = null;
100 |  |
101 |  |
         /**
102 |  |
          * The Page Number
103 |  |
          */
104 | 522 |
         protected int page = 0;
105 |  |
106 |  |
         /**
107 |  |
          * The order of the Field in the Form.
108 |  |
          */
109 | 522 |
         protected int fieldOrder = 0;
110 |  |
111 |  |
         /**
112 |  |
          * Internal representation of this.depends String as a List.  This List
113 |  |
          * gets updated whenever setDepends() gets called.  This List is
114 |  |
          * synchronized so a call to setDepends() (which clears the List) won't
115 |  |
          * interfere with a call to isDependency().
116 |  |
          */
117 | 522 |
         private List dependencyList = Collections.synchronizedList(new ArrayList());
118 |  |
119 |  |
         /**
120 |  |
          * @deprecated Subclasses should use getVarMap() instead.
121 |  |
          */
122 | 522 |
         protected FastHashMap hVars = new FastHashMap();
123 |  |
124 |  |
         /**
125 |  |
          * @deprecated Subclasses should use getMsgMap() instead.
126 |  |
          */
127 | 522 |
         protected FastHashMap hMsgs = new FastHashMap();
128 |  |
129 |  |
         /**
130 |  |
          * Holds Maps of arguments.  args[0] returns the Map for the first
131 |  |
          * replacement argument.  Start with a 0 length array so that it will
132 |  |
          * only grow to the size of the highest argument position.
133 |  |
          * @since Validator 1.1
134 |  |
          */
135 | 522 |
         protected Map[] args = new Map[0];
136 |  |
137 |  |
         /**
138 |  |
          * Gets the page value that the Field is associated with for
139 |  |
          * validation.
140 |  |
          * @return The page number.
141 |  |
          */
142 |  |
         public int getPage() {
143 | 163 |
             return this.page;
144 |  |
         }
145 |  |
146 |  |
         /**
147 |  |
          * Sets the page value that the Field is associated with for
148 |  |
          * validation.
149 |  |
          * @param page The page number.
150 |  |
          */
151 |  |
         public void setPage(int page) {
152 | 0 |
             this.page = page;
153 | 0 |
         }
154 |  |
155 |  |
         /**
156 |  |
          * Gets the position of the <code>Field</code> in the validation list.
157 |  |
          * @return The field position.
158 |  |
          */
159 |  |
         public int getFieldOrder() {
160 | 0 |
             return this.fieldOrder;
161 |  |
         }
162 |  |
163 |  |
         /**
164 |  |
          * Sets the position of the <code>Field</code> in the validation list.
165 |  |
          * @param fieldOrder The field position.
166 |  |
          */
167 |  |
         public void setFieldOrder(int fieldOrder) {
168 | 0 |
             this.fieldOrder = fieldOrder;
169 | 0 |
         }
170 |  |
171 |  |
         /**
172 |  |
          * Gets the property name of the field.
173 |  |
          * @return The field's property name.
174 |  |
          */
175 |  |
         public String getProperty() {
176 | 167 |
             return this.property;
177 |  |
         }
178 |  |
179 |  |
         /**
180 |  |
          * Sets the property name of the field.
181 |  |
          * @param property The field's property name.
182 |  |
          */
183 |  |
         public void setProperty(String property) {
184 | 513 |
             this.property = property;
185 | 513 |
         }
186 |  |
187 |  |
         /**
188 |  |
          * Gets the indexed property name of the field.  This
189 |  |
          * is the method name that can take an <code>int</code> as
190 |  |
          * a parameter for indexed property value retrieval.
191 |  |
          * @return The field's indexed property name.
192 |  |
          */
193 |  |
         public String getIndexedProperty() {
194 | 0 |
             return this.indexedProperty;
195 |  |
         }
196 |  |
197 |  |
         /**
198 |  |
          * Sets the indexed property name of the field.
199 |  |
          * @param indexedProperty The field's indexed property name.
200 |  |
          */
201 |  |
         public void setIndexedProperty(String indexedProperty) {
202 | 0 |
             this.indexedProperty = indexedProperty;
203 | 0 |
         }
204 |  |
205 |  |
         /**
206 |  |
          * Gets the indexed property name of the field.  This
207 |  |
          * is the method name that will return an array or a
208 |  |
          * <code>Collection</code> used to retrieve the
209 |  |
          * list and then loop through the list performing the specified
210 |  |
          * validations.
211 |  |
          * @return The field's indexed List property name.
212 |  |
          */
213 |  |
         public String getIndexedListProperty() {
214 | 0 |
             return this.indexedListProperty;
215 |  |
         }
216 |  |
217 |  |
         /**
218 |  |
          * Sets the indexed property name of the field.
219 |  |
          * @param indexedListProperty The field's indexed List property name.
220 |  |
          */
221 |  |
         public void setIndexedListProperty(String indexedListProperty) {
222 | 0 |
             this.indexedListProperty = indexedListProperty;
223 | 0 |
         }
224 |  |
225 |  |
         /**
226 |  |
          * Gets the validation rules for this field as a comma separated list.
227 |  |
          * @return A comma separated list of validator names.
228 |  |
          */
229 |  |
         public String getDepends() {
230 | 163 |
             return this.depends;
231 |  |
         }
232 |  |
233 |  |
         /**
234 |  |
          * Sets the validation rules for this field as a comma separated list.
235 |  |
          * @param depends A comma separated list of validator names.
236 |  |
          */
237 |  |
         public void setDepends(String depends) {
238 | 513 |
             this.depends = depends;
239 |  |
240 | 513 |
             this.dependencyList.clear();
241 |  |
242 | 513 |
             StringTokenizer st = new StringTokenizer(depends, ",");
243 | 1530 |
             while (st.hasMoreTokens()) {
244 | 504 |
                 String depend = st.nextToken().trim();
245 |  |
246 | 504 |
                 if (depend != null && depend.length() > 0) {
247 | 504 |
                     this.dependencyList.add(depend);
248 |  |
                 }
249 |  |
             }
250 | 513 |
         }
251 |  |
252 |  |
         /**
253 |  |
          * Add a <code>Msg</code> to the <code>Field</code>.
254 |  |
          * @param msg A validation message.
255 |  |
          */
256 |  |
         public void addMsg(Msg msg) {
257 | 0 |
             hMsgs.put(msg.getName(), msg);
258 | 0 |
         }
259 |  |
260 |  |
         /**
261 |  |
          * Retrieve a message value.
262 |  |
          * @param key Validation key.
263 |  |
          * @return A validation message for a specified validator.
264 |  |
          */
265 |  |
         public String getMsg(String key) {
266 | 0 |
             Msg msg = getMessage(key);
267 | 0 |
             return (msg == null) ? class="keyword">null : msg.getKey();
268 |  |
         }
269 |  |
270 |  |
         /**
271 |  |
          * Retrieve a message object.
272 |  |
          * @since Validator 1.1.4
273 |  |
          * @param key Validation key.
274 |  |
          * @return A validation message for a specified validator.
275 |  |
          */
276 |  |
         public Msg getMessage(String key) {
277 | 0 |
             return (Msg) hMsgs.get(key);
278 |  |
         }
279 |  |
280 |  |
         /**
281 |  |
          * The <code>Field</code>'s messages are returned as an
282 |  |
          * unmodifiable <code>Map</code>.
283 |  |
          * @since Validator 1.1.4
284 |  |
          * @return Map of validation messages for the field.
285 |  |
          */
286 |  |
         public Map getMessages() {
287 | 0 |
             return Collections.unmodifiableMap(hMsgs);
288 |  |
         }
289 |  |
290 |  |
         /**
291 |  |
          * Add an <code>Arg</code> to the replacement argument list.
292 |  |
          * @since Validator 1.1
293 |  |
          * @param arg Validation message's argument.
294 |  |
          */
295 |  |
         public void addArg(Arg arg) {
296 |  |
             // TODO this first if check can go away after arg0, etc. are removed from dtd
297 | 139 |
             if (arg == null || arg.getKey() == class="keyword">null || arg.getKey().length() == 0) {
298 | 0 |
                 return;
299 |  |
             }
300 |  |
301 | 139 |
             determineArgPosition(arg);
302 | 139 |
             ensureArgsCapacity(arg);
303 |  |
304 | 139 |
             Map argMap = this.args[arg.getPosition()];
305 | 139 |
             if (argMap == null) {
306 | 134 |
                 argMap = new HashMap();
307 | 134 |
                 this.args[arg.getPosition()] = argMap;
308 |  |
             }
309 |  |
310 | 139 |
             if (arg.getName() == null) {
311 | 130 |
                 argMap.put(DEFAULT_ARG, arg);
312 |  |
             } else {
313 | 9 |
                 argMap.put(arg.getName(), arg);
314 |  |
             }
315 |  |
316 | 139 |
         }
317 |  |
318 |  |
         /**
319 |  |
          * Calculate the position of the Arg
320 |  |
          */
321 |  |
         private void determineArgPosition(Arg arg) {
322 |  |
323 | 139 |
             int position = arg.getPosition();
324 |  |
325 |  |
             // position has been explicity set
326 | 139 |
             if (position >= 0) {
327 | 16 |
                 return;
328 |  |
             }
329 |  |
330 |  |
             // first arg to be added
331 | 123 |
             if (args == null || args.length == 0) {
332 | 107 |
                 arg.setPosition(0);
333 | 107 |
                 return;
334 |  |
             }
335 |  |
336 |  |
             // determine the position of the last argument with
337 |  |
             // the same name or the last default argument
338 | 16 |
             String key = arg.getName() == null ? DEFAULT_ARG : arg.getName();
339 | 16 |
             int lastPosition = -1;
340 | 16 |
             int lastDefault  = -1;
341 | 55 |
             for (int i = 0; i < args.length; i++) {
342 | 39 |
                 if (args[i] != null && args[i].containsKey(key)) {
343 | 18 |
                     lastPosition = i;
344 |  |
                 }
345 | 39 |
                 if (args[i] != null && args[i].containsKey(DEFAULT_ARG)) {
346 | 25 |
                     lastDefault = i;
347 |  |
                 }
348 |  |
             }
349 |  |
350 | 16 |
             if (lastPosition < 0) {
351 | 4 |
                 lastPosition = lastDefault;
352 |  |
             }
353 |  |
354 |  |
             // allocate the next position
355 | 16 |
             arg.setPosition(++lastPosition);
356 |  |
357 | 16 |
         }
358 |  |
359 |  |
         /**
360 |  |
          * Ensures that the args array can hold the given arg.  Resizes the array as
361 |  |
          * necessary.
362 |  |
          * @param arg Determine if the args array is long enough to store this arg's
363 |  |
          * position.
364 |  |
          */
365 |  |
         private void ensureArgsCapacity(Arg arg) {
366 | 139 |
             if (arg.getPosition() >= this.args.length) {
367 | 129 |
                 Map[] newArgs = new Map[arg.getPosition() + 1];
368 | 129 |
                 System.arraycopy(this.args, 0, newArgs, 0, class="keyword">this.args.length);
369 | 129 |
                 this.args = newArgs;
370 |  |
             }
371 | 139 |
         }
372 |  |
373 |  |
         /**
374 |  |
          * Gets the default <code>Arg</code> object at the given position.
375 |  |
          * @param position Validation message argument's position.
376 |  |
          * @return The default Arg or null if not found.
377 |  |
          * @since Validator 1.1
378 |  |
          */
379 |  |
         public Arg getArg(int position) {
380 | 69 |
             return this.getArg(DEFAULT_ARG, position);
381 |  |
         }
382 |  |
383 |  |
         /**
384 |  |
          * Gets the <code>Arg</code> object at the given position.  If the key
385 |  |
          * finds a <code>null</code> value then the default value will be
386 |  |
          * retrieved.
387 |  |
          * @param key The name the Arg is stored under.  If not found, the default
388 |  |
          * Arg for the given position (if any) will be retrieved.
389 |  |
          * @param position The Arg number to find.
390 |  |
          * @return The Arg with the given name and position or null if not found.
391 |  |
          * @since Validator 1.1
392 |  |
          */
393 |  |
         public Arg getArg(String key, int position) {
394 | 149 |
             if ((position >= this.args.length) || (class="keyword">this.args[position] == null)) {
395 | 2 |
                 return null;
396 |  |
             }
397 |  |
398 | 147 |
             Arg arg = (Arg) args[position].get(key);
399 |  |
400 |  |
             // Didn't find default arg so exit, otherwise we would get into
401 |  |
             // infinite recursion
402 | 147 |
             if ((arg == null) && key.equals(DEFAULT_ARG)) {
403 | 9 |
                 return null;
404 |  |
             }
405 |  |
406 | 138 |
             return (arg == null) ? this.getArg(position) : arg;
407 |  |
         }
408 |  |
409 |  |
         /**
410 |  |
          * Retrieves the Args for the given validator name.
411 |  |
          * @param key The validator's args to retrieve.
412 |  |
          * @return An Arg[] sorted by the Args' positions (i.e. the Arg at index 0
413 |  |
          * has a position of 0).
414 |  |
          * @since Validator 1.1.1
415 |  |
          */
416 |  |
         public Arg[] getArgs(String key){
417 | 13 |
             Arg[] args = new Arg[this.args.length];
418 |  |
419 | 55 |
             for (int i = 0; i < this.args.length; i++) {
420 | 42 |
                 args[i] = this.getArg(key, i);
421 |  |
             }
422 |  |
423 | 13 |
             return args;
424 |  |
         }
425 |  |
426 |  |
         /**
427 |  |
          * Add a <code>Var</code> to the <code>Field</code>.
428 |  |
          * @param v The Validator Argument.
429 |  |
          */
430 |  |
         public void addVar(Var v) {
431 | 125 |
             this.hVars.put(v.getName(), v);
432 | 125 |
         }
433 |  |
434 |  |
         /**
435 |  |
          * Add a <code>Var</code>, based on the values passed in, to the
436 |  |
          * <code>Field</code>.
437 |  |
          * @param name Name of the validation.
438 |  |
          * @param value The Argument's value.
439 |  |
          * @param jsType The Javascript type.
440 |  |
          */
441 |  |
         public void addVar(String name, String value, String jsType) {
442 | 0 |
             this.addVar(new Var(name, value, jsType));
443 | 0 |
         }
444 |  |
445 |  |
         /**
446 |  |
          * Retrieve a variable.
447 |  |
          * @param mainKey The Variable's key
448 |  |
          * @return the Variable
449 |  |
          */
450 |  |
         public Var getVar(String mainKey) {
451 | 208 |
             return (Var) hVars.get(mainKey);
452 |  |
         }
453 |  |
454 |  |
         /**
455 |  |
          * Retrieve a variable's value.
456 |  |
          * @param mainKey The Variable's key
457 |  |
          * @return the Variable's value
458 |  |
          */
459 |  |
         public String getVarValue(String mainKey) {
460 | 106 |
             String value = null;
461 |  |
462 | 106 |
             Object o = hVars.get(mainKey);
463 | 106 |
             if (o != null && o instanceof Var) {
464 | 64 |
                 Var v = (Var) o;
465 | 64 |
                 value = v.getValue();
466 |  |
             }
467 |  |
468 | 106 |
             return value;
469 |  |
         }
470 |  |
471 |  |
         /**
472 |  |
          * The <code>Field</code>'s variables are returned as an
473 |  |
          * unmodifiable <code>Map</code>.
474 |  |
          * @return the Map of Variable's for a Field.
475 |  |
          */
476 |  |
         public Map getVars() {
477 | 0 |
             return Collections.unmodifiableMap(hVars);
478 |  |
         }
479 |  |
480 |  |
         /**
481 |  |
          * Gets a unique key based on the property and indexedProperty fields.
482 |  |
          * @return a unique key for the field.
483 |  |
          */
484 |  |
         public String getKey() {
485 | 1107 |
             if (this.key == null) {
486 | 513 |
                 this.generateKey();
487 |  |
             }
488 |  |
489 | 1107 |
             return this.key;
490 |  |
         }
491 |  |
492 |  |
         /**
493 |  |
          * Sets a unique key for the field.  This can be used to change
494 |  |
          * the key temporarily to have a unique key for an indexed field.
495 |  |
          * @param key a unique key for the field
496 |  |
          */
497 |  |
         public void setKey(String key) {
498 | 0 |
             this.key = key;
499 | 0 |
         }
500 |  |
501 |  |
         /**
502 |  |
          * If there is a value specified for the indexedProperty field then
503 |  |
          * <code>true</code> will be returned.  Otherwise it will be
504 |  |
          * <code>false</code>.
505 |  |
          * @return Whether the Field is indexed.
506 |  |
          */
507 |  |
         public boolean isIndexed() {
508 | 1365 |
             return ((indexedListProperty != null && indexedListProperty.length() > 0));
509 |  |
         }
510 |  |
511 |  |
         /**
512 |  |
          * Generate correct <code>key</code> value.
513 |  |
          */
514 |  |
         public void generateKey() {
515 | 1026 |
             if (this.isIndexed()) {
516 | 0 |
                 this.key = class="keyword">this.indexedListProperty + TOKEN_INDEXED + "." + this.property;
517 |  |
             } else {
518 | 1026 |
                 this.key = class="keyword">this.property;
519 |  |
             }
520 | 1026 |
         }
521 |  |
522 |  |
         /**
523 |  |
          * Replace constants with values in fields and process the depends field
524 |  |
          * to create the dependency <code>Map</code>.
525 |  |
          */
526 |  |
         void process(Map globalConstants, Map constants) {
527 | 513 |
             this.hMsgs.setFast(false);
528 | 513 |
             this.hVars.setFast(true);
529 |  |
530 | 513 |
             this.generateKey();
531 |  |
532 |  |
             // Process FormSet Constants
533 | 1086 |
             for (Iterator i = constants.keySet().iterator(); i.hasNext();) {
534 | 60 |
                 String key = (String) i.next();
535 | 60 |
                 String key2 = TOKEN_START + key + TOKEN_END;
536 | 60 |
                 String replaceValue = (String) constants.get(key);
537 |  |
538 | 60 |
                 property = ValidatorUtils.replace(property, key2, replaceValue);
539 |  |
540 | 60 |
                 processVars(key2, replaceValue);
541 |  |
542 | 60 |
                 this.processMessageComponents(key2, replaceValue);
543 |  |
             }
544 |  |
545 |  |
             // Process Global Constants
546 | 1026 |
             for (Iterator i = globalConstants.keySet().iterator(); i.hasNext();) {
547 | 0 |
                 String key = (String) i.next();
548 | 0 |
                 String key2 = TOKEN_START + key + TOKEN_END;
549 | 0 |
                 String replaceValue = (String) globalConstants.get(key);
550 |  |
551 | 0 |
                 property = ValidatorUtils.replace(property, key2, replaceValue);
552 |  |
553 | 0 |
                 processVars(key2, replaceValue);
554 |  |
555 | 0 |
                 this.processMessageComponents(key2, replaceValue);
556 |  |
             }
557 |  |
558 |  |
             // Process Var Constant Replacement
559 | 1151 |
             for (Iterator i = hVars.keySet().iterator(); i.hasNext();) {
560 | 125 |
                 String key = (String) i.next();
561 | 125 |
                 String key2 = TOKEN_START + TOKEN_VAR + key + TOKEN_END;
562 | 125 |
                 Var var = this.getVar(key);
563 | 125 |
                 String replaceValue = var.getValue();
564 |  |
565 | 125 |
                 this.processMessageComponents(key2, replaceValue);
566 |  |
             }
567 |  |
568 | 513 |
             hMsgs.setFast(true);
569 | 513 |
         }
570 |  |
571 |  |
         /**
572 |  |
          * Replace the vars value with the key/value pairs passed in.
573 |  |
          */
574 |  |
         private void processVars(String key, String replaceValue) {
575 | 60 |
             Iterator i = this.hVars.keySet().iterator();
576 | 200 |
             while (i.hasNext()) {
577 | 80 |
                 String varKey = (String) i.next();
578 | 80 |
                 Var var = this.getVar(class="keyword">varKey);
579 |  |
580 | 80 |
                 var.setValue(ValidatorUtils.replace(class="keyword">var.getValue(), key, replaceValue));
581 |  |
             }
582 |  |
583 | 60 |
         }
584 |  |
585 |  |
         /**
586 |  |
          * Replace the args key value with the key/value pairs passed in.
587 |  |
          */
588 |  |
         private void processMessageComponents(String key, String replaceValue) {
589 | 185 |
             String varKey = TOKEN_START + TOKEN_VAR;
590 |  |
             // Process Messages
591 | 185 |
             if (key != null && !key.startsWith(varKey)) {
592 | 120 |
                 for (Iterator i = hMsgs.values().iterator(); i.hasNext();) {
593 | 0 |
                     Msg msg = (Msg) i.next();
594 | 0 |
                     msg.setKey(ValidatorUtils.replace(msg.getKey(), key, replaceValue));
595 |  |
                 }
596 |  |
             }
597 |  |
598 | 185 |
             this.processArg(key, replaceValue);
599 | 185 |
         }
600 |  |
601 |  |
         /**
602 |  |
          * Replace the arg <code>Collection</code> key value with the key/value
603 |  |
          * pairs passed in.
604 |  |
          */
605 |  |
         private void processArg(String key, String replaceValue) {
606 | 225 |
             for (int i = 0; i < this.args.length; i++) {
607 |  |
608 | 40 |
                 Map argMap = this.args[i];
609 | 40 |
                 if (argMap == null) {
610 | 0 |
                     continue;
611 |  |
                 }
612 |  |
613 | 40 |
                 Iterator iter = argMap.values().iterator();
614 | 120 |
                 while (iter.hasNext()) {
615 | 40 |
                     Arg arg = (Arg) iter.next();
616 |  |
617 | 40 |
                     if (arg != null) {
618 | 40 |
                         arg.setKey(
619 |  |
                                 ValidatorUtils.replace(arg.getKey(), key, replaceValue));
620 |  |
                     }
621 |  |
                 }
622 |  |
             }
623 | 185 |
         }
624 |  |
625 |  |
         /**
626 |  |
          * Checks if the validator is listed as a dependency.
627 |  |
          * @param validatorName Name of the validator to check.
628 |  |
          * @return Whether the field is dependant on a validator.
629 |  |
          */
630 |  |
         public boolean isDependency(String validatorName) {
631 | 0 |
             return this.dependencyList.contains(validatorName);
632 |  |
         }
633 |  |
634 |  |
         /**
635 |  |
          * Gets an unmodifiable <code>List</code> of the dependencies in the same
636 |  |
          * order they were defined in parameter passed to the setDepends() method.
637 |  |
          * @return A list of the Field's dependancies.
638 |  |
          */
639 |  |
         public List getDependencyList() {
640 | 0 |
             return Collections.unmodifiableList(this.dependencyList);
641 |  |
         }
642 |  |
643 |  |
         /**
644 |  |
          * Creates and returns a copy of this object.
645 |  |
          * @return A copy of the Field.
646 |  |
          */
647 |  |
         public Object clone() {
648 | 0 |
             Field field = null;
649 |  |
             try {
650 | 0 |
                 field = (Field) super.clone();
651 | 0 |
             } catch(CloneNotSupportedException e) {
652 | 0 |
                 throw new RuntimeException(e.toString());
653 |  |
             }
654 |  |
655 | 0 |
             field.args = new Map[this.args.length];
656 | 0 |
             for (int i = 0; i < this.args.length; i++) {
657 | 0 |
                 if (this.args[i] == null) {
658 | 0 |
                     continue;
659 |  |
                 }
660 |  |
661 | 0 |
                 Map argMap = new HashMap(this.args[i]);
662 | 0 |
                 Iterator iter = argMap.keySet().iterator();
663 | 0 |
                 while (iter.hasNext()) {
664 | 0 |
                     String validatorName = (String) iter.next();
665 | 0 |
                     Arg arg = (Arg) argMap.get(validatorName);
666 | 0 |
                     argMap.put(validatorName, arg.clone());
667 |  |
                 }
668 | 0 |
                 field.args[i] = argMap;
669 |  |
             }
670 |  |
671 | 0 |
             field.hVars = ValidatorUtils.copyFastHashMap(hVars);
672 | 0 |
             field.hMsgs = ValidatorUtils.copyFastHashMap(hMsgs);
673 |  |
674 | 0 |
             return field;
675 |  |
         }
676 |  |
677 |  |
         /**
678 |  |
          * Returns a string representation of the object.
679 |  |
          * @return A string representation of the object.
680 |  |
          */
681 |  |
         public String toString() {
682 | 0 |
             StringBuffer results = new StringBuffer();
683 |  |
684 | 0 |
             results.append("\t\tkey = " + key + "\n");
685 | 0 |
             results.append("\t\tproperty = " + property + "\n");
686 | 0 |
             results.append("\t\tindexedProperty = " + indexedProperty + "\n");
687 | 0 |
             results.append("\t\tindexedListProperty = " + indexedListProperty + "\n");
688 | 0 |
             results.append("\t\tdepends = " + depends + "\n");
689 | 0 |
             results.append("\t\tpage = " + page + "\n");
690 | 0 |
             results.append("\t\tfieldOrder = " + fieldOrder + "\n");
691 |  |
692 | 0 |
             if (hVars != null) {
693 | 0 |
                 results.append("\t\tVars:\n");
694 | 0 |
                 for (Iterator i = hVars.keySet().iterator(); i.hasNext();) {
695 | 0 |
                     Object key = i.next();
696 | 0 |
                     results.append("\t\t\t");
697 | 0 |
                     results.append(key);
698 | 0 |
                     results.append("=");
699 | 0 |
                     results.append(hVars.get(key));
700 | 0 |
                     results.append("\n");
701 |  |
                 }
702 |  |
             }
703 |  |
704 | 0 |
             return results.toString();
705 |  |
         }
706 |  |
707 |  |
         /**
708 |  |
          * Returns an indexed property from the object we're validating.
709 |  |
          *
710 |  |
          * @param bean The bean to extract the indexed values from.
711 |  |
          * @throws ValidatorException If there's an error looking up the property
712 |  |
          * or, the property found is not indexed.
713 |  |
          */
714 |  |
         Object[] getIndexedProperty(Object bean) throws ValidatorException {
715 | 0 |
             Object indexedProperty = null;
716 |  |
717 |  |
             try {
718 | 0 |
                 indexedProperty =
719 |  |
                     PropertyUtils.getProperty(bean, this.getIndexedListProperty());
720 |  |
721 | 0 |
             } catch(IllegalAccessException e) {
722 | 0 |
                 throw new ValidatorException(e.getMessage());
723 |  |
             } catch(InvocationTargetException e) {
724 | 0 |
                 throw new ValidatorException(e.getMessage());
725 |  |
             } catch(NoSuchMethodException e) {
726 | 0 |
                 throw new ValidatorException(e.getMessage());
727 |  |
             }
728 |  |
729 | 0 |
             if (indexedProperty instanceof Collection) {
730 | 0 |
                 return ((Collection) indexedProperty).toArray();
731 |  |
732 | 0 |
             } else if (indexedProperty.getClass().isArray()) {
733 | 0 |
                 return (Object[]) indexedProperty;
734 |  |
735 |  |
             } else {
736 | 0 |
                 throw new ValidatorException(this.getKey() + " is not indexed");
737 |  |
             }
738 |  |
739 |  |
         }
740 |  |
         /**
741 |  |
          * Returns the size of an indexed property from the object we're validating.
742 |  |
          *
743 |  |
          * @param bean The bean to extract the indexed values from.
744 |  |
          * @throws ValidatorException If there's an error looking up the property
745 |  |
          * or, the property found is not indexed.
746 |  |
          */
747 |  |
         private int getIndexedPropertySize(Object bean) throws ValidatorException {
748 | 0 |
             Object indexedProperty = null;
749 |  |
750 |  |
             try {
751 | 0 |
                 indexedProperty =
752 |  |
                     PropertyUtils.getProperty(bean, this.getIndexedListProperty());
753 |  |
754 | 0 |
             } catch(IllegalAccessException e) {
755 | 0 |
                 throw new ValidatorException(e.getMessage());
756 |  |
             } catch(InvocationTargetException e) {
757 | 0 |
                 throw new ValidatorException(e.getMessage());
758 |  |
             } catch(NoSuchMethodException e) {
759 | 0 |
                 throw new ValidatorException(e.getMessage());
760 |  |
             }
761 |  |
762 | 0 |
             if (indexedProperty == null) {
763 | 0 |
                 return 0;
764 | 0 |
             } else if (indexedProperty instanceof Collection) {
765 | 0 |
                 return ((Collection)indexedProperty).size();
766 | 0 |
             } else if (indexedProperty.getClass().isArray()) {
767 | 0 |
                 return ((Object[])indexedProperty).length;
768 |  |
             } else {
769 | 0 |
                 throw new ValidatorException(this.getKey() + " is not indexed");
770 |  |
             }
771 |  |
772 |  |
         }
773 |  |
774 |  |
         /**
775 |  |
          * Executes the given ValidatorAction and all ValidatorActions that it
776 |  |
          * depends on.
777 |  |
          * @return true if the validation succeeded.
778 |  |
          */
779 |  |
         private boolean validateForRule(
780 |  |
             ValidatorAction va,
781 |  |
             ValidatorResults results,
782 |  |
             Map actions,
783 |  |
             Map params,
784 |  |
             int pos)
785 |  |
             throws ValidatorException {
786 |  |
787 | 167 |
             ValidatorResult result = results.getValidatorResult(this.getKey());
788 | 167 |
             if (result != null && result.containsAction(va.getName())) {
789 | 0 |
                 return result.isValid(va.getName());
790 |  |
             }
791 |  |
792 | 167 |
             if (!this.runDependentValidators(va, results, actions, params, pos)) {
793 | 1 |
                 return false;
794 |  |
             }
795 |  |
796 | 166 |
             return va.executeValidationMethod(this, params, results, pos);
797 |  |
         }
798 |  |
799 |  |
         /**
800 |  |
          * Calls all of the validators that this validator depends on.
801 |  |
          * TODO ValidatorAction should know how to run its own dependencies.
802 |  |
          * @param va Run dependent validators for this action.
803 |  |
          * @param results
804 |  |
          * @param actions
805 |  |
          * @param pos
806 |  |
          * @return true if all of the dependent validations passed.
807 |  |
          * @throws ValidatorException If there's an error running a validator
808 |  |
          */
809 |  |
         private boolean runDependentValidators(
810 |  |
             ValidatorAction va,
811 |  |
             ValidatorResults results,
812 |  |
             Map actions,
813 |  |
             Map params,
814 |  |
             int pos)
815 |  |
             throws ValidatorException {
816 |  |
817 | 167 |
             List dependentValidators = va.getDependencyList();
818 |  |
819 | 167 |
             if (dependentValidators.isEmpty()) {
820 | 165 |
                 return true;
821 |  |
             }
822 |  |
823 | 2 |
             Iterator iter = dependentValidators.iterator();
824 | 5 |
             while (iter.hasNext()) {
825 | 2 |
                 String depend = (String) iter.next();
826 |  |
827 | 2 |
                 ValidatorAction action = (ValidatorAction) actions.get(depend);
828 | 2 |
                 if (action == null) {
829 | 0 |
                     this.handleMissingAction(depend);
830 |  |
                 }
831 |  |
832 | 2 |
                 if (!this.validateForRule(action, results, actions, params, pos)) {
833 | 1 |
                     return false;
834 |  |
                 }
835 |  |
             }
836 |  |
837 | 1 |
             return true;
838 |  |
         }
839 |  |
840 |  |
         /**
841 |  |
          * Run the configured validations on this field.  Run all validations
842 |  |
          * in the depends clause over each item in turn, returning when the first
843 |  |
          * one fails.
844 |  |
          * @param params A Map of parameter class names to parameter values to pass
845 |  |
          * into validation methods.
846 |  |
          * @param actions A Map of validator names to ValidatorAction objects.
847 |  |
          * @return A ValidatorResults object containing validation messages for
848 |  |
          * this field.
849 |  |
          * @throws ValidatorException If an error occurs during validation.
850 |  |
          */
851 |  |
         public ValidatorResults validate(Map params, Map actions)
852 |  |
             throws ValidatorException {
853 |  |
854 | 163 |
             if (this.getDepends() == null) {
855 | 0 |
                 return new ValidatorResults();
856 |  |
             }
857 |  |
858 | 163 |
             ValidatorResults allResults = new ValidatorResults();
859 |  |
860 | 163 |
             Object bean = params.get(Validator.BEAN_PARAM);
861 | 163 |
             int numberOfFieldsToValidate =
862 |  |
                 this.isIndexed() ? class="keyword">this.getIndexedPropertySize(bean) : 1;
863 |  |
864 | 251 |
             for (int fieldNumber = 0; fieldNumber < numberOfFieldsToValidate; fieldNumber++) {
865 |  |
866 | 163 |
                 Iterator dependencies = this.dependencyList.iterator();
867 | 163 |
                 ValidatorResults results = new ValidatorResults();
868 | 416 |
                 while (dependencies.hasNext()) {
869 | 165 |
                     String depend = (String) dependencies.next();
870 |  |
871 | 165 |
                     ValidatorAction action = (ValidatorAction) actions.get(depend);
872 | 165 |
                     if (action == null) {
873 | 0 |
                         this.handleMissingAction(depend);
874 |  |
                     }
875 |  |
876 | 165 |
                     boolean good =
877 |  |
                         validateForRule(action, results, actions, params, fieldNumber);
878 |  |
879 | 164 |
                     if (!good) {
880 | 74 |
                         allResults.merge(results);
881 | 74 |
                         return allResults;
882 |  |
                     }
883 |  |
                 }
884 | 88 |
                 allResults.merge(results);
885 |  |
             }
886 |  |
887 | 88 |
             return allResults;
888 |  |
         }
889 |  |
890 |  |
         /**
891 |  |
          * Called when a validator name is used in a depends clause but there is
892 |  |
          * no know ValidatorAction configured for that name.
893 |  |
          * @param name The name of the validator in the depends list.
894 |  |
          * @throws ValidatorException
895 |  |
          */
896 |  |
         private void handleMissingAction(String name) throws ValidatorException {
897 | 0 |
             throw new ValidatorException("No ValidatorAction named " + name
898 |  |
                     + " found for field " + this.getProperty());
899 |  |
         }
900 |  |
901 |  |
         /**
902 |  |
          * Returns a Map of String Msg names to Msg objects.
903 |  |
          * @since Validator 1.2.0
904 |  |
          * @return A Map of the Field's messages.
905 |  |
          */
906 |  |
         protected Map getMsgMap() {
907 | 0 |
             return hMsgs;
908 |  |
         }
909 |  |
910 |  |
         /**
911 |  |
          * Returns a Map of String Var names to Var objects.
912 |  |
          * @since Validator 1.2.0
913 |  |
          * @return A Map of the Field's variables.
914 |  |
          */
915 |  |
         protected Map getVarMap() {
916 | 0 |
             return hVars;
917 |  |
         }
918 |  |
919 |  |
     }
920 |  |

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.