1 package org.apache.turbine.services.intake.model;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.reflect.Method;
21
22 import java.util.Locale;
23
24 import org.apache.commons.lang.StringUtils;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 import org.apache.turbine.om.Retrievable;
30 import org.apache.turbine.services.TurbineServices;
31 import org.apache.turbine.services.intake.IntakeException;
32 import org.apache.turbine.services.intake.TurbineIntake;
33 import org.apache.turbine.services.intake.validator.DefaultValidator;
34 import org.apache.turbine.services.intake.validator.InitableByConstraintMap;
35 import org.apache.turbine.services.intake.validator.ValidationException;
36 import org.apache.turbine.services.intake.validator.Validator;
37 import org.apache.turbine.services.intake.xmlmodel.Rule;
38 import org.apache.turbine.services.intake.xmlmodel.XmlField;
39 import org.apache.turbine.services.localization.Localization;
40 import org.apache.turbine.services.localization.LocalizationService;
41 import org.apache.turbine.util.SystemError;
42 import org.apache.turbine.util.parser.ParameterParser;
43 import org.apache.turbine.util.parser.ValueParser;
44
45 /***
46 * Base class for Intake generated input processing classes.
47 *
48 * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
49 * @author <a href="mailto:dlr@finemaltcoding.com>Daniel Rall</a>
50 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
51 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
52 * @version $Id: Field.java 264148 2005-08-29 14:21:04Z henning $
53 */
54 public abstract class Field
55 {
56 /*** Empty Value */
57 private static final String EMPTY = "";
58
59 /*** CGI Key for "value if absent" */
60 private static final String VALUE_IF_ABSENT_KEY = "_vifa_";
61
62 /*** Default Package */
63 public static final String defaultFieldPackage = "org.apache.turbine.services.intake.validator.";
64
65
66
67 /*** Name of the field. */
68 protected final String name;
69
70 /*** Key used to identify the field in the parser */
71 protected final String key;
72
73 /*** Display name of the field to be used on data entry forms... */
74 protected String displayName;
75
76 /*** Class name of the object to which the field is mapped */
77 protected final String mapToObject;
78
79 /*** Used to validate the contents of the field */
80 protected Validator validator;
81
82 /*** Getter method in the mapped object used to populate the field */
83 protected final Method getter;
84
85 /*** Setter method in the mapped object used to store the value of field */
86 protected final Method setter;
87
88 /*** Error message set on the field if required and not set by parser */
89 protected String ifRequiredMessage;
90
91 /*** Does this field accept multiple values? */
92 protected final boolean isMultiValued;
93
94 /*** Group to which the field belongs */
95 protected final Group group;
96
97 /*** Is this field always required? This is only set through the XML file */
98 protected boolean alwaysRequired;
99
100 /***
101 * Value of the field if an error occurs while getting
102 * the value from the mapped object
103 */
104 protected Object onError;
105
106 /*** Default value of the field */
107 protected Object defaultValue;
108
109 /*** Value of the field to use if the mapped parameter is empty or non-existant */
110 protected Object emptyValue;
111
112 /*** Display size of the field */
113 private String displaySize;
114
115 /*** Max size of the field */
116 private String maxSize;
117
118
119
120 /*** Has the field has been set from the parser? */
121 protected boolean setFlag;
122
123 /*** Has the field passed the validation test? */
124 protected boolean validFlag;
125
126 /*** Does the field require a value? */
127 protected boolean required;
128
129 /*** Has the field has been set from the parser? */
130 protected boolean initialized;
131
132 /*** Error message, is any, resulting from validation */
133 protected String message;
134
135 /*** Mapped object used to set the initial field value */
136 protected Retrievable retrievable;
137
138 private Locale locale;
139 /*** String value of the field */
140 private String stringValue;
141 /*** String valuess of the field if isMultiValued=true */
142 private String[] stringValues;
143 /*** Stores the value of the field from the Retrievable object */
144 private Object validValue;
145 /*** Stores the value of the field from the parser */
146 private Object testValue;
147 /*** Used to pass testValue to the setter mathod through reflection */
148 private Object[] valArray;
149 /*** The object containing the field data. */
150 protected ValueParser parser;
151
152 /*** Logging */
153 protected Log log = LogFactory.getLog(this.getClass());
154 protected boolean isDebugEnabled = false;
155
156 /***
157 * Constructs a field based on data in the xml specification
158 * and assigns it to a Group.
159 *
160 * @param field a <code>XmlField</code> value
161 * @param group a <code>Group</code> value
162 * @throws IntakeException indicates the validator was not valid or
163 * could not be loaded.
164 * @throws SystemError only occurs is the Validation object does not
165 * extend InitableByConstraintMap
166 */
167 public Field(XmlField field, Group group) throws IntakeException
168 {
169 isDebugEnabled = log.isDebugEnabled();
170
171 this.group = group;
172 key = field.getKey();
173 name = field.getName();
174 displayName = field.getDisplayName();
175 displaySize = field.getDisplaySize();
176 isMultiValued = field.isMultiValued();
177
178 try
179 {
180 setDefaultValue(field.getDefaultValue());
181 }
182 catch (RuntimeException e)
183 {
184 log.error("Could not set default value of " +
185 this.getDisplayName() + " to "
186 + field.getDefaultValue(), e);
187 }
188
189 try
190 {
191 setEmptyValue(field.getEmptyValue());
192 }
193 catch (RuntimeException e)
194 {
195 log.error("Could not set empty value of " +
196 this.getDisplayName() + " to "
197 + field.getEmptyValue(), e);
198 }
199
200 String validatorClassName = field.getValidator();
201 if (validatorClassName == null && field.getRules().size() > 0)
202 {
203 validatorClassName = getDefaultValidator();
204 }
205 else if (validatorClassName != null
206 && validatorClassName.indexOf('.') == -1)
207 {
208 validatorClassName = defaultFieldPackage + validatorClassName;
209 }
210
211 if (validatorClassName != null)
212 {
213 try
214 {
215 validator = (Validator)
216 Class.forName(validatorClassName).newInstance();
217 }
218 catch (InstantiationException e)
219 {
220 throw new IntakeException(
221 "Could not create new instance of Validator("
222 + validatorClassName + ")", e);
223 }
224 catch (IllegalAccessException e)
225 {
226 throw new IntakeException(
227 "Could not create new instance of Validator("
228 + validatorClassName + ")", e);
229 }
230 catch (ClassNotFoundException e)
231 {
232 throw new IntakeException(
233 "Could not load Validator class("
234 + validatorClassName + ")", e);
235 }
236
237
238 if (validator instanceof InitableByConstraintMap)
239 {
240 ((InitableByConstraintMap) validator).init(field.getRuleMap());
241 }
242 else
243 {
244 throw new SystemError(
245 "All Validation objects must be subclasses of "
246 + "InitableByConstraintMap");
247 }
248 }
249
250
251 Rule reqRule = (Rule) field.getRuleMap().get("required");
252 if (reqRule != null)
253 {
254 alwaysRequired = Boolean.valueOf(reqRule.getValue()).booleanValue();
255 ifRequiredMessage = reqRule.getMessage();
256 }
257
258 Rule maxLengthRule = (Rule) field.getRuleMap().get("maxLength");
259 if (maxLengthRule != null)
260 {
261 maxSize = maxLengthRule.getValue();
262 }
263
264
265 mapToObject = field.getMapToObject();
266 String propName = field.getMapToProperty();
267 Method tmpGetter = null;
268 Method tmpSetter = null;
269 if (StringUtils.isNotEmpty(mapToObject)
270 && StringUtils.isNotEmpty(propName))
271 {
272 try
273 {
274 tmpGetter = TurbineIntake.getFieldGetter(mapToObject, propName);
275 }
276 catch (Exception e)
277 {
278 log.error("IntakeService could not map the getter for field "
279 + this.getDisplayName() + " in group "
280 + this.group.getIntakeGroupName()
281 + " to the property " + propName + " in object "
282 + mapToObject, e);
283 }
284 try
285 {
286 tmpSetter = TurbineIntake.getFieldSetter(mapToObject, propName);
287 }
288 catch (Exception e)
289 {
290 log.error("IntakeService could not map the setter for field "
291 + this.getDisplayName() + " in group "
292 + this.group.getIntakeGroupName()
293 + " to the property " + propName + " in object "
294 + mapToObject, e);
295 }
296 }
297 getter = tmpGetter;
298 setter = tmpSetter;
299
300 valArray = new Object[1];
301 }
302
303 /***
304 * Method called when this field (the group it belongs to) is
305 * pulled from the pool. The request data is searched to determine
306 * if a value has been supplied for this field. If so, the value
307 * is validated.
308 *
309 * @param pp a <code>ValueParser</code> value
310 * @return a <code>Field</code> value
311 * @throws IntakeException this exception is only thrown by subclasses
312 * overriding this implementation.
313 */
314 public Field init(ValueParser pp)
315 throws IntakeException
316 {
317 this.parser = pp;
318 validFlag = true;
319
320
321
322 if (TurbineServices.getInstance()
323 .isRegistered(LocalizationService.SERVICE_NAME))
324 {
325 if (pp instanceof ParameterParser)
326 {
327 this.locale = Localization.getLocale
328 (((ParameterParser) pp).getRequest());
329 }
330 else
331 {
332 this.locale = Localization.getLocale((String) null);
333 }
334 }
335
336 if (pp.containsKey(getKey()))
337 {
338 if (isDebugEnabled)
339 {
340 log.debug(name + ": Found our Key in the request, setting Value");
341 }
342 if (StringUtils.isNotEmpty(pp.getString(getKey())))
343 {
344 setFlag = true;
345 }
346 validate();
347 }
348 else if (pp.containsKey(getValueIfAbsent()) &&
349 pp.getString(getValueIfAbsent()) != null)
350 {
351 pp.add(getKey(), pp.getString(getValueIfAbsent()));
352 setFlag = true;
353 validate();
354 }
355
356 initialized = true;
357 return this;
358 }
359
360 /***
361 * Method called when this field or the group it belongs to is
362 * pulled from the pool. The retrievable object can provide
363 * a default value for the field, or using setProperty the field's
364 * value can be transferred to the retrievable.
365 *
366 * @param obj a <code>Retrievable</code> value
367 * @return a <code>Field</code> value
368 */
369 public Field init(Retrievable obj)
370 {
371 if (!initialized)
372 {
373 validFlag = true;
374 }
375 retrievable = obj;
376 return this;
377 }
378
379 /***
380 * Returns the <code>Locale</code> used when localizing data for
381 * this field, or <code>null</code> if unknown.
382 *
383 * @return Where to localize for.
384 */
385 protected Locale getLocale()
386 {
387 return locale;
388 }
389
390 /***
391 * Produces the fully qualified class name of the default validator.
392 *
393 * @return class name of the default validator
394 */
395 protected String getDefaultValidator()
396 {
397 return DefaultValidator.class.getName();
398 }
399
400 /***
401 * Gets the Validator object for this field.
402 * @return a <code>Validator</code> object
403 */
404 public Validator getValidator()
405 {
406 return validator;
407 }
408
409 /***
410 * Flag to determine whether the field has been declared as required.
411 *
412 * @return value of required.
413 */
414 public boolean isRequired()
415 {
416 return alwaysRequired || required;
417 }
418
419 /***
420 * Set whether this field is required to have a value. If the field
421 * is already required due to a setting in the XML file, this method
422 * can not set it to false.
423 *
424 * @param v Value to assign to required.
425 */
426 public void setRequired(boolean v)
427 {
428 setRequired(v, ifRequiredMessage);
429 }
430
431 /***
432 * Set the value of required.
433 *
434 * @param v a <code>boolean</code> value
435 * @param message override the value from intake.xml
436 */
437 public void setRequired(boolean v, String message)
438 {
439 this.required = v;
440 if (v && (!setFlag || null == getTestValue()))
441 {
442 validFlag = false;
443 this.message = message;
444 }
445 }
446
447 /***
448 * Removes references to this group and its fields from the
449 * query parameters
450 */
451 public void removeFromRequest()
452 {
453 parser.remove(getKey());
454 parser.remove(getKey()+ VALUE_IF_ABSENT_KEY);
455 }
456
457 /***
458 * Disposes the object after use. The method is called
459 * when the Group is returned to its pool.
460 * if overridden, super.dispose() should be called.
461 */
462 public void dispose()
463 {
464 parser = null;
465 initialized = false;
466 setFlag = false;
467 validFlag = false;
468 required = false;
469 message = null;
470 retrievable = null;
471
472 locale = null;
473 stringValue = null;
474 stringValues = null;
475 validValue = null;
476 testValue = null;
477 valArray[0] = null;
478 }
479
480 /***
481 * Get the key used to identify the field.
482 *
483 * @return the query data key.
484 */
485 public String getKey()
486 {
487 return (group == null) ? key : group.getObjectKey() + key;
488 }
489
490 /***
491 * Use in a hidden field assign a default value in the event the
492 * field is absent from the query parameters. Used to track checkboxes,
493 * since they only show up if checked.
494 */
495 public String getValueIfAbsent()
496 {
497 return getKey() + VALUE_IF_ABSENT_KEY;
498 }
499
500 /***
501 * Flag set to true, if the test value met the constraints.
502 * Is also true, in the case the test value was not set,
503 * unless this field has been marked as required.
504 *
505 * @return a <code>boolean</code> value
506 */
507 public boolean isValid()
508 {
509 return validFlag;
510 }
511
512 /***
513 * Flag set to true, if the test value has been set to
514 * anything other than an empty value.
515 *
516 * @return a <code>boolean</code> value
517 */
518 public boolean isSet()
519 {
520 return setFlag;
521 }
522
523 /***
524 * Get the display name of the field. Useful for building
525 * data entry forms. Returns name of field if no display
526 * name has been assigned to the field by xml input file.
527 *
528 * @return a <code>String</code> value
529 */
530 public String getDisplayName()
531 {
532 return (displayName == null) ? name : displayName;
533 }
534
535 /***
536 * Set the display name of the field. Display names are
537 * used in building data entry forms and serve as a
538 * user friendly description of the data contained in
539 * the field.
540 */
541 public void setDisplayName(String newDisplayName)
542 {
543 displayName = newDisplayName;
544 }
545
546 /***
547 * Get any error message resulting from invalid input.
548 *
549 * @return a <code>String</code> value
550 */
551 public String getMessage()
552 {
553 return (message == null) ? EMPTY : message;
554 }
555
556 /***
557 * Sets an error message. The field is also marked as invalid.
558 */
559 public void setMessage(String message)
560 {
561 this.message = message;
562 validFlag = false;
563 }
564
565 /***
566 * @deprecated Call validate() instead (with no parameters).
567 */
568 protected boolean validate(ValueParser pp)
569 {
570 return validate();
571 }
572
573 /***
574 * Compares request data with constraints and sets the valid flag.
575 */
576 protected boolean validate()
577 {
578 log.debug(name + ": validate()");
579
580 if (isMultiValued)
581 {
582 stringValues = parser.getStrings(getKey());
583
584 if (isDebugEnabled)
585 {
586 log.debug(name + ": Multi-Valued");
587 for (int i = 0; i < stringValues.length; i++)
588 {
589 log.debug(name + ": " + i + ". Wert: " + stringValues[i]);
590 }
591 }
592
593
594 if (validator != null)
595 {
596
597
598 setTestValue(parser.getStrings(getKey()));
599 for (int i = 0; i < stringValues.length; i++)
600 {
601 try
602 {
603 validator.assertValidity(stringValues[i]);
604 }
605 catch (ValidationException ve)
606 {
607 setMessage(ve.getMessage());
608 }
609 }
610 }
611
612 if (validFlag)
613 {
614 doSetValue();
615 }
616 }
617 else
618 {
619 stringValue = parser.getString(getKey());
620
621 if (isDebugEnabled)
622 {
623 log.debug(name + ": Single Valued, Value is " + stringValue);
624 }
625
626 if (validator != null)
627 {
628
629
630 setTestValue(parser.getString(getKey()));
631
632 try
633 {
634 validator.assertValidity(stringValue);
635 log.debug(name + ": Value is ok");
636 doSetValue();
637 }
638 catch (ValidationException ve)
639 {
640 log.debug(name + ": Value failed validation!");
641 setMessage(ve.getMessage());
642 }
643 }
644 else
645 {
646 doSetValue();
647 }
648 }
649
650 return validFlag;
651 }
652
653 /***
654 * Set the default Value. This value is used if
655 * Intake should map this field to a new object.
656 *
657 * @param prop The value to use if the field is mapped to a new object.
658 */
659 public abstract void setDefaultValue(String prop);
660
661 /***
662 * Set the empty Value. This value is used if Intake
663 * maps a field to a parameter returned by the user and
664 * the corresponding field is either empty (empty string)
665 * or non-existant.
666 *
667 * @param prop The value to use if the field is empty.
668 */
669 public abstract void setEmptyValue(String prop);
670
671 /***
672 * @deprecated Use doSetValue() instead (with no parameters).
673 */
674 protected void doSetValue(ValueParser pp)
675 {
676 doSetValue();
677 }
678
679 /***
680 * Sets the value of the field from data in the parser.
681 */
682 protected abstract void doSetValue();
683
684 /***
685 * Set the value used as a default, in the event the field
686 * has not been set yet.
687 *
688 * @param obj an <code>Object</code> value
689 */
690 void setInitialValue(Object obj)
691 {
692 validValue = obj;
693 }
694
695 /***
696 * Get the value used as a default. If the initial value has
697 * not been set and a <code>Retrievable</code> object has
698 * been associated with this field, the objects property will
699 * be used as the initial value.
700 *
701 * @return an <code>Object</code> value
702 * @exception IntakeException indicates the value could not be
703 * returned from the mapped object
704 */
705 public Object getInitialValue() throws IntakeException
706 {
707 if (validValue == null)
708 {
709 if (retrievable != null)
710 {
711 getProperty(retrievable);
712 }
713 else
714 {
715 getDefault();
716 }
717 }
718 return validValue;
719 }
720
721 /***
722 * Set the value input by a user that will be validated.
723 *
724 * @param obj an <code>Object</code> value
725 */
726 void setTestValue(Object obj)
727 {
728 testValue = obj;
729 }
730
731 /***
732 * Get the value input by a user that will be validated.
733 *
734 * @return an <code>Object</code> value
735 */
736 public Object getTestValue()
737 {
738 return testValue;
739 }
740
741 /***
742 * Get the value of the field. if a test value has been set, it
743 * will be returned as is, unless it is so badly formed that the
744 * validation could not parse it. In most cases the test value
745 * is returned even though invalid, so that it can be returned to
746 * the user to make modifications. If the test value is not set
747 * the initial value is returned.
748 *
749 * @return an <code>Object</code> value
750 */
751 public Object getValue()
752 {
753 Object val = null;
754 try
755 {
756 val = getInitialValue();
757 }
758 catch (IntakeException e)
759 {
760 log.error("Could not get intial value of " + this.getDisplayName() +
761 " in group " + this.group.getIntakeGroupName(), e);
762 }
763
764 if (getTestValue() != null)
765 {
766 val = getTestValue();
767 }
768
769 if (val == null)
770 {
771 val = onError;
772 }
773 return val;
774 }
775
776 /***
777 * Calls toString() on the object returned by getValue(),
778 * unless null; and then it returns "", the empty String.
779 *
780 * @return a <code>String</code> value
781 */
782 public String toString()
783 {
784 String res = EMPTY;
785
786 if (stringValue != null)
787 {
788 res = stringValue;
789 }
790 else if (getValue() != null)
791 {
792 res = getValue().toString();
793 }
794 return res;
795 }
796
797 /***
798 * Calls toString() on the object returned by getValue(),
799 * unless null; and then it returns "", the empty String.
800 * Escapes " characters to be able to display these
801 * in HTML form fields.
802 *
803 * @return a <code>String</code> value
804 */
805 public String getHTMLString()
806 {
807 String res = toString();
808 return StringUtils.replace(res, "\"", """);
809 }
810
811 /***
812 * Loads the valid value from a bean
813 *
814 * @throws IntakeException indicates a problem during the execution of the
815 * object's getter method
816 */
817 public void getProperty(Object obj)
818 throws IntakeException
819 {
820 try
821 {
822 validValue = getter.invoke(obj, null);
823 }
824 catch (IllegalAccessException e)
825 {
826 throwSetGetException("getter", obj, this.getDisplayName(),
827 this.group.getIntakeGroupName(), e);
828 }
829 catch (IllegalArgumentException e)
830 {
831 throwSetGetException("getter", obj, this.getDisplayName(),
832 this.group.getIntakeGroupName(), e);
833 }
834 catch (InvocationTargetException e)
835 {
836 throwSetGetException("getter", obj, this.getDisplayName(),
837 this.group.getIntakeGroupName(), e);
838 }
839 }
840
841 /***
842 * Loads the default value from the object
843 */
844
845 public void getDefault()
846 {
847 validValue = getDefaultValue();
848 }
849
850 /***
851 * Calls a setter method on obj, if this field has been set.
852 *
853 * @throws IntakeException indicates a problem during the execution of the
854 * object's setter method
855 */
856 public void setProperty(Object obj) throws IntakeException
857 {
858 if (isDebugEnabled)
859 {
860 log.debug(name + ".setProperty(" + obj.getClass().getName() + ")");
861 }
862
863 if (!isValid())
864 {
865 throw new IntakeException(
866 "Attempted to assign an invalid input.");
867 }
868 if (isSet())
869 {
870 valArray[0] = getTestValue();
871 if (isDebugEnabled)
872 {
873 log.debug(name + ": Property is set, value is " + valArray[0]);
874 }
875 }
876 else
877 {
878 valArray[0] = getSafeEmptyValue();
879 if (isDebugEnabled)
880 {
881 log.debug(name + ": Property is not set, using emptyValue " + valArray[0]);
882 }
883 }
884
885 try
886 {
887 setter.invoke(obj, valArray);
888 }
889 catch (IllegalAccessException e)
890 {
891 throwSetGetException("setter", obj, this.getDisplayName(),
892 this.group.getIntakeGroupName(), e);
893 }
894 catch (IllegalArgumentException e)
895 {
896 throwSetGetException("setter", obj, this.getDisplayName(),
897 this.group.getIntakeGroupName(), e);
898 }
899 catch (InvocationTargetException e)
900 {
901 throwSetGetException("setter", obj, this.getDisplayName(),
902 this.group.getIntakeGroupName(), e);
903 }
904 }
905
906 /***
907 * Used to throw an IntakeException when an error occurs execuing the
908 * get/set method of the mapped persistent object.
909 *
910 * @param type Type of method. (setter/getter)
911 * @param fieldName Name of the field
912 * @param groupName Name of the group
913 * @param e Exception that was thrown
914 * @throws IntakeException New exception with formatted message
915 */
916 private void throwSetGetException(String type, Object obj,
917 String fieldName, String groupName,
918 Exception e)
919 throws IntakeException
920 {
921 throw new IntakeException("Could not execute " + type
922 + " method for " + fieldName + " in group " + groupName
923 + " on " + obj.getClass().getName(), e);
924
925 }
926
927 /***
928 * Get the default Value
929 *
930 * @return the default value
931 */
932 public Object getDefaultValue()
933 {
934 return defaultValue;
935 }
936
937 /***
938 * Get the Value to use if the field is empty
939 *
940 * @return the value to use if the field is empty.
941 */
942 public Object getEmptyValue()
943 {
944 return emptyValue;
945 }
946
947 /***
948 * Provides access to emptyValue such that the value returned will be
949 * acceptable as an argument parameter to Method.invoke. Subclasses
950 * that deal with primitive types should ensure that they return an
951 * appropriate value wrapped in the object wrapper class for the
952 * primitive type.
953 *
954 * @return the value to use when the field is empty or an Object that
955 * wraps the empty value for primitive types.
956 */
957 protected Object getSafeEmptyValue()
958 {
959 return getEmptyValue();
960 }
961
962 /***
963 * Gets the name of the field.
964 *
965 * @return name of the field as specified in the XML file.
966 */
967 public String getName()
968 {
969 return name;
970 }
971
972 /***
973 * Gets the diplay size of the field. This is useful when
974 * building the HTML input tag. If no displaySize was set,
975 * an empty string is returned.
976 */
977 public String getDisplaySize()
978 {
979 return (StringUtils.isEmpty(displaySize) ? "" : displaySize);
980 }
981
982 /***
983 * Gets the maximum size of the field. This is useful when
984 * building the HTML input tag. The maxSize is set with the maxLength
985 * rule. If this rul was not set, an enmpty string is returned.
986 */
987 public String getMaxSize()
988 {
989 return (StringUtils.isEmpty(maxSize) ? "" : maxSize);
990 }
991
992 /***
993 * Gets the String representation of the Value. This is basically a wrapper
994 * method for the toString method which doesn't seem to show anything on
995 * screen if accessed from Template. Name is also more in line with getValue
996 * method which returns the actual Object.
997 * This is useful for displaying correctly formatted data such as dates,
998 * such as 18/11/1968 instead of the toString dump of a Date Object.
999 *
1000 * @return the String Value
1001 */
1002 public String getStringValue()
1003 {
1004 return this.toString();
1005 }
1006
1007 }