001/** 002 * Copyright 2005-2016 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 */ 016package org.kuali.rice.krad.datadictionary; 017 018import java.beans.PropertyEditor; 019import java.util.List; 020 021import org.apache.commons.lang.ClassUtils; 022import org.apache.commons.lang.StringUtils; 023import org.kuali.rice.core.api.data.DataType; 024import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader; 025import org.kuali.rice.core.api.util.ClassLoaderUtils; 026import org.kuali.rice.core.web.format.Formatter; 027import org.kuali.rice.krad.datadictionary.control.ControlDefinition; 028import org.kuali.rice.krad.datadictionary.mask.MaskFormatterLiteral; 029import org.kuali.rice.krad.datadictionary.parse.BeanTag; 030import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; 031import org.kuali.rice.krad.datadictionary.validation.ValidationPattern; 032import org.kuali.rice.krad.datadictionary.validation.capability.CaseConstrainable; 033import org.kuali.rice.krad.datadictionary.validation.capability.Formatable; 034import org.kuali.rice.krad.datadictionary.validation.capability.HierarchicallyConstrainable; 035import org.kuali.rice.krad.datadictionary.validation.capability.MustOccurConstrainable; 036import org.kuali.rice.krad.datadictionary.validation.capability.PrerequisiteConstrainable; 037import org.kuali.rice.krad.datadictionary.validation.capability.ValidCharactersConstrainable; 038import org.kuali.rice.krad.datadictionary.validation.constraint.CaseConstraint; 039import org.kuali.rice.krad.datadictionary.validation.constraint.MustOccurConstraint; 040import org.kuali.rice.krad.datadictionary.validation.constraint.PrerequisiteConstraint; 041import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint; 042import org.kuali.rice.krad.datadictionary.validator.ValidationTrace; 043import org.kuali.rice.krad.keyvalues.KeyValuesFinder; 044import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 045import org.kuali.rice.krad.uif.control.Control; 046import 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") 056public 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 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 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 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 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 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 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 506 // If we have an embedded attribute definition and this attribute is 507 // listed as "sensitive", then set the field to be masked by default on the UI 508 if ( getDataObjectAttribute() != null ) { 509 if ( getDataObjectAttribute().isSensitive() ) { 510 AttributeSecurity attrSec = new AttributeSecurity(); 511 attrSec.setMask(true); 512 attrSec.setMaskFormatter(new MaskFormatterLiteral()); 513 attributeSecurity = attrSec; 514 } 515 } 516 517 return attributeSecurity; 518 } 519 520 public void setAttributeSecurity(AttributeSecurity attributeSecurity) { 521 this.attributeSecurity = attributeSecurity; 522 } 523 524 public boolean hasAttributeSecurity() { 525 return (getAttributeSecurity() != null); 526 } 527 528 /** 529 * @return the unique 530 */ 531 public Boolean getUnique() { 532 return this.unique; 533 } 534 535 /** 536 * @param unique the unique to set 537 */ 538 public void setUnique(Boolean unique) { 539 this.unique = unique; 540 } 541 542 /** 543 * Default {@code Control} to use when the attribute is to be rendered 544 * for the UI. Used by the UIF when a control is not defined for an 545 * {@code InputField} 546 * 547 * If not set in the AttributeDefinition, a default will be generated from the metadata for this field. 548 * 549 * @return Control instance 550 */ 551 @BeanTagAttribute(name = "control", type = BeanTagAttribute.AttributeType.BYTYPE) 552 public Control getControlField() { 553 if ( controlField != null ) { 554 return controlField; 555 } 556 if ( cachedDerivedControl == null ) { 557 if ( GlobalResourceLoader.isInitialized() ) { 558 cachedDerivedControl = KRADServiceLocatorWeb.getUifDefaultingService().deriveControlAttributeFromMetadata(this); 559 } 560 } 561 return cachedDerivedControl; 562 } 563 564 /** 565 * Setter for the default control 566 * 567 * @param controlField 568 */ 569 public void setControlField(Control controlField) { 570 this.controlField = controlField; 571 } 572 573 /** 574 * @see org.kuali.rice.krad.datadictionary.validation.constraint.LengthConstraint#getMinLength() 575 */ 576 @BeanTagAttribute 577 public Integer getMinLength() { 578 if ( getSimpleConstraint().getMinLength() != null ) { 579 return getSimpleConstraint().getMinLength(); 580 } 581 if ( getDataObjectAttribute() != null ) { 582 if ( getDataObjectAttribute().getMinLength() != null ) { 583 return new Integer( getDataObjectAttribute().getMinLength().intValue() ); 584 } 585 } 586 return null; 587 } 588 589 /** 590 * Setter for minumum length 591 * 592 * @param minLength 593 */ 594 public void setMinLength(Integer minLength) { 595 this.getSimpleConstraint().setMinLength(minLength); 596 } 597 598 /** 599 * Returns the Kuali datatype for this field. See {@link DataType} for the defined types. 600 * 601 * If not defined in the AttributeDefinition, it will be retrieved from the embedded metadata, if defined. 602 * 603 * If not defined by either, will return {@link DataType#STRING}. 604 */ 605 @BeanTagAttribute(type = BeanTagAttribute.AttributeType.SINGLEBEAN) 606 public DataType getDataType() { 607 if ( simpleConstraint.getDataType() != null ) { 608 return simpleConstraint.getDataType(); 609 } 610 if ( getDataObjectAttribute() != null ) { 611 return getDataObjectAttribute().getDataType(); 612 } 613 return DataType.STRING; 614 } 615 616 /** 617 * @param dataType the dataType to set 618 */ 619 public void setDataType(DataType dataType) { 620 simpleConstraint.setDataType(dataType); 621 } 622 623 public void setDataType(String dataType) { 624 simpleConstraint.setDataType(DataType.valueOf(dataType)); 625 } 626 627 /** 628 * @return the customValidatorClass 629 */ 630 @BeanTagAttribute 631 public String getCustomValidatorClass() { 632 return this.customValidatorClass; 633 } 634 635 /** 636 * @param customValidatorClass the customValidatorClass to set 637 */ 638 public void setCustomValidatorClass(String customValidatorClass) { 639 this.customValidatorClass = customValidatorClass; 640 } 641 642 /** 643 * @return the validChars 644 */ 645 @Override 646 @BeanTagAttribute(type = BeanTagAttribute.AttributeType.DIRECTORBYTYPE) 647 public ValidCharactersConstraint getValidCharactersConstraint() { 648 if ( validCharactersConstraint == null ) { 649 // If there is no constraint set, attempt to derive one 650 if ( GlobalResourceLoader.isInitialized() ) { 651 // We don't set a default validation pattern if the field is hidden 652 if ( getControlField() != null && !getControlField().isHidden() && !Boolean.TRUE.equals(getControlField().getReadOnly()) ) { 653 validCharactersConstraint = KRADServiceLocatorWeb.getUifDefaultingService().deriveValidCharactersConstraint( this ); 654 } 655 } 656 } 657 return validCharactersConstraint; 658 } 659 660 /** 661 * @param validCharactersConstraint the validChars to set 662 */ 663 public void setValidCharactersConstraint(ValidCharactersConstraint validCharactersConstraint) { 664 this.validCharactersConstraint = validCharactersConstraint; 665 } 666 667 /** 668 * @return the caseConstraint 669 */ 670 @Override 671 @BeanTagAttribute(type = BeanTagAttribute.AttributeType.DIRECTORBYTYPE) 672 public CaseConstraint getCaseConstraint() { 673 return this.caseConstraint; 674 } 675 676 /** 677 * @param caseConstraint the caseConstraint to set 678 */ 679 public void setCaseConstraint(CaseConstraint caseConstraint) { 680 this.caseConstraint = caseConstraint; 681 } 682 683 /** 684 * @return the requireConstraint 685 */ 686 @Override 687 @BeanTagAttribute 688 public List<PrerequisiteConstraint> getPrerequisiteConstraints() { 689 return this.dependencyConstraints; 690 } 691 692 /** 693 * @param dependencyConstraints the requireConstraint to set 694 */ 695 public void setPrerequisiteConstraints(List<PrerequisiteConstraint> dependencyConstraints) { 696 this.dependencyConstraints = dependencyConstraints; 697 } 698 699 /** 700 * @return the occursConstraint 701 */ 702 @Override 703 @BeanTagAttribute 704 public List<MustOccurConstraint> getMustOccurConstraints() { 705 return this.mustOccurConstraints; 706 } 707 708 /** 709 * @param mustOccurConstraints the occursConstraint to set 710 */ 711 public void setMustOccurConstraints(List<MustOccurConstraint> mustOccurConstraints) { 712 this.mustOccurConstraints = mustOccurConstraints; 713 } 714 715 /** 716 * @return the childEntryName 717 */ 718 @Override 719 @BeanTagAttribute 720 public String getChildEntryName() { 721 return this.childEntryName; 722 } 723 724 /** 725 * @param childEntryName the childEntryName to set 726 */ 727 public void setChildEntryName(String childEntryName) { 728 this.childEntryName = childEntryName; 729 } 730 731 /** 732 * Instance of {@code KeyValluesFinder} that should be invoked to 733 * provide a List of values the field can have. Generally used to provide 734 * the options for a multi-value control or to validate the submitted field 735 * value 736 * 737 * @return KeyValuesFinder instance 738 */ 739 @BeanTagAttribute 740 public KeyValuesFinder getOptionsFinder() { 741 if ( optionsFinder == null ) { 742 if ( getDataObjectAttribute() != null && getDataObjectAttribute().getValidValues() != null ) { 743 return getDataObjectAttribute().getValidValues(); 744 } 745 } 746 return optionsFinder; 747 } 748 749 /** 750 * Setter for the field's KeyValuesFinder instance 751 * 752 * @param optionsFinder 753 */ 754 public void setOptionsFinder(KeyValuesFinder optionsFinder) { 755 this.optionsFinder = optionsFinder; 756 } 757 758 /** 759 * Setter that takes in the class name for the options finder and creates a 760 * new instance to use as the finder for the attribute field 761 * 762 * @param optionsFinderClass 763 */ 764 public void setOptionsFinderClass(Class<? extends KeyValuesFinder> optionsFinderClass) { 765 this.optionsFinder = KRADUtils.createNewObjectFromClass(optionsFinderClass); 766 } 767 768 public void setAdditionalDisplayAttributeName(String additionalDisplayAttributeName) { 769 this.additionalDisplayAttributeName = additionalDisplayAttributeName; 770 } 771 772 @BeanTagAttribute 773 public String getAdditionalDisplayAttributeName() { 774 return this.additionalDisplayAttributeName; 775 } 776 777 public void setAlternateDisplayAttributeName(String alternateDisplayAttributeName) { 778 this.alternateDisplayAttributeName = alternateDisplayAttributeName; 779 } 780 781 @BeanTagAttribute 782 public String getAlternateDisplayAttributeName() { 783 return this.alternateDisplayAttributeName; 784 } 785 786 /** 787 * Gets dependency constraints for this AttributeDefinition. Same as getPrerequisiteConstraints. 788 * 789 * @return dependency constraints 790 */ 791 public List<PrerequisiteConstraint> getDependencyConstraints() { 792 return dependencyConstraints; 793 } 794 795 /** 796 * Sets dependency constraints for this AttributeDefinition. Same as setPrerequisiteConstraints. 797 * 798 * @param dependencyConstraints dependency constraints 799 */ 800 public void setDependencyConstraints(List<PrerequisiteConstraint> dependencyConstraints) { 801 this.dependencyConstraints = dependencyConstraints; 802 } 803 804}