View Javadoc

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