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