001 package org.apache.fulcrum.intake.model;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 import java.lang.reflect.InvocationTargetException;
023 import java.lang.reflect.Method;
024 import java.util.Locale;
025
026 import org.apache.commons.lang.StringUtils;
027 import org.apache.commons.logging.Log;
028 import org.apache.commons.logging.LogFactory;
029 import org.apache.fulcrum.intake.IntakeError;
030 import org.apache.fulcrum.intake.IntakeException;
031 import org.apache.fulcrum.intake.IntakeServiceFacade;
032 import org.apache.fulcrum.intake.Retrievable;
033 import org.apache.fulcrum.intake.validator.DefaultValidator;
034 import org.apache.fulcrum.intake.validator.InitableByConstraintMap;
035 import org.apache.fulcrum.intake.validator.ValidationException;
036 import org.apache.fulcrum.intake.validator.Validator;
037 import org.apache.fulcrum.intake.xmlmodel.Rule;
038 import org.apache.fulcrum.intake.xmlmodel.XmlField;
039 import org.apache.fulcrum.parser.ValueParser;
040
041 /**
042 * Base class for Intake generated input processing classes.
043 *
044 * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
045 * @author <a href="mailto:dlr@finemaltcoding.com>Daniel Rall</a>
046 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
047 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
048 * @author <a href="mailto:jh@byteaction.de">Jürgen Hoffmann</a>
049 * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
050 * @version $Id: Field.java 671342 2008-06-24 20:57:54Z tv $
051 */
052 public abstract class Field
053 {
054 /** Empty Value */
055 private static final String EMPTY = "";
056
057 /** CGI Key for "value if absent" */
058 private static final String VALUE_IF_ABSENT_KEY = "_vifa_";
059
060 /** Default Validator Package */
061 public static final String defaultValidatorPackage = "org.apache.fulcrum.intake.validator.";
062
063 /** Default Field Package */
064 public static final String defaultFieldPackage = "org.apache.fulcrum.intake.model.";
065
066 // the following are set from the xml file and are permanent (final)
067
068 /** Name of the field. */
069 protected final String name;
070
071 /** Key used to identify the field in the parser */
072 protected final String key;
073
074 /** Display name of the field to be used on data entry forms... */
075 protected String displayName;
076
077 /** Class name of the object to which the field is mapped */
078 protected final String mapToObject;
079
080 /** Used to validate the contents of the field */
081 protected Validator validator;
082
083 /** Getter method in the mapped object used to populate the field */
084 protected final Method getter;
085
086 /** Setter method in the mapped object used to store the value of field */
087 protected final Method setter;
088
089 /** Error message set on the field if required and not set by parser */
090 protected String ifRequiredMessage;
091
092 /** Does this field accept multiple values? */
093 protected final boolean isMultiValued;
094
095 /** Group to which the field belongs */
096 protected final Group group;
097
098 /** Is this field always required? This is only set through the XML file */
099 protected boolean alwaysRequired;
100
101 /**
102 * Value of the field if an error occurs while getting
103 * the value from the mapped object
104 */
105 protected Object onError;
106
107 /** Default value of the field */
108 protected Object defaultValue;
109
110 /** Value of the field to use if the mapped parameter is empty or non-existant */
111 protected Object emptyValue;
112
113 /** Display size of the field */
114 private String displaySize;
115
116 /** Max size of the field */
117 private String maxSize;
118
119 // these are reset when the Field is returned to the pool
120
121 /** Has the field has been set from the parser? */
122 protected boolean setFlag;
123
124 /** Has the field passed the validation test? */
125 protected boolean validFlag;
126
127 /** Has the field been validated? */
128 protected boolean validated;
129
130 /** Does the field require a value? */
131 protected boolean required;
132
133 /** Has the field has been set from the parser? */
134 protected boolean initialized;
135
136 /** Error message, is any, resulting from validation */
137 protected String message;
138
139 /** Mapped object used to set the initial field value */
140 protected Retrievable retrievable;
141
142 private Locale locale;
143 /** String value of the field */
144 private String stringValue;
145 /** String valuess of the field if isMultiValued=true */
146 private String[] stringValues;
147 /** Stores the value of the field from the Retrievable object */
148 private Object validValue;
149 /** Stores the value of the field from the parser */
150 private Object testValue;
151 /** Used to pass testValue to the setter mathod through reflection */
152 private Object[] valArray;
153 /** The object containing the field data. */
154 protected ValueParser parser;
155
156 /** Logging */
157 protected Log log = LogFactory.getLog(this.getClass());
158 protected boolean isDebugEnabled = false;
159
160 /**
161 * Constructs a field based on data in the xml specification
162 * and assigns it to a Group.
163 *
164 * @param field a <code>XmlField</code> value
165 * @param group a <code>Group</code> value
166 * @throws IntakeException indicates the validator was not valid or
167 * could not be loaded.
168 * @throws SystemError only occurs is the Validation object does not
169 * extend InitableByConstraintMap
170 */
171 public Field(XmlField field, Group group) throws IntakeException
172 {
173 isDebugEnabled = log.isDebugEnabled();
174
175 this.group = group;
176 key = field.getKey();
177 name = field.getName();
178 displayName = field.getDisplayName();
179 displaySize = field.getDisplaySize();
180 isMultiValued = field.isMultiValued();
181
182 try
183 {
184 setDefaultValue(field.getDefaultValue());
185 }
186 catch (RuntimeException e)
187 {
188 log.error("Could not set default value of " +
189 this.getDisplayName() + " to "
190 + field.getDefaultValue(), e);
191 }
192
193 try
194 {
195 setEmptyValue(field.getEmptyValue());
196 }
197 catch (RuntimeException e)
198 {
199 log.error("Could not set empty value of " +
200 this.getDisplayName() + " to "
201 + field.getEmptyValue(), e);
202 }
203
204 String validatorClassName = field.getValidator();
205 if (validatorClassName == null)
206 {
207 validatorClassName = getDefaultValidator();
208 }
209 else if (validatorClassName.indexOf('.') == -1)
210 {
211 validatorClassName = defaultValidatorPackage + validatorClassName;
212 }
213
214 if (validatorClassName != null)
215 {
216 try
217 {
218 validator = (Validator)
219 Class.forName(validatorClassName).newInstance();
220 }
221 catch (InstantiationException e)
222 {
223 throw new IntakeException(
224 "Could not create new instance of Validator("
225 + validatorClassName + ")", e);
226 }
227 catch (IllegalAccessException e)
228 {
229 throw new IntakeException(
230 "Could not create new instance of Validator("
231 + validatorClassName + ")", e);
232 }
233 catch (ClassNotFoundException e)
234 {
235 throw new IntakeException(
236 "Could not load Validator class("
237 + validatorClassName + ")", e);
238 }
239 // this should always be true for now
240 // (until bean property initialization is implemented)
241 if (validator instanceof InitableByConstraintMap)
242 {
243 ((InitableByConstraintMap) validator).init(field.getRuleMap());
244 }
245 else
246 {
247 throw new IntakeError(
248 "All Validation objects must be subclasses of "
249 + "InitableByConstraintMap");
250 }
251 }
252
253 // field may have been declared as always required in the xml spec
254 Rule reqRule = (Rule) field.getRuleMap().get("required");
255 if (reqRule != null)
256 {
257 alwaysRequired = Boolean.valueOf(reqRule.getValue()).booleanValue();
258 ifRequiredMessage = reqRule.getMessage();
259 }
260
261 Rule maxLengthRule = (Rule) field.getRuleMap().get("maxLength");
262 if (maxLengthRule != null)
263 {
264 maxSize = maxLengthRule.getValue();
265 }
266
267 // map the getter and setter methods
268 mapToObject = field.getMapToObject();
269 String propName = field.getMapToProperty();
270 Method tmpGetter = null;
271 Method tmpSetter = null;
272 if (StringUtils.isNotEmpty(mapToObject)
273 && StringUtils.isNotEmpty(propName))
274 {
275 try
276 {
277 tmpGetter = IntakeServiceFacade.getFieldGetter(mapToObject, propName);
278 }
279 catch (Exception e)
280 {
281 log.error("IntakeService could not map the getter for field "
282 + this.getDisplayName() + " in group "
283 + this.group.getIntakeGroupName()
284 + " to the property " + propName + " in object "
285 + mapToObject, e);
286 }
287 try
288 {
289 tmpSetter = IntakeServiceFacade.getFieldSetter(mapToObject, propName);
290 }
291 catch (Exception e)
292 {
293 log.error("IntakeService could not map the setter for field "
294 + this.getDisplayName() + " in group "
295 + this.group.getIntakeGroupName()
296 + " to the property " + propName + " in object "
297 + mapToObject, e);
298 }
299 }
300 getter = tmpGetter;
301 setter = tmpSetter;
302
303 valArray = new Object[1];
304 }
305
306 /**
307 * Method called when this field (the group it belongs to) is
308 * pulled from the pool. The request data is searched to determine
309 * if a value has been supplied for this field. If so, the value
310 * is validated.
311 *
312 * @param pp a <code>ValueParser</code> value
313 * @return a <code>Field</code> value
314 * @throws IntakeException this exception is only thrown by subclasses
315 * overriding this implementation.
316 */
317 public Field init(ValueParser pp)
318 throws IntakeException
319 {
320 this.parser = pp;
321 validFlag = true;
322 validated = false;
323
324 this.locale = pp.getLocale();
325
326 if (pp.containsKey(getKey()))
327 {
328 if (isDebugEnabled)
329 {
330 log.debug(name + ": Found our Key in the request, setting Value");
331 }
332 if (pp.getString(getKey()) != null)
333 {
334 setFlag = true;
335 }
336 // validate();
337 }
338 else if (pp.containsKey(getValueIfAbsent()) &&
339 pp.getString(getValueIfAbsent()) != null)
340 {
341 pp.add(getKey(), pp.getString(getValueIfAbsent()));
342 setFlag = true;
343 // validate();
344 }
345
346 initialized = true;
347 return this;
348 }
349
350 /**
351 * Method called when this field or the group it belongs to is
352 * pulled from the pool. The retrievable object can provide
353 * a default value for the field, or using setProperty the field's
354 * value can be transferred to the retrievable.
355 *
356 * @param obj a <code>Retrievable</code> value
357 * @return a <code>Field</code> value
358 */
359 public Field init(Retrievable obj)
360 {
361 if (!initialized)
362 {
363 validFlag = true;
364 validated = false;
365 }
366 retrievable = obj;
367 return this;
368 }
369
370 /**
371 * Returns the <code>Group</code> this field belongs to
372 * or <code>null</code> if unknown.
373 *
374 * @return The group this field belongs to.
375 */
376 public Group getGroup()
377 {
378 return group;
379 }
380
381 /**
382 * Returns the <code>Locale</code> used when localizing data for
383 * this field, or <code>null</code> if unknown.
384 *
385 * @return Where to localize for.
386 */
387 public Locale getLocale()
388 {
389 return locale;
390 }
391
392 /**
393 * Produces the fully qualified class name of the default validator.
394 *
395 * @return class name of the default validator
396 */
397 protected String getDefaultValidator()
398 {
399 return DefaultValidator.class.getName();
400 }
401
402 /**
403 * Gets the Validator object for this field.
404 * @return a <code>Validator</code> object
405 */
406 public Validator getValidator()
407 {
408 return validator;
409 }
410
411 /**
412 * Flag to determine whether the field has been declared as multi-valued.
413 *
414 * @return value of isMultiValued.
415 */
416 public boolean isMultiValued()
417 {
418 return isMultiValued;
419 }
420
421 /**
422 * Flag to determine whether the field has been declared as required.
423 *
424 * @return value of required.
425 */
426 public boolean isRequired()
427 {
428 return alwaysRequired || required;
429 }
430
431 /**
432 * Set whether this field is required to have a value. If the field
433 * is already required due to a setting in the XML file, this method
434 * can not set it to false.
435 *
436 * @param v Value to assign to required.
437 */
438 public void setRequired(boolean v)
439 {
440 setRequired(v, ifRequiredMessage);
441 }
442
443 /**
444 * Set the value of required.
445 *
446 * @param v a <code>boolean</code> value
447 * @param message override the value from intake.xml
448 */
449 public void setRequired(boolean v, String message)
450 {
451 this.required = v;
452 if (v && (!setFlag || null == getTestValue()))
453 {
454 validFlag = false;
455 this.message = message;
456 }
457 }
458
459 /**
460 * Removes references to this group and its fields from the
461 * query parameters
462 */
463 public void removeFromRequest()
464 {
465 parser.remove(getKey());
466 parser.remove(getKey()+ VALUE_IF_ABSENT_KEY);
467 }
468
469 /**
470 * Disposes the object after use. The method is called
471 * when the Group is returned to its pool.
472 * if overridden, super.dispose() should be called.
473 */
474 public void dispose()
475 {
476 parser = null;
477 initialized = false;
478 setFlag = false;
479 validFlag = false;
480 validated = false;
481 required = false;
482 message = null;
483 retrievable = null;
484
485 locale = null;
486 stringValue = null;
487 stringValues = null;
488 validValue = null;
489 testValue = null;
490 valArray[0] = null;
491 }
492
493 /**
494 * Get the key used to identify the field.
495 *
496 * @return the query data key.
497 */
498 public String getKey()
499 {
500 return (group == null) ? key : group.getObjectKey() + key;
501 }
502
503 /**
504 * Use in a hidden field assign a default value in the event the
505 * field is absent from the query parameters. Used to track checkboxes,
506 * since they only show up if checked.
507 */
508 public String getValueIfAbsent()
509 {
510 return getKey() + VALUE_IF_ABSENT_KEY;
511 }
512
513 /**
514 * Flag set to true, if the test value met the constraints.
515 * Is also true, in the case the test value was not set,
516 * unless this field has been marked as required.
517 *
518 * @return a <code>boolean</code> value
519 */
520 public boolean isValid()
521 {
522 return validFlag;
523 }
524
525 /**
526 * Flag to determine whether the field has been validated.
527 *
528 * @return value of validated.
529 */
530 public boolean isValidated()
531 {
532 return validated;
533 }
534
535 /**
536 * Flag set to true, if the test value has been set by the parser (even to
537 * an empty value, so don't used this to determine if the field contains a
538 * non-empty value). Validation will only be executed for fields that have
539 * been set in this manner.
540 *
541 * @return a <code>boolean</code> value
542 */
543 public boolean isSet()
544 {
545 return setFlag;
546 }
547
548 /**
549 * Get the display name of the field. Useful for building
550 * data entry forms. Returns name of field if no display
551 * name has been assigned to the field by xml input file.
552 *
553 * @return a <code>String</code> value
554 */
555 public String getDisplayName()
556 {
557 return (displayName == null) ? name : displayName;
558 }
559
560 /**
561 * Set the display name of the field. Display names are
562 * used in building data entry forms and serve as a
563 * user friendly description of the data contained in
564 * the field.
565 */
566 public void setDisplayName(String newDisplayName)
567 {
568 displayName = newDisplayName;
569 }
570
571 /**
572 * Get any error message resulting from invalid input.
573 *
574 * @return a <code>String</code> value
575 */
576 public String getMessage()
577 {
578 return (message == null) ? EMPTY : message;
579 }
580
581 /**
582 * Sets an error message. The field is also marked as invalid.
583 */
584 public void setMessage(String message)
585 {
586 this.message = message;
587 validFlag = false;
588 }
589
590 /**
591 * @deprecated Call validate() instead (with no parameters).
592 */
593 protected boolean validate(ValueParser pp)
594 {
595 return validate();
596 }
597
598 /**
599 * Compares request data with constraints and sets the valid flag.
600 */
601 public boolean validate()
602 {
603 log.debug(name + ": validate()");
604
605 if (isMultiValued)
606 {
607 stringValues = parser.getStrings(getKey());
608
609 if (isDebugEnabled)
610 {
611 log.debug(name + ": Multi-Valued, Value is " + stringValue);
612 if (stringValues != null)
613 {
614 for (int i = 0; i < stringValues.length; i++)
615 {
616 log.debug(name + ": " + i + ". Value: " + stringValues[i]);
617 }
618 }
619 }
620
621 if (validator != null)
622 {
623 // set the test value as a String[] which might be replaced by
624 // the correct type if the input is valid.
625 setTestValue(stringValues);
626
627 try
628 {
629 validator.assertValidity(this);
630 }
631 catch (ValidationException ve)
632 {
633 setMessage(ve.getMessage());
634 }
635 }
636
637 if (validFlag)
638 {
639 doSetValue();
640 }
641 }
642 else
643 {
644 stringValue = parser.getString(getKey());
645
646 if (isDebugEnabled)
647 {
648 log.debug(name + ": Single Valued, Value is " + stringValue);
649 }
650
651 if (validator != null)
652 {
653 // set the test value as a String which might be replaced by
654 // the correct type if the input is valid.
655 setTestValue(parser.getString(getKey()));
656
657 try
658 {
659 validator.assertValidity(this);
660 log.debug(name + ": Value is ok");
661 doSetValue();
662 }
663 catch (ValidationException ve)
664 {
665 log.debug(name + ": Value failed validation!");
666 setMessage(ve.getMessage());
667 }
668 }
669 else
670 {
671 doSetValue();
672 }
673 }
674
675 validated = true;
676
677 return validFlag;
678 }
679
680 /**
681 * Set the default Value. This value is used if
682 * Intake should map this field to a new object.
683 *
684 * @param prop The value to use if the field is mapped to a new object.
685 */
686 public abstract void setDefaultValue(String prop);
687
688 /**
689 * Set the empty Value. This value is used if Intake
690 * maps a field to a parameter returned by the user and
691 * the corresponding field is either empty (empty string)
692 * or non-existant.
693 *
694 * @param prop The value to use if the field is empty.
695 */
696 public abstract void setEmptyValue(String prop);
697
698 /**
699 * @deprecated Use doSetValue() instead (with no parameters).
700 */
701 protected void doSetValue(ValueParser pp)
702 {
703 doSetValue();
704 }
705
706 /**
707 * Sets the value of the field from data in the parser.
708 */
709 protected abstract void doSetValue();
710
711 /**
712 * Set the value used as a default, in the event the field
713 * has not been set yet.
714 *
715 * @param obj an <code>Object</code> value
716 */
717 void setInitialValue(Object obj)
718 {
719 validValue = obj;
720 }
721
722 /**
723 * Get the value used as a default. If the initial value has
724 * not been set and a <code>Retrievable</code> object has
725 * been associated with this field, the objects property will
726 * be used as the initial value.
727 *
728 * @return an <code>Object</code> value
729 * @exception IntakeException indicates the value could not be
730 * returned from the mapped object
731 */
732 public Object getInitialValue() throws IntakeException
733 {
734 if (validValue == null)
735 {
736 if (retrievable != null)
737 {
738 getProperty(retrievable);
739 }
740 else
741 {
742 getDefault();
743 }
744 }
745 return validValue;
746 }
747
748 /**
749 * Set the value input by a user that will be validated.
750 *
751 * @param obj an <code>Object</code> value
752 */
753 void setTestValue(Object obj)
754 {
755 testValue = obj;
756 }
757
758 /**
759 * Get the value input by a user that will be validated.
760 *
761 * @return an <code>Object</code> value
762 */
763 public Object getTestValue()
764 {
765 return testValue;
766 }
767
768 /**
769 * Get the value of the field. if a test value has been set, it
770 * will be returned as is, unless it is so badly formed that the
771 * validation could not parse it. In most cases the test value
772 * is returned even though invalid, so that it can be returned to
773 * the user to make modifications. If the test value is not set
774 * the initial value is returned.
775 *
776 * @return an <code>Object</code> value
777 */
778 public Object getValue()
779 {
780 Object val = null;
781 try
782 {
783 val = getInitialValue();
784 }
785 catch (IntakeException e)
786 {
787 log.error("Could not get intial value of " + this.getDisplayName() +
788 " in group " + this.group.getIntakeGroupName(), e);
789 }
790
791 if (getTestValue() != null)
792 {
793 val = getTestValue();
794 }
795
796 if (val == null)
797 {
798 val = onError;
799 }
800 return val;
801 }
802
803 /**
804 * Calls toString() on the object returned by getValue(),
805 * unless null; and then it returns "", the empty String.
806 *
807 * @return a <code>String</code> value
808 */
809 public String toString()
810 {
811 String res = EMPTY;
812
813 if (stringValue != null)
814 {
815 res = stringValue;
816 }
817 else if (getValue() != null)
818 {
819 res = getValue().toString();
820 }
821 return res;
822 }
823
824 /**
825 * Calls toString() on the object returned by getValue(),
826 * unless null; and then it returns "", the empty String.
827 * Escapes " characters to be able to display these
828 * in HTML form fields.
829 *
830 * @return a <code>String</code> value
831 */
832 public String getHTMLString()
833 {
834 String res = toString();
835 return StringUtils.replace(res, "\"", """);
836 }
837
838 /**
839 * Loads the valid value from a bean
840 *
841 * @throws IntakeException indicates a problem during the execution of the
842 * object's getter method
843 */
844 public void getProperty(Object obj)
845 throws IntakeException
846 {
847 try
848 {
849 validValue = getter.invoke(obj, (Object[])null);
850 }
851 catch (IllegalAccessException e)
852 {
853 throwSetGetException("getter", obj, this.getDisplayName(),
854 this.group.getIntakeGroupName(), e);
855 }
856 catch (IllegalArgumentException e)
857 {
858 throwSetGetException("getter", obj, this.getDisplayName(),
859 this.group.getIntakeGroupName(), e);
860 }
861 catch (InvocationTargetException e)
862 {
863 throwSetGetException("getter", obj, this.getDisplayName(),
864 this.group.getIntakeGroupName(), e);
865 }
866 }
867
868 /**
869 * Loads the default value from the object
870 */
871
872 public void getDefault()
873 {
874 validValue = getDefaultValue();
875 }
876
877 /**
878 * Calls a setter method on obj, if this field has been set.
879 *
880 * @throws IntakeException indicates a problem during the execution of the
881 * object's setter method
882 */
883 public void setProperty(Object obj) throws IntakeException
884 {
885 if (isDebugEnabled)
886 {
887 log.debug(name + ".setProperty(" + obj.getClass().getName() + ")");
888 }
889
890 if (!isValid())
891 {
892 throw new IntakeException(
893 "Attempted to assign an invalid input.");
894 }
895 if (isSet() && null != getTestValue())
896 {
897 valArray[0] = getTestValue();
898 if (isDebugEnabled)
899 {
900 log.debug(name + ": Property is set, value is " + valArray[0]);
901 }
902 }
903 else
904 {
905 valArray[0] = getSafeEmptyValue();
906 if (isDebugEnabled)
907 {
908 log.debug(name + ": Property is not set, using emptyValue " + valArray[0]);
909 }
910 }
911
912 try
913 {
914 /*
915 * In the case we map a Group to an Object using mapToObject, and we
916 * want to add an additional Field which should not be mapped, and
917 * we leave the mapToProperty empty, we will get a NPE here. So we
918 * have to double check, if we really have a setter set.
919 */
920 if(setter != null)
921 {
922 setter.invoke(obj, valArray);
923 }
924 else if (isDebugEnabled)
925 {
926 log.debug(name + ": has a null setter for the mapToProperty"
927 + " Attribute, although all Fields should be mapped"
928 + " to " + mapToObject + ". If this is unwanted, you"
929 + " should double check the mapToProperty Attribute, and"
930 + " consult the logs. The Turbine Intake Service will"
931 + " have logged a detailed Message with the error.");
932 }
933 }
934 catch (IllegalAccessException e)
935 {
936 throwSetGetException("setter", obj, this.getDisplayName(),
937 this.group.getIntakeGroupName(), e);
938 }
939 catch (IllegalArgumentException e)
940 {
941 throwSetGetException("setter", obj, this.getDisplayName(),
942 this.group.getIntakeGroupName(), e);
943 }
944 catch (InvocationTargetException e)
945 {
946 throwSetGetException("setter", obj, this.getDisplayName(),
947 this.group.getIntakeGroupName(), e);
948 }
949 }
950
951 /**
952 * Used to throw an IntakeException when an error occurs execuing the
953 * get/set method of the mapped persistent object.
954 *
955 * @param type Type of method. (setter/getter)
956 * @param fieldName Name of the field
957 * @param groupName Name of the group
958 * @param e Exception that was thrown
959 * @throws IntakeException New exception with formatted message
960 */
961 private void throwSetGetException(String type, Object obj,
962 String fieldName, String groupName,
963 Exception e)
964 throws IntakeException
965 {
966 throw new IntakeException("Could not execute " + type
967 + " method for " + fieldName + " in group " + groupName
968 + " on " + obj.getClass().getName(), e);
969
970 }
971
972 /**
973 * Get the default Value
974 *
975 * @return the default value
976 */
977 public Object getDefaultValue()
978 {
979 return defaultValue;
980 }
981
982 /**
983 * Get the Value to use if the field is empty
984 *
985 * @return the value to use if the field is empty.
986 */
987 public Object getEmptyValue()
988 {
989 return emptyValue;
990 }
991
992 /**
993 * Provides access to emptyValue such that the value returned will be
994 * acceptable as an argument parameter to Method.invoke. Subclasses
995 * that deal with primitive types should ensure that they return an
996 * appropriate value wrapped in the object wrapper class for the
997 * primitive type.
998 *
999 * @return the value to use when the field is empty or an Object that
1000 * wraps the empty value for primitive types.
1001 */
1002 protected Object getSafeEmptyValue()
1003 {
1004 return getEmptyValue();
1005 }
1006
1007 /**
1008 * Gets the name of the field.
1009 *
1010 * @return name of the field as specified in the XML file.
1011 */
1012 public String getName()
1013 {
1014 return name;
1015 }
1016
1017 /**
1018 * Gets the diplay size of the field. This is useful when
1019 * building the HTML input tag. If no displaySize was set,
1020 * an empty string is returned.
1021 */
1022 public String getDisplaySize()
1023 {
1024 return (StringUtils.isEmpty(displaySize) ? "" : displaySize);
1025 }
1026
1027 /**
1028 * Gets the maximum size of the field. This is useful when
1029 * building the HTML input tag. The maxSize is set with the maxLength
1030 * rule. If this rul was not set, an enmpty string is returned.
1031 */
1032 public String getMaxSize()
1033 {
1034 return (StringUtils.isEmpty(maxSize) ? "" : maxSize);
1035 }
1036
1037 /**
1038 * Gets the String representation of the Value. This is basically a wrapper
1039 * method for the toString method which doesn't seem to show anything on
1040 * screen if accessed from Template. Name is also more in line with getValue
1041 * method which returns the actual Object.
1042 * This is useful for displaying correctly formatted data such as dates,
1043 * such as 18/11/1968 instead of the toString dump of a Date Object.
1044 *
1045 * @return the String Value
1046 */
1047 public String getStringValue()
1048 {
1049 return this.toString();
1050 }
1051
1052 }