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 }