001 /**
002 * Copyright 2005-2014 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.krad.datadictionary;
017
018 import java.beans.PropertyEditor;
019 import java.util.List;
020
021 import org.apache.commons.lang.ClassUtils;
022 import org.apache.commons.lang.StringUtils;
023 import org.kuali.rice.core.api.data.DataType;
024 import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
025 import org.kuali.rice.core.api.util.ClassLoaderUtils;
026 import org.kuali.rice.core.web.format.Formatter;
027 import org.kuali.rice.krad.datadictionary.control.ControlDefinition;
028 import org.kuali.rice.krad.datadictionary.mask.MaskFormatterLiteral;
029 import org.kuali.rice.krad.datadictionary.parse.BeanTag;
030 import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
031 import org.kuali.rice.krad.datadictionary.validation.ValidationPattern;
032 import org.kuali.rice.krad.datadictionary.validation.capability.CaseConstrainable;
033 import org.kuali.rice.krad.datadictionary.validation.capability.Formatable;
034 import org.kuali.rice.krad.datadictionary.validation.capability.HierarchicallyConstrainable;
035 import org.kuali.rice.krad.datadictionary.validation.capability.MustOccurConstrainable;
036 import org.kuali.rice.krad.datadictionary.validation.capability.PrerequisiteConstrainable;
037 import org.kuali.rice.krad.datadictionary.validation.capability.ValidCharactersConstrainable;
038 import org.kuali.rice.krad.datadictionary.validation.constraint.CaseConstraint;
039 import org.kuali.rice.krad.datadictionary.validation.constraint.MustOccurConstraint;
040 import org.kuali.rice.krad.datadictionary.validation.constraint.PrerequisiteConstraint;
041 import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint;
042 import org.kuali.rice.krad.datadictionary.validator.ValidationTrace;
043 import org.kuali.rice.krad.keyvalues.KeyValuesFinder;
044 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
045 import org.kuali.rice.krad.uif.control.Control;
046 import org.kuali.rice.krad.util.KRADUtils;
047
048 /**
049 * A single attribute definition in the DataDictionary, which contains
050 * information relating to the display, validation, and general maintenance of a
051 * specific attribute of an entry.
052 *
053 * @author Kuali Rice Team (rice.collab@kuali.org)
054 */
055 @BeanTag(name = "attributeDefinition-bean")
056 public class AttributeDefinition extends AttributeDefinitionBase implements CaseConstrainable, PrerequisiteConstrainable, Formatable, HierarchicallyConstrainable, MustOccurConstrainable, ValidCharactersConstrainable {
057 private static final long serialVersionUID = -2490613377818442742L;
058 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AttributeDefinition.class);
059
060 protected Boolean forceUppercase;
061
062 protected Boolean unique;
063
064 //These are deprecated DO NOT USE with new KRAD implementations
065 @Deprecated
066 protected ValidationPattern validationPattern;
067
068 @Deprecated
069 protected ControlDefinition control;
070
071 // TODO: rename to control once ControlDefinition is removed
072 protected Control controlField;
073 protected Control cachedDerivedControl = null;
074
075 @Deprecated
076 protected String formatterClass;
077 protected PropertyEditor propertyEditor;
078
079 protected AttributeSecurity attributeSecurity;
080
081 protected Boolean dynamic;
082
083 // KRAD constraints
084 protected String customValidatorClass;
085 protected ValidCharactersConstraint validCharactersConstraint;
086 protected CaseConstraint caseConstraint;
087 protected List<PrerequisiteConstraint> dependencyConstraints;
088 protected List<MustOccurConstraint> mustOccurConstraints;
089
090 //TODO: This may not be required since we now use ComplexAttributeDefinition
091 protected String childEntryName;
092
093 private KeyValuesFinder optionsFinder;
094
095 protected String alternateDisplayAttributeName;
096 protected String additionalDisplayAttributeName;
097
098 public AttributeDefinition() {
099 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() && !getControlField().isReadOnly() ) {
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 }