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