1 /*
2 * $Header: /home/cvs/jakarta-commons/validator/src/share/org/apache/commons/validator/Field.java,v 1.31.2.1 2004/06/22 02:24:38 husted Exp $
3 * $Revision: 1.31.2.1 $
4 * $Date: 2004/06/22 02:24:38 $
5 *
6 * ====================================================================
7 * Copyright 2001-2004 The Apache Software Foundation
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
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; // DEPRECATED
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.getKey());
243 }
244
245 /***
246 * Retrieve a message value.
247 */
248 public String getMsg(String key) {
249 return (String) hMsgs.get(key);
250 }
251
252 /***
253 * Add an <code>Arg</code> to the replacement argument list.
254 * @since Validator 1.1
255 */
256 public void addArg(Arg arg) {
257 // TODO this first if check can go away after arg0, etc. are removed from dtd
258 if (arg == null || arg.getKey() == null || arg.getKey().length() == 0) {
259 return;
260 }
261
262 this.ensureArgsCapacity(arg);
263
264 Map argMap = this.args[arg.getPosition()];
265 if (argMap == null) {
266 argMap = new HashMap();
267 this.args[arg.getPosition()] = argMap;
268 }
269
270 if (arg.getName() == null) {
271 argMap.put(DEFAULT_ARG, arg);
272 } else {
273 argMap.put(arg.getName(), arg);
274 }
275
276 }
277
278 /***
279 * Ensures that the args array can hold the given arg. Resizes the array as
280 * necessary.
281 * @param arg Determine if the args array is long enough to store this arg's
282 * position.
283 */
284 private void ensureArgsCapacity(Arg arg) {
285 if (arg.getPosition() >= this.args.length) {
286 Map[] newArgs = new Map[arg.getPosition() + 1];
287 System.arraycopy(this.args, 0, newArgs, 0, this.args.length);
288 this.args = newArgs;
289 }
290 }
291
292 /***
293 * Gets the default <code>Arg</code> object at the given position.
294 * @return The default Arg or null if not found.
295 * @since Validator 1.1
296 */
297 public Arg getArg(int position) {
298 return this.getArg(DEFAULT_ARG, position);
299 }
300
301 /***
302 * Gets the <code>Arg</code> object at the given position. If the key
303 * finds a <code>null</code> value then the default value will be
304 * retrieved.
305 * @param key The name the Arg is stored under. If not found, the default
306 * Arg for the given position (if any) will be retrieved.
307 * @param position The Arg number to find.
308 * @return The Arg with the given name and position or null if not found.
309 * @since Validator 1.1
310 */
311 public Arg getArg(String key, int position) {
312 if ((position >= this.args.length) || (this.args[position] == null)) {
313 return null;
314 }
315
316 Arg arg = (Arg) args[position].get(key);
317
318 // Didn't find default arg so exit, otherwise we would get into
319 // infinite recursion
320 if ((arg == null) && key.equals(DEFAULT_ARG)) {
321 return null;
322 }
323
324 return (arg == null) ? this.getArg(position) : arg;
325 }
326
327 /***
328 * Retrieves the Args for the given validator name.
329 * @param key The validator's args to retrieve.
330 * @return An Arg[] sorted by the Args' positions (i.e. the Arg at index 0
331 * has a position of 0).
332 * @since Validator 1.1.1
333 */
334 public Arg[] getArgs(String key){
335 Arg[] args = new Arg[this.args.length];
336
337 for (int i = 0; i < this.args.length; i++) {
338 args[i] = this.getArg(key, i);
339 }
340
341 return args;
342 }
343
344 /***
345 * Add a <code>Arg</code> to the arg0 list.
346 * @deprecated Use addArg(Arg) instead.
347 */
348 public void addArg0(Arg arg) {
349 arg.setPosition(0);
350 this.addArg(arg);
351 }
352
353 /***
354 * Gets the default arg0 <code>Arg</code> object.
355 * @deprecated Use getArg(0) instead.
356 */
357 public Arg getArg0() {
358 return this.getArg(0);
359 }
360
361 /***
362 * Gets the arg0 <code>Arg</code> object based on the key passed in. If
363 * the key finds a <code>null</code> value then the default value will
364 * be retrieved.
365 * @deprecated Use getArg(String, 0) instead.
366 */
367 public Arg getArg0(String key) {
368 return this.getArg(key, 0);
369 }
370
371 /***
372 * Add a <code>Arg</code> to the arg1 list.
373 * @deprecated Use addArg(Arg) instead.
374 */
375 public void addArg1(Arg arg) {
376 arg.setPosition(1);
377 this.addArg(arg);
378 }
379
380 /***
381 * Gets the default arg1 <code>Arg</code> object.
382 * @deprecated Use getArg(1) instead.
383 */
384 public Arg getArg1() {
385 return this.getArg(1);
386 }
387
388 /***
389 * Gets the arg1 <code>Arg</code> object based on the key passed in. If the key
390 * finds a <code>null</code> value then the default value will try to be retrieved.
391 * @deprecated Use getArg(String, 1) instead.
392 */
393 public Arg getArg1(String key) {
394 return this.getArg(key, 1);
395 }
396
397 /***
398 * Add a <code>Arg</code> to the arg2 list.
399 * @deprecated Use addArg(Arg) instead.
400 */
401 public void addArg2(Arg arg) {
402 arg.setPosition(2);
403 this.addArg(arg);
404 }
405
406 /***
407 * Gets the default arg2 <code>Arg</code> object.
408 * @deprecated Use getArg(2) instead.
409 */
410 public Arg getArg2() {
411 return this.getArg(2);
412 }
413
414 /***
415 * Gets the arg2 <code>Arg</code> object based on the key passed in. If the key
416 * finds a <code>null</code> value then the default value will try to be retrieved.
417 * @deprecated Use getArg(String, 2) instead.
418 */
419 public Arg getArg2(String key) {
420 return this.getArg(key, 2);
421 }
422
423 /***
424 * Add a <code>Arg</code> to the arg3 list.
425 * @deprecated Use addArg(Arg) instead.
426 */
427 public void addArg3(Arg arg) {
428 arg.setPosition(3);
429 this.addArg(arg);
430 }
431
432 /***
433 * Gets the default arg3 <code>Arg</code> object.
434 * @deprecated Use getArg(3) instead.
435 */
436 public Arg getArg3() {
437 return this.getArg(3);
438 }
439
440 /***
441 * Gets the arg3 <code>Arg</code> object based on the key passed in. If the key
442 * finds a <code>null</code> value then the default value will try to be retrieved.
443 * @deprecated Use getArg(String, 3) instead.
444 */
445 public Arg getArg3(String key) {
446 return this.getArg(key, 3);
447 }
448
449 /***
450 * Add a <code>Var</code> to the <code>Field</code>.
451 */
452 public void addVar(Var v) {
453 this.hVars.put(v.getName(), v);
454 }
455
456 /***
457 * Add a <code>Var</code>, based on the values passed in, to the
458 * <code>Field</code>.
459 * @deprecated Use addVar(String, String, String) instead.
460 */
461 public void addVarParam(String name, String value, String jsType) {
462 this.addVar(new Var(name, value, jsType));
463 }
464
465 /***
466 * Add a <code>Var</code>, based on the values passed in, to the
467 * <code>Field</code>.
468 * @param name
469 * @param value
470 * @param jsType
471 */
472 public void addVar(String name, String value, String jsType) {
473 this.addVar(new Var(name, value, jsType));
474 }
475
476 /***
477 * Retrieve a variable.
478 * @param mainKey
479 */
480 public Var getVar(String mainKey) {
481 return (Var) hVars.get(mainKey);
482 }
483
484 /***
485 * Retrieve a variable's value.
486 * @param mainKey
487 */
488 public String getVarValue(String mainKey) {
489 String value = null;
490
491 Object o = hVars.get(mainKey);
492 if (o != null && o instanceof Var) {
493 Var v = (Var) o;
494 value = v.getValue();
495 }
496
497 return value;
498 }
499
500 /***
501 * The <code>Field</code>'s variables are returned as an
502 * unmodifiable <code>Map</code>.
503 */
504 public Map getVars() {
505 return Collections.unmodifiableMap(hVars);
506 }
507
508 /***
509 * Gets a unique key based on the property and indexedProperty fields.
510 */
511 public String getKey() {
512 if (this.key == null) {
513 this.generateKey();
514 }
515
516 return this.key;
517 }
518
519 /***
520 * Sets a unique key for the field. This can be used to change
521 * the key temporarily to have a unique key for an indexed field.
522 * @param key
523 */
524 public void setKey(String key) {
525 this.key = key;
526 }
527
528 /***
529 * If there is a value specified for the indexedProperty field then
530 * <code>true</code> will be returned. Otherwise it will be
531 * <code>false</code>.
532 */
533 public boolean isIndexed() {
534 return ((indexedListProperty != null && indexedListProperty.length() > 0));
535 }
536
537 /***
538 * Generate correct <code>key</code> value.
539 */
540 public void generateKey() {
541 if (this.isIndexed()) {
542 this.key = this.indexedListProperty + TOKEN_INDEXED + "." + this.property;
543 } else {
544 this.key = this.property;
545 }
546 }
547
548 /***
549 * Replace constants with values in fields and process the depends field
550 * to create the dependency <code>Map</code>.
551 * @deprecated This method is called by the framework. It will be made protected
552 * in a future release. TODO
553 */
554 public void process(Map globalConstants, Map constants) {
555 this.hMsgs.setFast(false);
556 this.hVars.setFast(true);
557
558 this.generateKey();
559
560 // Process FormSet Constants
561 for (Iterator i = constants.keySet().iterator(); i.hasNext();) {
562 String key = (String) i.next();
563 String key2 = TOKEN_START + key + TOKEN_END;
564 String replaceValue = (String) constants.get(key);
565
566 property = ValidatorUtils.replace(property, key2, replaceValue);
567
568 processVars(key2, replaceValue);
569
570 this.processMessageComponents(key2, replaceValue);
571 }
572
573 // Process Global Constants
574 for (Iterator i = globalConstants.keySet().iterator(); i.hasNext();) {
575 String key = (String) i.next();
576 String key2 = TOKEN_START + key + TOKEN_END;
577 String replaceValue = (String) globalConstants.get(key);
578
579 property = ValidatorUtils.replace(property, key2, replaceValue);
580
581 processVars(key2, replaceValue);
582
583 this.processMessageComponents(key2, replaceValue);
584 }
585
586 // Process Var Constant Replacement
587 for (Iterator i = hVars.keySet().iterator(); i.hasNext();) {
588 String key = (String) i.next();
589 String key2 = TOKEN_START + TOKEN_VAR + key + TOKEN_END;
590 Var var = this.getVar(key);
591 String replaceValue = var.getValue();
592
593 this.processMessageComponents(key2, replaceValue);
594 }
595
596 hMsgs.setFast(true);
597 }
598
599 /***
600 * Replace the vars value with the key/value pairs passed in.
601 */
602 private void processVars(String key, String replaceValue) {
603 Iterator i = this.hVars.keySet().iterator();
604 while (i.hasNext()) {
605 String varKey = (String) i.next();
606 Var var = this.getVar(varKey);
607
608 var.setValue(ValidatorUtils.replace(var.getValue(), key, replaceValue));
609 }
610
611 }
612
613 /***
614 * Replace the args key value with the key/value pairs passed in.
615 * @deprecated This is an internal setup method that clients don't need to call.
616 */
617 public void processMessageComponents(String key, String replaceValue) {
618 this.internalProcessMessageComponents(key, replaceValue);
619 }
620
621 /***
622 * Replace the args key value with the key/value pairs passed in.
623 * TODO When processMessageComponents() is removed from the public API we
624 * should rename this private method to "processMessageComponents".
625 */
626 private void internalProcessMessageComponents(String key, String replaceValue) {
627 String varKey = TOKEN_START + TOKEN_VAR;
628 // Process Messages
629 if (key != null && !key.startsWith(varKey)) {
630 for (Iterator i = hMsgs.keySet().iterator(); i.hasNext();) {
631 String msgKey = (String) i.next();
632 String value = this.getMsg(msgKey);
633
634 hMsgs.put(msgKey, ValidatorUtils.replace(value, key, replaceValue));
635 }
636 }
637
638 this.processArg(key, replaceValue);
639 }
640
641 /***
642 * Replace the arg <code>Collection</code> key value with the key/value
643 * pairs passed in.
644 */
645 private void processArg(String key, String replaceValue) {
646 for (int i = 0; i < this.args.length; i++) {
647
648 Map argMap = this.args[i];
649 if (argMap == null) {
650 continue;
651 }
652
653 Iterator iter = argMap.values().iterator();
654 while (iter.hasNext()) {
655 Arg arg = (Arg) iter.next();
656
657 if (arg != null) {
658 arg.setKey(
659 ValidatorUtils.replace(arg.getKey(), key, replaceValue));
660 }
661 }
662 }
663 }
664
665 /***
666 * Checks if the validator is listed as a dependency.
667 */
668 public boolean isDependency(String validatorName) {
669 return this.dependencyList.contains(validatorName);
670 }
671
672 /***
673 * Gets an unmodifiable <code>Set</code> of the dependencies.
674 * @deprecated Use getDependencyList() instead.
675 */
676 public Collection getDependencies() {
677 return this.getDependencyList();
678 }
679
680 /***
681 * Gets an unmodifiable <code>List</code> of the dependencies in the same
682 * order they were defined in parameter passed to the setDepends() method.
683 */
684 public List getDependencyList() {
685 return Collections.unmodifiableList(this.dependencyList);
686 }
687
688
689 /***
690 * Creates and returns a copy of this object.
691 */
692 public Object clone() {
693 Field field = null;
694 try {
695 field = (Field) super.clone();
696 } catch(CloneNotSupportedException e) {
697 throw new RuntimeException(e.toString());
698 }
699
700 field.args = new Map[this.args.length];
701 for (int i = 0; i < this.args.length; i++) {
702 if (this.args[i] == null) {
703 continue;
704 }
705
706 Map argMap = new HashMap(this.args[i]);
707 Iterator iter = argMap.keySet().iterator();
708 while (iter.hasNext()) {
709 String validatorName = (String) iter.next();
710 Arg arg = (Arg) argMap.get(validatorName);
711 argMap.put(validatorName, arg.clone());
712 }
713 field.args[i] = argMap;
714 }
715
716 field.hVars = ValidatorUtils.copyFastHashMap(hVars);
717 field.hMsgs = ValidatorUtils.copyFastHashMap(hMsgs);
718 field.hArg0 = ValidatorUtils.copyFastHashMap(hArg0);
719 field.hArg1 = ValidatorUtils.copyFastHashMap(hArg1);
720 field.hArg2 = ValidatorUtils.copyFastHashMap(hArg2);
721 field.hArg3 = ValidatorUtils.copyFastHashMap(hArg3);
722
723 return field;
724 }
725
726 /***
727 * Returns a string representation of the object.
728 */
729 public String toString() {
730 StringBuffer results = new StringBuffer();
731
732 results.append("\t\tkey = " + key + "\n");
733 results.append("\t\tproperty = " + property + "\n");
734 results.append("\t\tindexedProperty = " + indexedProperty + "\n");
735 results.append("\t\tindexedListProperty = " + indexedListProperty + "\n");
736 results.append("\t\tdepends = " + depends + "\n");
737 results.append("\t\tpage = " + page + "\n");
738 results.append("\t\tfieldOrder = " + fieldOrder + "\n");
739
740 if (hVars != null) {
741 results.append("\t\tVars:\n");
742 for (Iterator i = hVars.keySet().iterator(); i.hasNext();) {
743 Object key = i.next();
744 results.append("\t\t\t");
745 results.append(key);
746 results.append("=");
747 results.append(hVars.get(key));
748 results.append("\n");
749 }
750 }
751
752 return results.toString();
753 }
754
755 /***
756 * Returns an indexed property from the object we're validating.
757 *
758 * @param bean The bean to extract the indexed values from.
759 * @throws ValidatorException If there's an error looking up the property
760 * or, the property found is not indexed.
761 */
762 Object[] getIndexedProperty(Object bean) throws ValidatorException {
763 Object indexedProperty = null;
764
765 try {
766 indexedProperty =
767 PropertyUtils.getProperty(bean, this.getIndexedListProperty());
768
769 } catch(IllegalAccessException e) {
770 throw new ValidatorException(e.getMessage());
771 } catch(InvocationTargetException e) {
772 throw new ValidatorException(e.getMessage());
773 } catch(NoSuchMethodException e) {
774 throw new ValidatorException(e.getMessage());
775 }
776
777 if (indexedProperty instanceof Collection) {
778 return ((Collection) indexedProperty).toArray();
779
780 } else if (indexedProperty.getClass().isArray()) {
781 return (Object[]) indexedProperty;
782
783 } else {
784 throw new ValidatorException(this.getKey() + " is not indexed");
785 }
786
787 }
788
789 /***
790 * Executes the given ValidatorAction and all ValidatorActions that it
791 * depends on.
792 * @return true if the validation succeeded.
793 */
794 private boolean validateForRule(
795 ValidatorAction va,
796 ValidatorResults results,
797 Map actions,
798 Map params,
799 int pos)
800 throws ValidatorException {
801
802 ValidatorResult result = results.getValidatorResult(this.getKey());
803 if (result != null && result.containsAction(va.getName())) {
804 return result.isValid(va.getName());
805 }
806
807 if (!this.runDependentValidators(va, results, actions, params, pos)) {
808 return false;
809 }
810
811 return va.executeValidationMethod(this, params, results, pos);
812 }
813
814 /***
815 * Calls all of the validators that this validator depends on.
816 * TODO ValidatorAction should know how to run its own dependencies.
817 * @param va Run dependent validators for this action.
818 * @param results
819 * @param actions
820 * @param pos
821 * @return true if all of the dependent validations passed.
822 * @throws ValidatorException
823 */
824 private boolean runDependentValidators(
825 ValidatorAction va,
826 ValidatorResults results,
827 Map actions,
828 Map params,
829 int pos)
830 throws ValidatorException {
831
832 List dependentValidators = va.getDependencyList();
833
834 if (dependentValidators.isEmpty()) {
835 return true;
836 }
837
838 Iterator iter = dependentValidators.iterator();
839 while (iter.hasNext()) {
840 String depend = (String) iter.next();
841
842 ValidatorAction action = (ValidatorAction) actions.get(depend);
843 if (action == null) {
844 this.handleMissingAction(depend);
845 }
846
847 if (!this.validateForRule(action, results, actions, params, pos)) {
848 return false;
849 }
850 }
851
852 return true;
853 }
854
855 /***
856 * Run the configured validations on this field. Run all validations
857 * in the depends clause over each item in turn, returning when the first
858 * one fails.
859 * @param params A Map of parameter class names to parameter values to pass
860 * into validation methods.
861 * @param actions A Map of validator names to ValidatorAction objects.
862 * @return A ValidatorResults object containing validation messages for
863 * this field.
864 */
865 ValidatorResults validate(Map params, Map actions)
866 throws ValidatorException {
867
868 if (this.getDepends() == null) {
869 return new ValidatorResults();
870 }
871
872 ValidatorResults allResults = new ValidatorResults();
873
874 Object bean = params.get(Validator.BEAN_PARAM);
875 int numberOfFieldsToValidate =
876 this.isIndexed() ? this.getIndexedProperty(bean).length : 1;
877
878 for (int fieldNumber = 0; fieldNumber < numberOfFieldsToValidate; fieldNumber++) {
879
880 Iterator dependencies = this.dependencyList.iterator();
881 while (dependencies.hasNext()) {
882 String depend = (String) dependencies.next();
883
884 ValidatorAction action = (ValidatorAction) actions.get(depend);
885 if (action == null) {
886 this.handleMissingAction(depend);
887 }
888
889 ValidatorResults results = new ValidatorResults();
890 boolean good =
891 validateForRule(action, results, actions, params, fieldNumber);
892
893 allResults.merge(results);
894
895 if (!good) {
896 return allResults;
897 }
898 }
899 }
900
901 return allResults;
902 }
903
904 /***
905 * Called when a validator name is used in a depends clause but there is
906 * no know ValidatorAction configured for that name.
907 * @param name The name of the validator in the depends list.
908 * @throws ValidatorException
909 */
910 private void handleMissingAction(String name) throws ValidatorException {
911 throw new ValidatorException(
912 "No ValidatorAction named "
913 + name
914 + " found for field "
915 + this.getProperty());
916 }
917
918 }
This page was automatically generated by Maven