1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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;
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 * <field> 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 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 protected String property = null;
80
81 /***
82 * The Field's indexed property name.
83 */
84 protected String indexedProperty = null;
85
86 /***
87 * The Field's indexed list property name.
88 */
89 protected String indexedListProperty = null;
90
91 /***
92 * The Field's unique key.
93 */
94 protected String key = null;
95
96 /***
97 * A comma separated list of validator's this field depends on.
98 */
99 protected String depends = null;
100
101 /***
102 * The Page Number
103 */
104 protected int page = 0;
105
106 /***
107 * The order of the Field in the Form.
108 */
109 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 private List dependencyList = Collections.synchronizedList(new ArrayList());
118
119 /***
120 * @deprecated Subclasses should use getVarMap() instead.
121 */
122 protected FastHashMap hVars = new FastHashMap();
123
124 /***
125 * @deprecated Subclasses should use getMsgMap() instead.
126 */
127 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 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 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 this.page = page;
153 }
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 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 this.fieldOrder = fieldOrder;
169 }
170
171 /***
172 * Gets the property name of the field.
173 * @return The field's property name.
174 */
175 public String getProperty() {
176 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 this.property = property;
185 }
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 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 this.indexedProperty = indexedProperty;
203 }
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 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 this.indexedListProperty = indexedListProperty;
223 }
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 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 this.depends = depends;
239
240 this.dependencyList.clear();
241
242 StringTokenizer st = new StringTokenizer(depends, ",");
243 while (st.hasMoreTokens()) {
244 String depend = st.nextToken().trim();
245
246 if (depend != null && depend.length() > 0) {
247 this.dependencyList.add(depend);
248 }
249 }
250 }
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 hMsgs.put(msg.getName(), msg);
258 }
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 Msg msg = getMessage(key);
267 return (msg == null) ? 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 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 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
297 if (arg == null || arg.getKey() == null || arg.getKey().length() == 0) {
298 return;
299 }
300
301 determineArgPosition(arg);
302 ensureArgsCapacity(arg);
303
304 Map argMap = this.args[arg.getPosition()];
305 if (argMap == null) {
306 argMap = new HashMap();
307 this.args[arg.getPosition()] = argMap;
308 }
309
310 if (arg.getName() == null) {
311 argMap.put(DEFAULT_ARG, arg);
312 } else {
313 argMap.put(arg.getName(), arg);
314 }
315
316 }
317
318 /***
319 * Calculate the position of the Arg
320 */
321 private void determineArgPosition(Arg arg) {
322
323 int position = arg.getPosition();
324
325
326 if (position >= 0) {
327 return;
328 }
329
330
331 if (args == null || args.length == 0) {
332 arg.setPosition(0);
333 return;
334 }
335
336
337
338 String key = arg.getName() == null ? DEFAULT_ARG : arg.getName();
339 int lastPosition = -1;
340 int lastDefault = -1;
341 for (int i = 0; i < args.length; i++) {
342 if (args[i] != null && args[i].containsKey(key)) {
343 lastPosition = i;
344 }
345 if (args[i] != null && args[i].containsKey(DEFAULT_ARG)) {
346 lastDefault = i;
347 }
348 }
349
350 if (lastPosition < 0) {
351 lastPosition = lastDefault;
352 }
353
354
355 arg.setPosition(++lastPosition);
356
357 }
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 if (arg.getPosition() >= this.args.length) {
367 Map[] newArgs = new Map[arg.getPosition() + 1];
368 System.arraycopy(this.args, 0, newArgs, 0, this.args.length);
369 this.args = newArgs;
370 }
371 }
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 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 if ((position >= this.args.length) || (this.args[position] == null)) {
395 return null;
396 }
397
398 Arg arg = (Arg) args[position].get(key);
399
400
401
402 if ((arg == null) && key.equals(DEFAULT_ARG)) {
403 return null;
404 }
405
406 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 Arg[] args = new Arg[this.args.length];
418
419 for (int i = 0; i < this.args.length; i++) {
420 args[i] = this.getArg(key, i);
421 }
422
423 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 this.hVars.put(v.getName(), v);
432 }
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 this.addVar(new Var(name, value, jsType));
443 }
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 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 String value = null;
461
462 Object o = hVars.get(mainKey);
463 if (o != null && o instanceof Var) {
464 Var v = (Var) o;
465 value = v.getValue();
466 }
467
468 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 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 if (this.key == null) {
486 this.generateKey();
487 }
488
489 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 this.key = key;
499 }
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 return ((indexedListProperty != null && indexedListProperty.length() > 0));
509 }
510
511 /***
512 * Generate correct <code>key</code> value.
513 */
514 public void generateKey() {
515 if (this.isIndexed()) {
516 this.key = this.indexedListProperty + TOKEN_INDEXED + "." + this.property;
517 } else {
518 this.key = this.property;
519 }
520 }
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 this.hMsgs.setFast(false);
528 this.hVars.setFast(true);
529
530 this.generateKey();
531
532
533 for (Iterator i = constants.keySet().iterator(); i.hasNext();) {
534 String key = (String) i.next();
535 String key2 = TOKEN_START + key + TOKEN_END;
536 String replaceValue = (String) constants.get(key);
537
538 property = ValidatorUtils.replace(property, key2, replaceValue);
539
540 processVars(key2, replaceValue);
541
542 this.processMessageComponents(key2, replaceValue);
543 }
544
545
546 for (Iterator i = globalConstants.keySet().iterator(); i.hasNext();) {
547 String key = (String) i.next();
548 String key2 = TOKEN_START + key + TOKEN_END;
549 String replaceValue = (String) globalConstants.get(key);
550
551 property = ValidatorUtils.replace(property, key2, replaceValue);
552
553 processVars(key2, replaceValue);
554
555 this.processMessageComponents(key2, replaceValue);
556 }
557
558
559 for (Iterator i = hVars.keySet().iterator(); i.hasNext();) {
560 String key = (String) i.next();
561 String key2 = TOKEN_START + TOKEN_VAR + key + TOKEN_END;
562 Var var = this.getVar(key);
563 String replaceValue = var.getValue();
564
565 this.processMessageComponents(key2, replaceValue);
566 }
567
568 hMsgs.setFast(true);
569 }
570
571 /***
572 * Replace the vars value with the key/value pairs passed in.
573 */
574 private void processVars(String key, String replaceValue) {
575 Iterator i = this.hVars.keySet().iterator();
576 while (i.hasNext()) {
577 String varKey = (String) i.next();
578 Var var = this.getVar(varKey);
579
580 var.setValue(ValidatorUtils.replace(var.getValue(), key, replaceValue));
581 }
582
583 }
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 String varKey = TOKEN_START + TOKEN_VAR;
590
591 if (key != null && !key.startsWith(varKey)) {
592 for (Iterator i = hMsgs.values().iterator(); i.hasNext();) {
593 Msg msg = (Msg) i.next();
594 msg.setKey(ValidatorUtils.replace(msg.getKey(), key, replaceValue));
595 }
596 }
597
598 this.processArg(key, replaceValue);
599 }
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 for (int i = 0; i < this.args.length; i++) {
607
608 Map argMap = this.args[i];
609 if (argMap == null) {
610 continue;
611 }
612
613 Iterator iter = argMap.values().iterator();
614 while (iter.hasNext()) {
615 Arg arg = (Arg) iter.next();
616
617 if (arg != null) {
618 arg.setKey(
619 ValidatorUtils.replace(arg.getKey(), key, replaceValue));
620 }
621 }
622 }
623 }
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 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 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 Field field = null;
649 try {
650 field = (Field) super.clone();
651 } catch(CloneNotSupportedException e) {
652 throw new RuntimeException(e.toString());
653 }
654
655 field.args = new Map[this.args.length];
656 for (int i = 0; i < this.args.length; i++) {
657 if (this.args[i] == null) {
658 continue;
659 }
660
661 Map argMap = new HashMap(this.args[i]);
662 Iterator iter = argMap.keySet().iterator();
663 while (iter.hasNext()) {
664 String validatorName = (String) iter.next();
665 Arg arg = (Arg) argMap.get(validatorName);
666 argMap.put(validatorName, arg.clone());
667 }
668 field.args[i] = argMap;
669 }
670
671 field.hVars = ValidatorUtils.copyFastHashMap(hVars);
672 field.hMsgs = ValidatorUtils.copyFastHashMap(hMsgs);
673
674 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 StringBuffer results = new StringBuffer();
683
684 results.append("\t\tkey = " + key + "\n");
685 results.append("\t\tproperty = " + property + "\n");
686 results.append("\t\tindexedProperty = " + indexedProperty + "\n");
687 results.append("\t\tindexedListProperty = " + indexedListProperty + "\n");
688 results.append("\t\tdepends = " + depends + "\n");
689 results.append("\t\tpage = " + page + "\n");
690 results.append("\t\tfieldOrder = " + fieldOrder + "\n");
691
692 if (hVars != null) {
693 results.append("\t\tVars:\n");
694 for (Iterator i = hVars.keySet().iterator(); i.hasNext();) {
695 Object key = i.next();
696 results.append("\t\t\t");
697 results.append(key);
698 results.append("=");
699 results.append(hVars.get(key));
700 results.append("\n");
701 }
702 }
703
704 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 Object indexedProperty = null;
716
717 try {
718 indexedProperty =
719 PropertyUtils.getProperty(bean, this.getIndexedListProperty());
720
721 } catch(IllegalAccessException e) {
722 throw new ValidatorException(e.getMessage());
723 } catch(InvocationTargetException e) {
724 throw new ValidatorException(e.getMessage());
725 } catch(NoSuchMethodException e) {
726 throw new ValidatorException(e.getMessage());
727 }
728
729 if (indexedProperty instanceof Collection) {
730 return ((Collection) indexedProperty).toArray();
731
732 } else if (indexedProperty.getClass().isArray()) {
733 return (Object[]) indexedProperty;
734
735 } else {
736 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 Object indexedProperty = null;
749
750 try {
751 indexedProperty =
752 PropertyUtils.getProperty(bean, this.getIndexedListProperty());
753
754 } catch(IllegalAccessException e) {
755 throw new ValidatorException(e.getMessage());
756 } catch(InvocationTargetException e) {
757 throw new ValidatorException(e.getMessage());
758 } catch(NoSuchMethodException e) {
759 throw new ValidatorException(e.getMessage());
760 }
761
762 if (indexedProperty == null) {
763 return 0;
764 } else if (indexedProperty instanceof Collection) {
765 return ((Collection)indexedProperty).size();
766 } else if (indexedProperty.getClass().isArray()) {
767 return ((Object[])indexedProperty).length;
768 } else {
769 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 ValidatorResult result = results.getValidatorResult(this.getKey());
788 if (result != null && result.containsAction(va.getName())) {
789 return result.isValid(va.getName());
790 }
791
792 if (!this.runDependentValidators(va, results, actions, params, pos)) {
793 return false;
794 }
795
796 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 List dependentValidators = va.getDependencyList();
818
819 if (dependentValidators.isEmpty()) {
820 return true;
821 }
822
823 Iterator iter = dependentValidators.iterator();
824 while (iter.hasNext()) {
825 String depend = (String) iter.next();
826
827 ValidatorAction action = (ValidatorAction) actions.get(depend);
828 if (action == null) {
829 this.handleMissingAction(depend);
830 }
831
832 if (!this.validateForRule(action, results, actions, params, pos)) {
833 return false;
834 }
835 }
836
837 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 if (this.getDepends() == null) {
855 return new ValidatorResults();
856 }
857
858 ValidatorResults allResults = new ValidatorResults();
859
860 Object bean = params.get(Validator.BEAN_PARAM);
861 int numberOfFieldsToValidate =
862 this.isIndexed() ? this.getIndexedPropertySize(bean) : 1;
863
864 for (int fieldNumber = 0; fieldNumber < numberOfFieldsToValidate; fieldNumber++) {
865
866 Iterator dependencies = this.dependencyList.iterator();
867 ValidatorResults results = new ValidatorResults();
868 while (dependencies.hasNext()) {
869 String depend = (String) dependencies.next();
870
871 ValidatorAction action = (ValidatorAction) actions.get(depend);
872 if (action == null) {
873 this.handleMissingAction(depend);
874 }
875
876 boolean good =
877 validateForRule(action, results, actions, params, fieldNumber);
878
879 if (!good) {
880 allResults.merge(results);
881 return allResults;
882 }
883 }
884 allResults.merge(results);
885 }
886
887 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 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 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 return hVars;
917 }
918
919 }
920