View Javadoc
1   /**
2    * Copyright 2005-2014 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  package org.kuali.rice.krad.datadictionary;
17  
18  import java.beans.PropertyEditor;
19  import java.util.List;
20  
21  import org.apache.commons.lang.ClassUtils;
22  import org.apache.commons.lang.StringUtils;
23  import org.kuali.rice.core.api.data.DataType;
24  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
25  import org.kuali.rice.core.api.util.ClassLoaderUtils;
26  import org.kuali.rice.core.web.format.Formatter;
27  import org.kuali.rice.krad.datadictionary.control.ControlDefinition;
28  import org.kuali.rice.krad.datadictionary.mask.MaskFormatterLiteral;
29  import org.kuali.rice.krad.datadictionary.parse.BeanTag;
30  import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
31  import org.kuali.rice.krad.datadictionary.validation.ValidationPattern;
32  import org.kuali.rice.krad.datadictionary.validation.capability.CaseConstrainable;
33  import org.kuali.rice.krad.datadictionary.validation.capability.Formatable;
34  import org.kuali.rice.krad.datadictionary.validation.capability.HierarchicallyConstrainable;
35  import org.kuali.rice.krad.datadictionary.validation.capability.MustOccurConstrainable;
36  import org.kuali.rice.krad.datadictionary.validation.capability.PrerequisiteConstrainable;
37  import org.kuali.rice.krad.datadictionary.validation.capability.ValidCharactersConstrainable;
38  import org.kuali.rice.krad.datadictionary.validation.constraint.CaseConstraint;
39  import org.kuali.rice.krad.datadictionary.validation.constraint.MustOccurConstraint;
40  import org.kuali.rice.krad.datadictionary.validation.constraint.PrerequisiteConstraint;
41  import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint;
42  import org.kuali.rice.krad.datadictionary.validator.ValidationTrace;
43  import org.kuali.rice.krad.keyvalues.KeyValuesFinder;
44  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
45  import org.kuali.rice.krad.uif.control.Control;
46  import org.kuali.rice.krad.util.KRADUtils;
47  
48  /**
49   * A single attribute definition in the DataDictionary, which contains
50   * information relating to the display, validation, and general maintenance of a
51   * specific attribute of an entry.
52   *
53   * @author Kuali Rice Team (rice.collab@kuali.org)
54   */
55  @BeanTag(name = "attributeDefinition-bean")
56  public class AttributeDefinition extends AttributeDefinitionBase implements CaseConstrainable, PrerequisiteConstrainable, Formatable, HierarchicallyConstrainable, MustOccurConstrainable, ValidCharactersConstrainable {
57      private static final long serialVersionUID = -2490613377818442742L;
58      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AttributeDefinition.class);
59  
60      protected Boolean forceUppercase;
61  
62      protected Boolean unique;
63  
64      //These are deprecated DO NOT USE with new KRAD implementations
65      @Deprecated
66      protected ValidationPattern validationPattern;
67  
68      @Deprecated
69      protected ControlDefinition control;
70  
71      // TODO: rename to control once ControlDefinition is removed
72      protected Control controlField;
73      protected Control cachedDerivedControl = null;
74  
75      @Deprecated
76      protected String formatterClass;
77      protected PropertyEditor propertyEditor;
78  
79      protected AttributeSecurity attributeSecurity;
80  
81      protected Boolean dynamic;
82  
83      // KRAD constraints
84      protected String customValidatorClass;
85      protected ValidCharactersConstraint validCharactersConstraint;
86      protected CaseConstraint caseConstraint;
87      protected List<PrerequisiteConstraint> dependencyConstraints;
88      protected List<MustOccurConstraint> mustOccurConstraints;
89  
90      //TODO: This may not be required since we now use ComplexAttributeDefinition
91      protected String childEntryName;
92  
93      private KeyValuesFinder optionsFinder;
94  
95      protected String alternateDisplayAttributeName;
96      protected String additionalDisplayAttributeName;
97  
98      public AttributeDefinition() {
99          super();
100     }
101 
102     /**
103      * Setter for force upper case
104      *
105      * @param forceUppercase
106      */
107     public void setForceUppercase(Boolean forceUppercase) {
108         this.forceUppercase = forceUppercase;
109     }
110 
111     /**
112      * Indicates whether user entry should be converted to upper case
113      *
114      * <p>
115      * If set all user input will be changed to uppercase. Values from the database will also be forced to display
116      * as upper case and thus be persisted as upper case.
117      * </p>
118      *
119      * If not set and embedded metadata is present, the ForceUppercase value will be read from the linked metadata.
120      *
121      * @return boolean true if force upper case is set
122      */
123     @BeanTagAttribute(name = "forceUppercase")
124     public Boolean getForceUppercase() {
125         if ( forceUppercase != null ) {
126             return forceUppercase;
127         }
128         if ( getDataObjectAttribute() != null ) {
129             return getDataObjectAttribute().isForceUppercase();
130         }
131         return Boolean.FALSE;
132     }
133 
134     /**
135      * Returns the maximum length for this field, if set.  If not set, it attempts to pull from
136      * the embedded metadata, if any.
137      *z
138      * @see org.kuali.rice.krad.datadictionary.validation.constraint.LengthConstraint#getMaxLength()
139      */
140     @BeanTagAttribute(name = "maxLength")
141     public Integer getMaxLength() {
142         if ( getSimpleConstraint().getMaxLength() != null ) {
143             return getSimpleConstraint().getMaxLength();
144         }
145         if ( getDataObjectAttribute() != null ) {
146             if ( getDataObjectAttribute().getMaxLength() != null ) {
147                 return new Integer( getDataObjectAttribute().getMaxLength().intValue() );
148             }
149         }
150         return null;
151     }
152 
153     /**
154      * Setter for maximum length
155      *
156      * @param maxLength
157      */
158     public void setMaxLength(Integer maxLength) {
159         this.getSimpleConstraint().setMaxLength(maxLength);
160     }
161 
162     /**
163      * @see org.kuali.rice.krad.datadictionary.validation.constraint.RangeConstraint#getExclusiveMin()
164      */
165     @BeanTagAttribute(name = "exclusiveMin")
166     public String getExclusiveMin() {
167         return this.getSimpleConstraint().getExclusiveMin();
168     }
169 
170     /**
171      * Setter for minimum value
172      *
173      * @param exclusiveMin - minimum allowed value
174      */
175     public void setExclusiveMin(String exclusiveMin) {
176         this.getSimpleConstraint().setExclusiveMin(exclusiveMin);
177     }
178 
179     /**
180      * @see org.kuali.rice.krad.datadictionary.validation.constraint.RangeConstraint#getInclusiveMax()
181      */
182     @BeanTagAttribute(name = "inclusiveMax")
183     public String getInclusiveMax() {
184         return this.getSimpleConstraint().getInclusiveMax();
185     }
186 
187     /**
188      * Setter for maximum value
189      *
190      * @param inclusiveMax - max allowed value
191      */
192     public void setInclusiveMax(String inclusiveMax) {
193         this.getSimpleConstraint().setInclusiveMax(inclusiveMax);
194     }
195 
196     /**
197      * The validationPattern element defines the allowable character-level or
198      * field-level values for an attribute.
199      *
200      * JSTL: validationPattern is a Map which is accessed using a key of
201      * "validationPattern". Each entry may contain some of the keys listed
202      * below. The keys that may be present for a given attribute are dependent
203      * upon the type of validationPattern.
204      *
205      * maxLength (String) exactLength type allowWhitespace allowUnderscore
206      * allowPeriod validChars precision scale allowNegative
207      *
208      * The allowable keys (in addition to type) for each type are: Type****
209      * ***Keys*** alphanumeric exactLength maxLength allowWhitespace
210      * allowUnderscore allowPeriod
211      *
212      * alpha exactLength maxLength allowWhitespace
213      *
214      * anyCharacter exactLength maxLength allowWhitespace
215      *
216      * charset validChars
217      *
218      * numeric exactLength maxLength
219      *
220      * fixedPoint allowNegative precision scale
221      *
222      * floatingPoint allowNegative
223      *
224      * date n/a emailAddress n/a javaClass n/a month n/a phoneNumber n/a
225      * timestamp n/a year n/a zipcode n/a
226      *
227      * Note: maxLength and exactLength are mutually exclusive. If one is
228      * entered, the other may not be entered.
229      *
230      * Note: See ApplicationResources.properties for exact regex patterns. e.g.
231      * validationPatternRegex.date for regex used in date validation.
232      */
233     @Deprecated
234     public void setValidationPattern(ValidationPattern validationPattern) {
235         this.validationPattern = validationPattern;
236     }
237 
238     /**
239      * Indicates whether a validation pattern has been set
240      * @return boolean
241      */
242     @Deprecated
243     public boolean hasValidationPattern() {
244         return (validationPattern != null);
245     }
246 
247     /**
248      * Defines the allowable character-level or
249      * field-level values for an attribute
250      *
251      * <p>
252      * ValidationPattern is a Map which is accessed using a key of "validationPattern". Each entry may contain
253      * some of the keys listed below. The keys that may be present for a given attribute are dependent
254      * upon the type of validationPattern.
255      *
256      * maxLength (String) exactLength type allowWhitespace allowUnderscore
257      * allowPeriod validChars precision scale allowNegative
258      *
259      * The allowable keys (in addition to type) for each type are: Type****
260      * ***Keys*** alphanumeric exactLength maxLength allowWhitespace
261      * allowUnderscore allowPeriod
262      *
263      * alpha exactLength maxLength allowWhitespace
264      *
265      * anyCharacter exactLength maxLength allowWhitespace
266      *
267      * charset validChars
268      *
269      * numeric exactLength maxLength
270      *
271      * fixedPoint allowNegative precision scale
272      *
273      * floatingPoint allowNegative
274      *
275      * date n/a emailAddress n/a javaClass n/a month n/a phoneNumber n/a
276      * timestamp n/a year n/a zipcode n/a
277      *
278      * Note: maxLength and exactLength are mutually exclusive. If one is
279      * entered, the other may not be entered.
280      *
281      * Note: See ApplicationResources.properties for exact regex patterns. e.g.
282      * validationPatternRegex.date for regex used in date validation.
283      * </p>
284      *
285      * @return ValidationPattern
286      */
287     @Deprecated
288     public ValidationPattern getValidationPattern() {
289         return this.validationPattern;
290     }
291 
292     /**
293      * @return control
294      */
295     @BeanTagAttribute(name = "oldControl", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
296     @Deprecated
297     public ControlDefinition getControl() {
298         return control;
299     }
300 
301     /**
302      * The control element defines the manner in which an attribute is displayed
303      * and the manner in which the attribute value is entered.
304      *
305      * JSTL: control is a Map representing an HTML control. It is accessed using
306      * a key of "control". The table below shows the types of entries associated
307      * with each type of control.
308      *
309      * * Control Type** **Key** **Value** checkbox checkbox boolean String
310      *
311      * hidden hidden boolean String
312      *
313      * radio radio boolean String valuesFinder valuesFinder class name
314      * dataObjectClass String keyAttribute String labelAttribute String
315      * includeKeyInLabel boolean String
316      *
317      * select select boolean String valuesFinder valuesFinder class name
318      * dataObjectClass String keyAttribute String labelAttribute String
319      * includeBlankRow boolean String includeKeyInLabel boolean String
320      *
321      * apcSelect apcSelect boolean String paramNamespace String
322      * parameterDetailType String parameterName String
323      *
324      * text text boolean String size String
325      *
326      * textarea textarea boolean String rows cols
327      *
328      * currency currency boolean String size String formattedMaxLength String
329      *
330      * kualiUser kualiUser boolean String universalIdAttributeName String
331      * userIdAttributeName String personNameAttributeName String
332      *
333      * lookupHidden lookupHidden boolean String
334      *
335      * lookupReadonly lookupReadonly boolean String
336      *
337      * @param control
338      * @throws IllegalArgumentException if the given control is null
339      */
340     @Deprecated
341     public void setControl(ControlDefinition control) {
342         if (control == null) {
343             throw new IllegalArgumentException("invalid (null) control");
344         }
345         this.control = control;
346     }
347 
348     @Deprecated
349     public boolean hasFormatterClass() {
350         return (formatterClass != null);
351     }
352 
353     @Override
354     @BeanTagAttribute(name = "formatterClass")
355     @Deprecated
356     public String getFormatterClass() {
357         return formatterClass;
358     }
359 
360     /**
361      * The formatterClass element is used when custom formatting is required for
362      * display of the field value. This field specifies the name of the java
363      * class to be used for the formatting. About 15 different classes are
364      * available including BooleanFormatter, CurrencyFormatter, DateFormatter,
365      * etc.
366      */
367     @Deprecated
368     public void setFormatterClass(String formatterClass) {
369         if (formatterClass == null) {
370             throw new IllegalArgumentException("invalid (null) formatterClass");
371         }
372         this.formatterClass = formatterClass;
373     }
374 
375     /**
376      * Performs formatting of the field value for display and then converting the value back to its
377      * expected type from a string.
378      *
379      * If not set in the AttributeDefinition, it attempts to pull from the embedded metadata, if any.
380      *
381      * <p>
382      * Note property editors exist and are already registered for the basic Java types and the
383      * common Kuali types such as [@link KualiDecimal}. Registration with this property is only
384      * needed for custom property editors
385      * </p>
386      *
387      * @return PropertyEditor property editor instance to use for this field
388      */
389     @BeanTagAttribute(name = "propertyEditor", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
390     public PropertyEditor getPropertyEditor() {
391         if ( propertyEditor != null ) {
392             return propertyEditor;
393         }
394         if ( getDataObjectAttribute() != null ) {
395             return getDataObjectAttribute().getPropertyEditor();
396         }
397         return null;
398     }
399 
400     /**
401      * Setter for the custom property editor to use for the field
402      *
403      * @param propertyEditor
404      */
405     public void setPropertyEditor(PropertyEditor propertyEditor) {
406         this.propertyEditor = propertyEditor;
407     }
408 
409     /**
410      * Convenience setter for configuring a property editor by class
411      *
412      * @param propertyEditorClass
413      */
414     public void setPropertyEditorClass(Class<? extends PropertyEditor> propertyEditorClass) {
415         this.propertyEditor = KRADUtils.createNewObjectFromClass(propertyEditorClass);
416     }
417 
418     /**
419      * This overridden method ...
420      *
421      * @see org.kuali.rice.krad.datadictionary.DictionaryBeanBase#dataDictionaryPostProcessing()
422      */
423     @Override
424     public void dataDictionaryPostProcessing() {
425         super.dataDictionaryPostProcessing();
426         if ( getAttributeSecurity() != null ) {
427             getAttributeSecurity().dataDictionaryPostProcessing();
428         }
429     }
430 
431     /**
432      * Directly validate simple fields, call completeValidation on Definition
433      * fields.
434      *
435      * @see org.kuali.rice.krad.datadictionary.DataDictionaryEntry#completeValidation()
436      */
437     @Override
438     @Deprecated
439     public void completeValidation(Class<?> rootObjectClass, Class<?> otherObjectClass) {
440         completeValidation(rootObjectClass, otherObjectClass, new ValidationTrace());
441     }
442 
443     /**
444      * Directly validate simple fields, call completeValidation on Definition
445      * fields.
446      *
447      * @see org.kuali.rice.krad.datadictionary.DataDictionaryEntry#completeValidation(org.kuali.rice.krad.datadictionary.validator.ValidationTrace)
448      */
449     @Override
450     public void completeValidation(Class rootObjectClass, Class otherObjectClass, ValidationTrace tracer) {
451         tracer.addBean(this.getClass().getSimpleName(), "id: " + getId());
452         try {
453             if (StringUtils.isBlank(getName())) {
454                 String currentValues[] = {"id = " + getId(), "class = " + rootObjectClass.getName()};
455                 tracer.createError("AttributeDefinition missing name", currentValues);
456             }
457             if (!DataDictionary.isPropertyOf(rootObjectClass, getName())) {
458                 String currentValues[] = {"property = " + getName(), "class = " + rootObjectClass.getName()};
459                 tracer.createError("Property is not found in class. Ensure that the property is defined on the class and that there is at least a public 'getter' for it.", currentValues);
460             }
461 
462             if (getControl() == null && getControlField() == null) {
463                 String currentValues[] = {"property = " + getName(), "class = " + rootObjectClass.getName()};
464                 tracer.createError("Property does not have a control defined in the class", currentValues);
465             }
466 
467             if (getAttributeSecurity() != null) {
468                 getAttributeSecurity().completeValidation(rootObjectClass, otherObjectClass, tracer.getCopy());
469             }
470 
471             // KNS Controls - do not use KRAD Validation style
472             if (getControl() != null) {
473                 getControl().completeValidation(rootObjectClass, otherObjectClass);
474             }
475             if (validationPattern != null) {
476                  validationPattern.completeValidation();
477             }
478 
479             if (getFormatterClass() != null) {
480                 try {
481                     Class formatterClassObject = ClassUtils.getClass(ClassLoaderUtils.getDefaultClassLoader(),
482                             getFormatterClass());
483                     if (!Formatter.class.isAssignableFrom(formatterClassObject)) {
484                         String currentValues[] = {"formatterClassObject = " + formatterClassObject.getName()};
485                         tracer.createError("FormatterClass is not a valid instance", currentValues);
486                     }
487                 } catch (ClassNotFoundException e) {
488                     String currentValues[] = {"class = " + getFormatterClass()};
489                     tracer.createError("FormatterClass could not be found", currentValues);
490                 }
491             }
492         } catch (RuntimeException ex) {
493             String currentValues[] =
494                     {"attribute = " + rootObjectClass + "." + getName(), "Exception = " + ex.getMessage()};
495             tracer.createError("Unable to validate attribute", currentValues);
496             LOG.error("Exception while validating AttributeDefinition: " + getId(), ex );
497         }
498     }
499 
500     @BeanTagAttribute(name = "attributeSecurity", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
501     public AttributeSecurity getAttributeSecurity() {
502         if ( attributeSecurity != null ) {
503             return attributeSecurity;
504         }
505         // If we have an embedded attribute definition and this attribute is
506         // listed as "sensitive", then set the field to be masked by default on the UI
507         if ( getDataObjectAttribute() != null ) {
508             if ( getDataObjectAttribute().isSensitive() ) {
509                 AttributeSecurity attrSec = new AttributeSecurity();
510                 attrSec.setMask(true);
511                 attrSec.setMaskFormatter(new MaskFormatterLiteral());
512                 attributeSecurity = attrSec;
513             }
514         }
515         return attributeSecurity;
516     }
517 
518     public void setAttributeSecurity(AttributeSecurity attributeSecurity) {
519         this.attributeSecurity = attributeSecurity;
520     }
521 
522     public boolean hasAttributeSecurity() {
523         return (getAttributeSecurity() != null);
524     }
525 
526     /**
527      * @return the unique
528      */
529     public Boolean getUnique() {
530         return this.unique;
531     }
532 
533     /**
534      * @param unique the unique to set
535      */
536     public void setUnique(Boolean unique) {
537         this.unique = unique;
538     }
539 
540     /**
541      * Default {@code Control} to use when the attribute is to be rendered
542      * for the UI. Used by the UIF when a control is not defined for an
543      * {@code InputField}
544      *
545      * If not set in the AttributeDefinition, a default will be generated from the metadata for this field.
546      *
547      * @return Control instance
548      */
549     @BeanTagAttribute(name = "control", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
550     public Control getControlField() {
551         if ( controlField != null ) {
552             return controlField;
553         }
554         if ( cachedDerivedControl == null ) {
555             if ( GlobalResourceLoader.isInitialized() ) {
556                 cachedDerivedControl = KRADServiceLocatorWeb.getUifDefaultingService().deriveControlAttributeFromMetadata(this);
557             }
558         }
559         return cachedDerivedControl;
560     }
561 
562     /**
563      * Setter for the default control
564      *
565      * @param controlField
566      */
567     public void setControlField(Control controlField) {
568         this.controlField = controlField;
569     }
570 
571     /**
572      * @see org.kuali.rice.krad.datadictionary.validation.constraint.LengthConstraint#getMinLength()
573      */
574     @BeanTagAttribute(name = "minLength")
575     public Integer getMinLength() {
576         if ( getSimpleConstraint().getMinLength() != null ) {
577             return getSimpleConstraint().getMinLength();
578         }
579         if ( getDataObjectAttribute() != null ) {
580             if ( getDataObjectAttribute().getMinLength() != null ) {
581                 return new Integer( getDataObjectAttribute().getMinLength().intValue() );
582             }
583         }
584         return null;
585     }
586 
587     /**
588      * Setter for minumum length
589      *
590      * @param minLength
591      */
592     public void setMinLength(Integer minLength) {
593         this.getSimpleConstraint().setMinLength(minLength);
594     }
595 
596     /**
597      * Returns the Kuali datatype for this field.  See {@link DataType} for the defined types.
598      *
599      * If not defined in the AttributeDefinition, it will be retrieved from the embedded metadata, if defined.
600      *
601      * If not defined by either, will return {@link DataType#STRING}.
602      */
603     @BeanTagAttribute(name = "dataType", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
604     public DataType getDataType() {
605         if ( simpleConstraint.getDataType() != null ) {
606             return simpleConstraint.getDataType();
607         }
608         if ( getDataObjectAttribute() != null ) {
609             return getDataObjectAttribute().getDataType();
610         }
611         return DataType.STRING;
612     }
613 
614     /**
615      * @param dataType the dataType to set
616      */
617     public void setDataType(DataType dataType) {
618         simpleConstraint.setDataType(dataType);
619     }
620 
621     public void setDataType(String dataType) {
622         simpleConstraint.setDataType(DataType.valueOf(dataType));
623     }
624 
625     /**
626      * @return the customValidatorClass
627      */
628     @BeanTagAttribute(name = "customValidatorClass")
629     public String getCustomValidatorClass() {
630         return this.customValidatorClass;
631     }
632 
633     /**
634      * @param customValidatorClass the customValidatorClass to set
635      */
636     public void setCustomValidatorClass(String customValidatorClass) {
637         this.customValidatorClass = customValidatorClass;
638     }
639 
640     /**
641      * @return the validChars
642      */
643     @Override
644     @BeanTagAttribute(name = "validChractersConstraint", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
645     public ValidCharactersConstraint getValidCharactersConstraint() {
646         if ( validCharactersConstraint == null ) {
647             // If there is no constraint set, attempt to derive one
648             if ( GlobalResourceLoader.isInitialized() ) {
649                 // We don't set a default validation pattern if the field is hidden
650                 if ( getControlField() != null && !getControlField().isHidden() && !Boolean.TRUE.equals(getControlField().getReadOnly()) ) {
651                     validCharactersConstraint = KRADServiceLocatorWeb.getUifDefaultingService().deriveValidCharactersConstraint( this );
652                 }
653             }
654         }
655         return validCharactersConstraint;
656     }
657 
658     /**
659      * @param validCharactersConstraint the validChars to set
660      */
661     public void setValidCharactersConstraint(ValidCharactersConstraint validCharactersConstraint) {
662         this.validCharactersConstraint = validCharactersConstraint;
663     }
664 
665     /**
666      * @return the caseConstraint
667      */
668     @Override
669     @BeanTagAttribute(name = "caseConstraint", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
670     public CaseConstraint getCaseConstraint() {
671         return this.caseConstraint;
672     }
673 
674     /**
675      * @param caseConstraint the caseConstraint to set
676      */
677     public void setCaseConstraint(CaseConstraint caseConstraint) {
678         this.caseConstraint = caseConstraint;
679     }
680 
681     /**
682      * @return the requireConstraint
683      */
684     @Override
685     @BeanTagAttribute(name = "prerequisteConstraint", type = BeanTagAttribute.AttributeType.LISTBEAN)
686     public List<PrerequisiteConstraint> getPrerequisiteConstraints() {
687         return this.dependencyConstraints;
688     }
689 
690     /**
691      * @param dependencyConstraints the requireConstraint to set
692      */
693     public void setPrerequisiteConstraints(List<PrerequisiteConstraint> dependencyConstraints) {
694         this.dependencyConstraints = dependencyConstraints;
695     }
696 
697     /**
698      * @return the occursConstraint
699      */
700     @Override
701     @BeanTagAttribute(name = "mustOccurConstraints", type = BeanTagAttribute.AttributeType.LISTBEAN)
702     public List<MustOccurConstraint> getMustOccurConstraints() {
703         return this.mustOccurConstraints;
704     }
705 
706     /**
707      * @param mustOccurConstraints the occursConstraint to set
708      */
709     public void setMustOccurConstraints(List<MustOccurConstraint> mustOccurConstraints) {
710         this.mustOccurConstraints = mustOccurConstraints;
711     }
712 
713     /**
714      * @return the childEntryName
715      */
716     @Override
717     @BeanTagAttribute(name = "childEntryName")
718     public String getChildEntryName() {
719         return this.childEntryName;
720     }
721 
722     /**
723      * @param childEntryName the childEntryName to set
724      */
725     public void setChildEntryName(String childEntryName) {
726         this.childEntryName = childEntryName;
727     }
728 
729     /**
730      * Instance of {@code KeyValluesFinder} that should be invoked to
731      * provide a List of values the field can have. Generally used to provide
732      * the options for a multi-value control or to validate the submitted field
733      * value
734      *
735      * @return KeyValuesFinder instance
736      */
737     @BeanTagAttribute(name = "optionFinder", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
738     public KeyValuesFinder getOptionsFinder() {
739         if ( optionsFinder == null ) {
740             if ( getDataObjectAttribute() != null && getDataObjectAttribute().getValidValues() != null ) {
741                 return getDataObjectAttribute().getValidValues();
742             }
743         }
744         return optionsFinder;
745     }
746 
747     /**
748      * Setter for the field's KeyValuesFinder instance
749      *
750      * @param optionsFinder
751      */
752     public void setOptionsFinder(KeyValuesFinder optionsFinder) {
753         this.optionsFinder = optionsFinder;
754     }
755 
756     /**
757      * Setter that takes in the class name for the options finder and creates a
758      * new instance to use as the finder for the attribute field
759      *
760      * @param optionsFinderClass
761      */
762     public void setOptionsFinderClass(Class<? extends KeyValuesFinder> optionsFinderClass) {
763         this.optionsFinder = KRADUtils.createNewObjectFromClass(optionsFinderClass);
764     }
765 
766     public void setAdditionalDisplayAttributeName(String additionalDisplayAttributeName) {
767         this.additionalDisplayAttributeName = additionalDisplayAttributeName;
768     }
769 
770     @BeanTagAttribute(name = "additionalDisplayAttributeName")
771     public String getAdditionalDisplayAttributeName() {
772         return this.additionalDisplayAttributeName;
773     }
774 
775     public void setAlternateDisplayAttributeName(String alternateDisplayAttributeName) {
776         this.alternateDisplayAttributeName = alternateDisplayAttributeName;
777     }
778 
779     @BeanTagAttribute(name = "alternateDisplayAttributeName")
780     public String getAlternateDisplayAttributeName() {
781         return this.alternateDisplayAttributeName;
782     }
783 
784     /**
785      * Gets dependency constraints for this AttributeDefinition.  Same as getPrerequisiteConstraints.
786      *
787      * @return dependency constraints
788      */
789     public List<PrerequisiteConstraint> getDependencyConstraints() {
790         return dependencyConstraints;
791     }
792 
793     /**
794      * Sets dependency constraints for this AttributeDefinition.  Same as setPrerequisiteConstraints.
795      *
796      * @param dependencyConstraints dependency constraints
797      */
798     public void setDependencyConstraints(List<PrerequisiteConstraint> dependencyConstraints) {
799         this.dependencyConstraints = dependencyConstraints;
800     }
801 
802 }