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 }