Coverage Report - org.kuali.rice.kns.datadictionary.AttributeDefinition
 
Classes in this File Line Coverage Branch Coverage Complexity
AttributeDefinition
0%
0/116
0%
0/32
1.404
 
 1  
 /*
 2  
  * Copyright 2005-2008 The Kuali Foundation
 3  
  * 
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  * 
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  * 
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 package org.kuali.rice.kns.datadictionary;
 18  
 
 19  
 import java.util.List;
 20  
 
 21  
 import org.apache.commons.lang.ClassUtils;
 22  
 import org.apache.commons.lang.StringUtils;
 23  
 import org.apache.log4j.Logger;
 24  
 import org.kuali.rice.core.util.ClassLoaderUtils;
 25  
 import org.kuali.rice.core.web.format.Formatter;
 26  
 import org.kuali.rice.kns.datadictionary.control.ControlDefinition;
 27  
 import org.kuali.rice.kns.datadictionary.exception.AttributeValidationException;
 28  
 import org.kuali.rice.kns.datadictionary.exception.ClassValidationException;
 29  
 import org.kuali.rice.kns.datadictionary.validation.DataType;
 30  
 import org.kuali.rice.kns.datadictionary.validation.ValidationPattern;
 31  
 import org.kuali.rice.kns.datadictionary.validation.capability.CaseConstrainable;
 32  
 import org.kuali.rice.kns.datadictionary.validation.capability.Formatable;
 33  
 import org.kuali.rice.kns.datadictionary.validation.capability.HierarchicallyConstrainable;
 34  
 import org.kuali.rice.kns.datadictionary.validation.capability.LengthConstrainable;
 35  
 import org.kuali.rice.kns.datadictionary.validation.capability.MustOccurConstrainable;
 36  
 import org.kuali.rice.kns.datadictionary.validation.capability.PrerequisiteConstrainable;
 37  
 import org.kuali.rice.kns.datadictionary.validation.capability.RangeConstrainable;
 38  
 import org.kuali.rice.kns.datadictionary.validation.capability.ValidCharactersConstrainable;
 39  
 import org.kuali.rice.kns.datadictionary.validation.constraint.CaseConstraint;
 40  
 import org.kuali.rice.kns.datadictionary.validation.constraint.LookupConstraint;
 41  
 import org.kuali.rice.kns.datadictionary.validation.constraint.MustOccurConstraint;
 42  
 import org.kuali.rice.kns.datadictionary.validation.constraint.PrerequisiteConstraint;
 43  
 import org.kuali.rice.kns.datadictionary.validation.constraint.ValidCharactersConstraint;
 44  
 import org.kuali.rice.kns.lookup.keyvalues.KeyValuesFinder;
 45  
 import org.kuali.rice.kns.uif.control.Control;
 46  
 import org.kuali.rice.kns.uif.core.BindingInfo;
 47  
 import org.kuali.rice.kns.util.ObjectUtils;
 48  
 
 49  
 /**
 50  
  * A single attribute definition in the DataDictionary, which contains
 51  
  * information relating to the display, validation, and general maintenance of a
 52  
  * specific attribute of an entry.
 53  
  * 
 54  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 55  
  */
 56  
 public class AttributeDefinition extends AttributeDefinitionBase implements CaseConstrainable, PrerequisiteConstrainable, Formatable, HierarchicallyConstrainable, MustOccurConstrainable, LengthConstrainable, RangeConstrainable, ValidCharactersConstrainable {
 57  
         private static final long serialVersionUID = -2490613377818442742L;
 58  
 
 59  0
         protected Boolean forceUppercase = Boolean.FALSE;
 60  
         
 61  
         protected DataType dataType;
 62  
         
 63  
         protected Integer minLength;
 64  
         protected Integer maxLength;
 65  
         protected Boolean unique;
 66  
 
 67  
         protected String exclusiveMin;
 68  
         protected String inclusiveMax;
 69  
 
 70  
         @Deprecated 
 71  
         protected ValidationPattern validationPattern;
 72  
 
 73  
         protected ControlDefinition control;
 74  
 
 75  
         // TODO: rename to control once ControlDefinition is removed
 76  
         protected Control controlField;
 77  
 
 78  
         protected String formatterClass;
 79  
 
 80  
         protected AttributeSecurity attributeSecurity;
 81  
         
 82  
         protected Boolean dynamic;
 83  
         
 84  
         // KS-style constraints 
 85  
         protected String customValidatorClass;
 86  
         protected ValidCharactersConstraint validCharactersConstraint;        
 87  
     protected CaseConstraint caseConstraint;
 88  
     protected List<PrerequisiteConstraint> dependencyConstraints;
 89  
         protected List<MustOccurConstraint> mustOccurConstraints;
 90  
         protected LookupConstraint lookupDefinition;// If the user wants to match
 91  
                 // against two searches, that search must be defined as  well
 92  
         protected String lookupContextPath;
 93  
         
 94  
         //TODO: This may not be required since we now use ComplexAttributeDefinition
 95  
         protected String childEntryName;
 96  
         
 97  
         private KeyValuesFinder optionsFinder;
 98  
 
 99  
         protected String alternateDisplayAttributeName;
 100  
     protected String additionalDisplayAttributeName;
 101  
     
 102  
 
 103  0
         public AttributeDefinition() {
 104  
                 // Empty
 105  0
         }
 106  
 
 107  
         /**
 108  
          * forceUppercase = convert user entry to uppercase and always display
 109  
          * database value as uppercase.
 110  
          */
 111  
         public void setForceUppercase(Boolean forceUppercase) {
 112  0
                 this.forceUppercase = forceUppercase;
 113  0
         }
 114  
 
 115  
         public Boolean getForceUppercase() {
 116  0
                 return this.forceUppercase;
 117  
         }
 118  
 
 119  
         @Override
 120  
         public Integer getMaxLength() {
 121  0
                 return maxLength;
 122  
         }
 123  
 
 124  
         /**
 125  
          * The maxLength element determines the maximum size of the field for data
 126  
          * entry edit purposes and for display purposes.
 127  
          */
 128  
         public void setMaxLength(Integer maxLength) {
 129  0
                 this.maxLength = maxLength;
 130  0
         }
 131  
 
 132  
         @Override
 133  
         public String getExclusiveMin() {
 134  0
                 return exclusiveMin;
 135  
         }
 136  
 
 137  
         /**
 138  
          * The exclusiveMin element determines the minimum allowable value for data
 139  
          * entry editing purposes. Value can be an integer or decimal value such as
 140  
          * -.001 or 99.
 141  
          */
 142  
         public void setExclusiveMin(String exclusiveMin) {
 143  0
                 this.exclusiveMin = exclusiveMin;
 144  0
         }
 145  
 
 146  
         /**
 147  
          * The inclusiveMax element determines the maximum allowable value for data
 148  
          * entry editing purposes. Value can be an integer or decimal value such as
 149  
          * -.001 or 99.
 150  
          * 
 151  
          * JSTL: This field is mapped into the field named "exclusiveMax".
 152  
          */
 153  
         @Override
 154  
         public String getInclusiveMax() {
 155  0
                 return inclusiveMax;
 156  
         }
 157  
 
 158  
         /**
 159  
          * The inclusiveMax element determines the maximum allowable value for data
 160  
          * entry editing purposes. Value can be an integer or decimal value such as
 161  
          * -.001 or 99.
 162  
          * 
 163  
          * JSTL: This field is mapped into the field named "exclusiveMax".
 164  
          */
 165  
         public void setInclusiveMax(String inclusiveMax) {
 166  0
                 this.inclusiveMax = inclusiveMax;
 167  0
         }
 168  
 
 169  
         /**
 170  
          * @return true if a validationPattern has been set
 171  
          */
 172  
         public boolean hasValidationPattern() {
 173  0
                 return (validationPattern != null);
 174  
         }
 175  
 
 176  
         public ValidationPattern getValidationPattern() {
 177  0
                 return this.validationPattern;
 178  
         }
 179  
 
 180  
         /**
 181  
          * The validationPattern element defines the allowable character-level or
 182  
          * field-level values for an attribute.
 183  
          * 
 184  
          * JSTL: validationPattern is a Map which is accessed using a key of
 185  
          * "validationPattern". Each entry may contain some of the keys listed
 186  
          * below. The keys that may be present for a given attribute are dependent
 187  
          * upon the type of validationPattern.
 188  
          * 
 189  
          * maxLength (String) exactLength type allowWhitespace allowUnderscore
 190  
          * allowPeriod validChars precision scale allowNegative
 191  
          * 
 192  
          * The allowable keys (in addition to type) for each type are: Type****
 193  
          * ***Keys*** alphanumeric exactLength maxLength allowWhitespace
 194  
          * allowUnderscore allowPeriod
 195  
          * 
 196  
          * alpha exactLength maxLength allowWhitespace
 197  
          * 
 198  
          * anyCharacter exactLength maxLength allowWhitespace
 199  
          * 
 200  
          * charset validChars
 201  
          * 
 202  
          * numeric exactLength maxLength
 203  
          * 
 204  
          * fixedPoint allowNegative precision scale
 205  
          * 
 206  
          * floatingPoint allowNegative
 207  
          * 
 208  
          * date n/a emailAddress n/a javaClass n/a month n/a phoneNumber n/a
 209  
          * timestamp n/a year n/a zipcode n/a
 210  
          * 
 211  
          * Note: maxLength and exactLength are mutually exclusive. If one is
 212  
          * entered, the other may not be entered.
 213  
          * 
 214  
          * Note: See ApplicationResources.properties for exact regex patterns. e.g.
 215  
          * validationPatternRegex.date for regex used in date validation.
 216  
          */
 217  
         public void setValidationPattern(ValidationPattern validationPattern) {
 218  0
                 this.validationPattern = validationPattern;
 219  
                 
 220  
                 // FIXME: JLR - need to recreate this functionality using the ValidCharsConstraint logic
 221  0
         }
 222  
 
 223  
 
 224  
         /**
 225  
          * @return control
 226  
          */
 227  
         public ControlDefinition getControl() {
 228  0
                 return control;
 229  
         }
 230  
 
 231  
         /**
 232  
          * The control element defines the manner in which an attribute is displayed
 233  
          * and the manner in which the attribute value is entered.
 234  
          * 
 235  
          * JSTL: control is a Map representing an HTML control. It is accessed using
 236  
          * a key of "control". The table below shows the types of entries associated
 237  
          * with each type of control.
 238  
          * 
 239  
          ** Control Type** **Key** **Value** checkbox checkbox boolean String
 240  
          * 
 241  
          * hidden hidden boolean String
 242  
          * 
 243  
          * radio radio boolean String valuesFinder valuesFinder class name
 244  
          * businessObjectClass String keyAttribute String labelAttribute String
 245  
          * includeKeyInLabel boolean String
 246  
          * 
 247  
          * select select boolean String valuesFinder valuesFinder class name
 248  
          * businessObjectClass String keyAttribute String labelAttribute String
 249  
          * includeBlankRow boolean String includeKeyInLabel boolean String
 250  
          * 
 251  
          * apcSelect apcSelect boolean String paramNamespace String
 252  
          * parameterDetailType String parameterName String
 253  
          * 
 254  
          * text text boolean String size String
 255  
          * 
 256  
          * textarea textarea boolean String rows cols
 257  
          * 
 258  
          * currency currency boolean String size String formattedMaxLength String
 259  
          * 
 260  
          * kualiUser kualiUser boolean String universalIdAttributeName String
 261  
          * userIdAttributeName String personNameAttributeName String
 262  
          * 
 263  
          * lookupHidden lookupHidden boolean String
 264  
          * 
 265  
          * lookupReadonly lookupReadonly boolean String
 266  
          * 
 267  
          * @param control
 268  
          * @throws IllegalArgumentException
 269  
          *             if the given control is null
 270  
          */
 271  
         public void setControl(ControlDefinition control) {
 272  0
                 if (control == null) {
 273  0
                         throw new IllegalArgumentException("invalid (null) control");
 274  
                 }
 275  0
                 this.control = control;
 276  0
         }
 277  
 
 278  
         public boolean hasFormatterClass() {
 279  0
                 return (formatterClass != null);
 280  
         }
 281  
 
 282  
         @Override
 283  
         public String getFormatterClass() {
 284  0
                 return formatterClass;
 285  
         }
 286  
 
 287  
         /**
 288  
          * The formatterClass element is used when custom formatting is required for
 289  
          * display of the field value. This field specifies the name of the java
 290  
          * class to be used for the formatting. About 15 different classes are
 291  
          * available including BooleanFormatter, CurrencyFormatter, DateFormatter,
 292  
          * etc.
 293  
          */
 294  
         public void setFormatterClass(String formatterClass) {
 295  0
                 if (formatterClass == null) {
 296  0
                         throw new IllegalArgumentException("invalid (null) formatterClass");
 297  
                 }
 298  0
                 this.formatterClass = formatterClass;
 299  0
         }
 300  
 
 301  
         /**
 302  
          * Directly validate simple fields, call completeValidation on Definition
 303  
          * fields.
 304  
          * 
 305  
          * @see org.kuali.rice.kns.datadictionary.DataDictionaryEntry#completeValidation()
 306  
          */
 307  
         @Override
 308  
         public void completeValidation(Class<?> rootObjectClass, Class<?> otherObjectClass) {
 309  
                 try {
 310  0
                         if (!DataDictionary.isPropertyOf(rootObjectClass, getName())) {
 311  0
                                 throw new AttributeValidationException("property '" + getName() + "' is not a property of class '"
 312  
                                                 + rootObjectClass.getName() + "' (" + "" + ")");
 313  
                         }
 314  
 
 315  
                         //TODO currently requiring a control or controlField, but this should not be case (AttrField should probably do the check)
 316  0
                         if (getControl() == null && getControlField() == null) {
 317  0
                                 throw new AttributeValidationException("property '" + getName() + "' in class '"
 318  
                                                 + rootObjectClass.getName() + " does not have a control defined");
 319  
                         }
 320  
                         
 321  0
                         if(getControl() != null) {
 322  0
                             getControl().completeValidation(rootObjectClass, otherObjectClass);
 323  
                         }
 324  
 
 325  0
                         if (attributeSecurity != null) {
 326  0
                                 attributeSecurity.completeValidation(rootObjectClass, otherObjectClass);
 327  
                         }
 328  
 
 329  0
                         if (validationPattern != null) {
 330  0
                                 validationPattern.completeValidation();
 331  
                         }
 332  
 
 333  0
                         if (formatterClass != null) {
 334  
                                 try {
 335  0
                                         Class formatterClassObject = ClassUtils.getClass(ClassLoaderUtils.getDefaultClassLoader(),
 336  
                                                         getFormatterClass());
 337  0
                                         if (!Formatter.class.isAssignableFrom(formatterClassObject)) {
 338  0
                                                 throw new ClassValidationException("formatterClass is not a valid instance of "
 339  
                                                                 + Formatter.class.getName() + " instead was: " + formatterClassObject.getName());
 340  
                                         }
 341  
                                 }
 342  0
                                 catch (ClassNotFoundException e) {
 343  0
                                         throw new ClassValidationException("formatterClass could not be found: " + getFormatterClass(), e);
 344  0
                                 }
 345  
                         }
 346  
                 }
 347  0
                 catch (RuntimeException ex) {
 348  0
                         Logger.getLogger(getClass()).error(
 349  
                                         "Unable to validate attribute " + rootObjectClass + "." + getName() + ": " + ex.getMessage(), ex);
 350  0
                         throw ex;
 351  0
                 }
 352  0
         }
 353  
 
 354  
         /**
 355  
          * @see java.lang.Object#toString()
 356  
          */
 357  
         @Override
 358  
         public String toString() {
 359  0
                 return "AttributeDefinition for attribute " + getName();
 360  
         }
 361  
 
 362  
         /**
 363  
          * @return the attributeSecurity
 364  
          */
 365  
         public AttributeSecurity getAttributeSecurity() {
 366  0
                 return this.attributeSecurity;
 367  
         }
 368  
 
 369  
         /**
 370  
          * @param attributeSecurity
 371  
          *            the attributeSecurity to set
 372  
          */
 373  
         public void setAttributeSecurity(AttributeSecurity attributeSecurity) {
 374  0
                 this.attributeSecurity = attributeSecurity;
 375  0
         }
 376  
 
 377  
         public boolean hasAttributeSecurity() {
 378  0
                 return (attributeSecurity != null);
 379  
         }
 380  
 
 381  
         /**
 382  
          * This overridden method ...
 383  
          * 
 384  
          * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
 385  
          */
 386  
         @Override
 387  
         public void afterPropertiesSet() throws Exception {
 388  0
                 if (StringUtils.isEmpty(name)) {
 389  0
                         throw new RuntimeException("blank name for bean: " + id);
 390  
                 }
 391  
 
 392  0
                 if (validationPattern != null) {
 393  0
                         if (validCharactersConstraint == null) {
 394  0
                                 validCharactersConstraint = new ValidCharactersConstraint();
 395  
                         }
 396  
                         
 397  0
                         validCharactersConstraint.setValue(new StringBuilder().append(validationPattern.getRegexPattern()).toString());
 398  
                 }
 399  0
         }
 400  
 
 401  
         /**
 402  
          * @return the unique
 403  
          */
 404  
         public Boolean getUnique() {
 405  0
                 return this.unique;
 406  
         }
 407  
 
 408  
         /**
 409  
          * @param unique
 410  
          *            the unique to set
 411  
          */
 412  
         public void setUnique(Boolean unique) {
 413  0
                 this.unique = unique;
 414  0
         }
 415  
 
 416  
         /**
 417  
          * Default <code>Control</code> to use when the attribute is to be rendered
 418  
          * for the UI. Used by the UIF when a control is not defined for an
 419  
          * <code>AttributeField</code>
 420  
          * 
 421  
          * @return Control instance
 422  
          */
 423  
         public Control getControlField() {
 424  0
                 return this.controlField;
 425  
         }
 426  
 
 427  
         /**
 428  
          * Setter for the default control
 429  
          * 
 430  
          * @param controlField
 431  
          */
 432  
         public void setControlField(Control controlField) {
 433  0
                 this.controlField = controlField;
 434  0
         }
 435  
 
 436  
         /**
 437  
          * @return the minLength
 438  
          */
 439  
         public Integer getMinLength() {
 440  0
                 return this.minLength;
 441  
         }
 442  
 
 443  
         /**
 444  
          * @param minLength the minLength to set
 445  
          */
 446  
         public void setMinLength(Integer minLength) {
 447  0
                 this.minLength = minLength;
 448  0
         }
 449  
 
 450  
         /**
 451  
          * @return the dataType
 452  
          */
 453  
         @Override
 454  
         public DataType getDataType() {
 455  0
                 return this.dataType;
 456  
         }
 457  
 
 458  
         /**
 459  
          * @param dataType the dataType to set
 460  
          */
 461  
         public void setDataType(DataType dataType) {
 462  0
                 this.dataType = dataType;
 463  0
         }
 464  
         
 465  
         public void setDataType(String dataType) {
 466  0
                 this.dataType = DataType.valueOf(dataType);
 467  0
         }
 468  
 
 469  
         /**
 470  
          * @return the customValidatorClass
 471  
          */
 472  
         public String getCustomValidatorClass() {
 473  0
                 return this.customValidatorClass;
 474  
         }
 475  
 
 476  
         /**
 477  
          * @param customValidatorClass the customValidatorClass to set
 478  
          */
 479  
         public void setCustomValidatorClass(String customValidatorClass) {
 480  0
                 this.customValidatorClass = customValidatorClass;
 481  0
         }
 482  
 
 483  
         /**
 484  
          * @return the validChars
 485  
          */
 486  
         @Override
 487  
         public ValidCharactersConstraint getValidCharactersConstraint() {
 488  0
                 return this.validCharactersConstraint;
 489  
         }
 490  
 
 491  
         /**
 492  
          * @param validCharactersConstraint the validChars to set
 493  
          */
 494  
         public void setValidCharactersConstraint(ValidCharactersConstraint validCharactersConstraint) {
 495  0
                 this.validCharactersConstraint = validCharactersConstraint;
 496  0
         }
 497  
 
 498  
         /**
 499  
          * @return the caseConstraint
 500  
          */
 501  
         @Override
 502  
         public CaseConstraint getCaseConstraint() {
 503  0
                 return this.caseConstraint;
 504  
         }
 505  
 
 506  
         /**
 507  
          * @param caseConstraint the caseConstraint to set
 508  
          */
 509  
         public void setCaseConstraint(CaseConstraint caseConstraint) {
 510  0
                 this.caseConstraint = caseConstraint;
 511  0
         }
 512  
 
 513  
         /**
 514  
          * @return the requireConstraint
 515  
          */
 516  
         @Override
 517  
         public List<PrerequisiteConstraint> getPrerequisiteConstraints() {
 518  0
                 return this.dependencyConstraints;
 519  
         }
 520  
 
 521  
         /**
 522  
          * @param dependencyConstraints the requireConstraint to set
 523  
          */
 524  
         public void setPrerequisiteConstraints(List<PrerequisiteConstraint> dependencyConstraints) {
 525  0
                 this.dependencyConstraints = dependencyConstraints;
 526  0
         }
 527  
 
 528  
         /**
 529  
          * @return the occursConstraint
 530  
          */
 531  
         @Override
 532  
         public List<MustOccurConstraint> getMustOccurConstraints() {
 533  0
                 return this.mustOccurConstraints;
 534  
         }
 535  
 
 536  
         /**
 537  
          * @param mustOccurConstraints the occursConstraint to set
 538  
          */
 539  
         public void setMustOccurConstraints(List<MustOccurConstraint> mustOccurConstraints) {
 540  0
                 this.mustOccurConstraints = mustOccurConstraints;
 541  0
         }
 542  
 
 543  
         /**
 544  
          * @return the lookupDefinition
 545  
          */
 546  
         public LookupConstraint getLookupDefinition() {
 547  0
                 return this.lookupDefinition;
 548  
         }
 549  
 
 550  
         /**
 551  
          * @param lookupDefinition the lookupDefinition to set
 552  
          */
 553  
         public void setLookupDefinition(LookupConstraint lookupDefinition) {
 554  0
                 this.lookupDefinition = lookupDefinition;
 555  0
         }
 556  
 
 557  
         /**
 558  
          * @return the lookupContextPath
 559  
          */
 560  
         public String getLookupContextPath() {
 561  0
                 return this.lookupContextPath;
 562  
         }
 563  
 
 564  
         /**
 565  
          * @param lookupContextPath the lookupContextPath to set
 566  
          */
 567  
         public void setLookupContextPath(String lookupContextPath) {
 568  0
                 this.lookupContextPath = lookupContextPath;
 569  0
         }
 570  
 
 571  
         /**
 572  
          * @return the childEntryName
 573  
          */
 574  
         public String getChildEntryName() {
 575  0
                 return this.childEntryName;
 576  
         }
 577  
 
 578  
         /**
 579  
          * @param childEntryName the childEntryName to set
 580  
          */
 581  
         public void setChildEntryName(String childEntryName) {
 582  0
                 this.childEntryName = childEntryName;
 583  0
         }
 584  
 
 585  
         /**
 586  
          * @return the constraintMessage
 587  
          */
 588  
         public String getConstraint() {
 589  0
                 return this.constraint;
 590  
         }
 591  
 
 592  
         /**
 593  
          * @param constraintMessage the constraintMessage to set
 594  
          */
 595  
         public void setConstraint(String constraint) {
 596  0
                 this.constraint = constraint;
 597  0
         }
 598  
         
 599  
     /**
 600  
      * Instance of <code>KeyValluesFinder</code> that should be invoked to
 601  
      * provide a List of values the field can have. Generally used to provide
 602  
      * the options for a multi-value control or to validate the submitted field
 603  
      * value
 604  
      * 
 605  
      * @return KeyValuesFinder instance
 606  
      */
 607  
     public KeyValuesFinder getOptionsFinder() {
 608  0
         return this.optionsFinder;
 609  
     }
 610  
 
 611  
     /**
 612  
      * Setter for the field's KeyValuesFinder instance
 613  
      * 
 614  
      * @param optionsFinder
 615  
      */
 616  
     public void setOptionsFinder(KeyValuesFinder optionsFinder) {
 617  0
         this.optionsFinder = optionsFinder;
 618  0
     }
 619  
     
 620  
     /**
 621  
      * Setter that takes in the class name for the options finder and creates a
 622  
      * new instance to use as the finder for the attribute field
 623  
      * 
 624  
      * @param optionsFinderClass
 625  
      */
 626  
     public void setOptionsFinderClass(Class<? extends KeyValuesFinder> optionsFinderClass) {
 627  0
         this.optionsFinder = ObjectUtils.newInstance(optionsFinderClass);
 628  0
     }
 629  
         
 630  
         public void setAdditionalDisplayAttributeName(String additionalDisplayAttributeName) {
 631  0
                 this.additionalDisplayAttributeName = additionalDisplayAttributeName;
 632  0
         }
 633  
         
 634  
         public String getAdditionalDisplayAttributeName() {
 635  0
                 return this.additionalDisplayAttributeName;
 636  
         }
 637  
 
 638  
         public void setAlternateDisplayAttributeName(String alternateDisplayAttributeName) {
 639  0
                 this.alternateDisplayAttributeName = alternateDisplayAttributeName;
 640  0
         }
 641  
         
 642  
         public String getAlternateDisplayAttributeName() {
 643  0
                 return this.alternateDisplayAttributeName;
 644  
         }
 645  
 
 646  
 }