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.uif.field; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.rice.core.api.exception.RiceRuntimeException; 020import org.kuali.rice.krad.bo.DataObjectRelationship; 021import org.kuali.rice.krad.bo.KualiCode; 022import org.kuali.rice.krad.datadictionary.AttributeDefinition; 023import org.kuali.rice.krad.datadictionary.mask.MaskFormatter; 024import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 025import org.kuali.rice.krad.uif.component.BindingInfo; 026import org.kuali.rice.krad.uif.component.Component; 027import org.kuali.rice.krad.uif.component.ComponentSecurity; 028import org.kuali.rice.krad.uif.component.DataBinding; 029import org.kuali.rice.krad.uif.util.ObjectPropertyUtils; 030import org.kuali.rice.krad.uif.util.ViewModelUtils; 031import org.kuali.rice.krad.uif.view.View; 032import org.kuali.rice.krad.uif.widget.Inquiry; 033import org.kuali.rice.krad.util.KRADPropertyConstants; 034import org.kuali.rice.krad.util.ObjectUtils; 035import org.kuali.rice.krad.valuefinder.ValueFinder; 036 037import java.beans.PropertyEditor; 038import java.util.ArrayList; 039import java.util.List; 040 041/** 042 * Field that renders data from the application, such as the value of a data object property 043 * 044 * @author Kuali Rice Team (rice.collab@kuali.org) 045 */ 046public class DataField extends FieldBase implements DataBinding { 047 private static final long serialVersionUID = -4129678891948564724L; 048 049 // binding 050 private String propertyName; 051 private BindingInfo bindingInfo; 052 053 private String dictionaryAttributeName; 054 private String dictionaryObjectEntry; 055 056 // value props 057 private String defaultValue; 058 private Class<? extends ValueFinder> defaultValueFinderClass; 059 060 private PropertyEditor propertyEditor; 061 062 private boolean readOnlyHidden; 063 064 // alternate and additional display properties 065 protected String alternateDisplayPropertyName; 066 protected String additionalDisplayPropertyName; 067 068 private String alternateDisplayValue; 069 private String additionalDisplayValue; 070 071 private boolean applyValueMask; 072 private MaskFormatter maskFormatter; 073 074 private List<String> hiddenPropertyNames; 075 private List<String> informationalDisplayPropertyNames; 076 077 private boolean escapeHtmlInPropertyValue = true; 078 079 private String helpSummary; 080 private String helpDescription; 081 082 // widgets 083 private Inquiry fieldInquiry; 084 085 public DataField() { 086 super(); 087 088 readOnlyHidden = false; 089 applyValueMask = false; 090 091 hiddenPropertyNames = new ArrayList<String>(); 092 informationalDisplayPropertyNames = new ArrayList<String>(); 093 } 094 095 /** 096 * The following initialization is performed: 097 * 098 * <ul> 099 * <li>Set defaults for binding</li> 100 * <li>Default the model path if not set</li> 101 * </ul> 102 * 103 * @see org.kuali.rice.krad.uif.component.ComponentBase#performInitialization(org.kuali.rice.krad.uif.view.View, 104 * java.lang.Object) 105 */ 106 @Override 107 public void performInitialization(View view, Object model) { 108 super.performInitialization(view, model); 109 110 if (bindingInfo != null) { 111 bindingInfo.setDefaults(view, getPropertyName()); 112 } 113 } 114 115 /** 116 * The following updates are done here: 117 * 118 * <ul> 119 * <li>If readOnlyHidden set to true, set field to readonly and add to hidden property names</li> 120 * </ul> 121 */ 122 public void performApplyModel(View view, Object model, Component parent) { 123 super.performApplyModel(view, model, parent); 124 125 if (isReadOnlyHidden()) { 126 setReadOnly(true); 127 getHiddenPropertyNames().add(getPropertyName()); 128 } 129 } 130 131 /** 132 * The following actions are performed: 133 * 134 * <ul> 135 * <li>Set the ids for the various attribute components</li> 136 * <li>Sets up the client side validation for constraints on this field. In 137 * addition, it sets up the messages applied to this field</li> 138 * </ul> 139 * 140 * @see org.kuali.rice.krad.uif.component.ComponentBase#performFinalize(org.kuali.rice.krad.uif.view.View, 141 * java.lang.Object, org.kuali.rice.krad.uif.component.Component) 142 */ 143 @Override 144 public void performFinalize(View view, Object model, Component parent) { 145 super.performFinalize(view, model, parent); 146 147 // adjust the path for hidden fields 148 // TODO: should this check the view#readOnly? 149 List<String> hiddenPropertyPaths = new ArrayList<String>(); 150 for (String hiddenPropertyName : getHiddenPropertyNames()) { 151 String hiddenPropertyPath = getBindingInfo().getPropertyAdjustedBindingPath(hiddenPropertyName); 152 hiddenPropertyPaths.add(hiddenPropertyPath); 153 } 154 this.hiddenPropertyNames = hiddenPropertyPaths; 155 156 // adjust paths on informational property names 157 List<String> informationalPropertyPaths = new ArrayList<String>(); 158 for (String infoPropertyName : getInformationalDisplayPropertyNames()) { 159 String infoPropertyPath = getBindingInfo().getPropertyAdjustedBindingPath(infoPropertyName); 160 informationalPropertyPaths.add(infoPropertyPath); 161 } 162 this.informationalDisplayPropertyNames = informationalPropertyPaths; 163 164 // Additional and Alternate display value 165 setAlternateAndAdditionalDisplayValue(view, model); 166 } 167 168 /** 169 * Sets alternate and additional property value for this field. 170 * 171 * <p> 172 * If <code>AttributeSecurity</code> present in this field, make sure the current user has permission to view the 173 * field value. If user doesn't have permission to view the value, mask the value as configured and set it 174 * as alternate value for display. If security doesn't exists for this field but 175 * <code>alternateDisplayPropertyName</code> present, get its value and format it based on that 176 * fields formatting and set for display. 177 * </p> 178 * 179 * <p> 180 * For additional display value, if <code>AttributeSecurity</code> not present, sets the value if 181 * <code>additionalDisplayPropertyName</code> present. If not present, check whether this field is a 182 * <code>KualiCode</code> and get the relationship configured in the datadictionary file and set the name 183 * additional display value which will be displayed along with the code. If additional display property not 184 * present, check whether this field is has <code>MultiValueControlBase</code>. If yes, get the Label 185 * for the value and set it as additional display value. 186 * </p> 187 * 188 * @param view - the current view instance 189 * @param model - model instance 190 */ 191 protected void setAlternateAndAdditionalDisplayValue(View view, Object model) { 192 // if alternate or additional display values set don't use property names 193 if (StringUtils.isNotBlank(alternateDisplayValue) || StringUtils.isNotBlank(additionalDisplayValue)) { 194 return; 195 } 196 197 // check whether field value needs to be masked, and if so apply masking as alternateDisplayValue 198 if (isApplyValueMask()) { 199 Object fieldValue = ObjectPropertyUtils.getPropertyValue(model, getBindingInfo().getBindingPath()); 200 alternateDisplayValue = getMaskFormatter().maskValue(fieldValue); 201 202 // mask values are forced to be readonly 203 setReadOnly(true); 204 return; 205 } 206 207 // if not read only, return without trying to set alternate and additional values 208 if (!isReadOnly()) { 209 return; 210 } 211 212 // if field is not secure, check for alternate and additional display properties 213 if (StringUtils.isNotBlank(getAlternateDisplayPropertyName())) { 214 String alternateDisplayPropertyPath = getBindingInfo().getPropertyAdjustedBindingPath( 215 getAlternateDisplayPropertyName()); 216 217 Object alternateFieldValue = ObjectPropertyUtils.getPropertyValue(model, alternateDisplayPropertyPath); 218 if (alternateFieldValue != null) { 219 // TODO: format by type 220 alternateDisplayValue = alternateFieldValue.toString(); 221 } 222 } 223 224 // perform automatic translation for code references if enabled on view 225 if (StringUtils.isBlank(getAdditionalDisplayPropertyName()) && view.isTranslateCodes()) { 226 // check for any relationship present for this field and it's of type KualiCode 227 Class<?> parentObjectClass = ViewModelUtils.getParentObjectClassForMetadata(view, model, this); 228 DataObjectRelationship relationship = 229 KRADServiceLocatorWeb.getDataObjectMetaDataService().getDataObjectRelationship(null, 230 parentObjectClass, getBindingInfo().getBindingName(), "", true, false, false); 231 232 if (relationship != null 233 && getPropertyName().startsWith(relationship.getParentAttributeName()) 234 && KualiCode.class.isAssignableFrom(relationship.getRelatedClass())) { 235 additionalDisplayPropertyName = 236 relationship.getParentAttributeName() + "." + KRADPropertyConstants.NAME; 237 } 238 } 239 240 // now check for an additional display property and if set get the value 241 if (StringUtils.isNotBlank(getAdditionalDisplayPropertyName())) { 242 String additionalDisplayPropertyPath = getBindingInfo().getPropertyAdjustedBindingPath( 243 getAdditionalDisplayPropertyName()); 244 245 Object additionalFieldValue = ObjectPropertyUtils.getPropertyValue(model, additionalDisplayPropertyPath); 246 if (additionalFieldValue != null) { 247 // TODO: format by type 248 additionalDisplayValue = additionalFieldValue.toString(); 249 } 250 } 251 } 252 253 /** 254 * Defaults the properties of the <code>DataField</code> to the 255 * corresponding properties of its <code>AttributeDefinition</code> 256 * retrieved from the dictionary (if such an entry exists). If the field 257 * already contains a value for a property, the definitions value is not 258 * used. 259 * 260 * @param view - view instance the field belongs to 261 * @param attributeDefinition - AttributeDefinition instance the property values should be 262 * copied from 263 */ 264 public void copyFromAttributeDefinition(View view, AttributeDefinition attributeDefinition) { 265 // label 266 if (StringUtils.isEmpty(getLabel())) { 267 setLabel(attributeDefinition.getLabel()); 268 } 269 270 // short label 271 if (StringUtils.isEmpty(getShortLabel())) { 272 setShortLabel(attributeDefinition.getShortLabel()); 273 } 274 275 // summary 276 if (StringUtils.isEmpty(getHelpSummary())) { 277 setHelpSummary(attributeDefinition.getSummary()); 278 } 279 280 // description 281 if (StringUtils.isEmpty(getHelpDescription())) { 282 setHelpDescription(attributeDefinition.getDescription()); 283 } 284 285 // security 286 if (getDataFieldSecurity().getAttributeSecurity() == null) { 287 getDataFieldSecurity().setAttributeSecurity(attributeDefinition.getAttributeSecurity()); 288 } 289 290 // alternate property name 291 if (getAlternateDisplayPropertyName() == null && StringUtils.isNotBlank( 292 attributeDefinition.getAlternateDisplayAttributeName())) { 293 setAlternateDisplayPropertyName(attributeDefinition.getAlternateDisplayAttributeName()); 294 } 295 296 // additional property display name 297 if (getAdditionalDisplayPropertyName() == null && StringUtils.isNotBlank( 298 attributeDefinition.getAdditionalDisplayAttributeName())) { 299 setAdditionalDisplayPropertyName(attributeDefinition.getAdditionalDisplayAttributeName()); 300 } 301 302 // property editor 303 if (getPropertyEditor() == null) { 304 setPropertyEditor(attributeDefinition.getPropertyEditor()); 305 } 306 } 307 308 /** 309 * @see org.kuali.rice.krad.uif.component.ComponentBase#getComponentsForLifecycle() 310 */ 311 @Override 312 public List<Component> getComponentsForLifecycle() { 313 List<Component> components = super.getComponentsForLifecycle(); 314 315 components.add(fieldInquiry); 316 317 return components; 318 } 319 320 /** 321 * Indicates whether the data field instance allows input, subclasses should override and set to 322 * true if input is allowed 323 * 324 * @return boolean true if input is allowed, false if read only 325 */ 326 public boolean isInputAllowed() { 327 return false; 328 } 329 330 /** 331 * @see org.kuali.rice.krad.uif.component.DataBinding#getPropertyName() 332 */ 333 public String getPropertyName() { 334 return this.propertyName; 335 } 336 337 /** 338 * Setter for the component's property name 339 * 340 * @param propertyName 341 */ 342 public void setPropertyName(String propertyName) { 343 this.propertyName = propertyName; 344 } 345 346 /** 347 * Performs formatting of the field value for display and then converting the value back to its 348 * expected type from a string 349 * 350 * <p> 351 * Note property editors exist and are already registered for the basic Java types and the 352 * common Kuali types such as [@link KualiDecimal}. Registration with this property is only 353 * needed for custom property editors 354 * </p> 355 * 356 * @return PropertyEditor property editor instance to use for this field 357 */ 358 public PropertyEditor getPropertyEditor() { 359 return propertyEditor; 360 } 361 362 /** 363 * Setter for the custom property editor to use for the field 364 * 365 * @param propertyEditor 366 */ 367 public void setPropertyEditor(PropertyEditor propertyEditor) { 368 this.propertyEditor = propertyEditor; 369 } 370 371 /** 372 * Convenience setter for configuring a property editor by class 373 * 374 * @param propertyEditorClass 375 */ 376 public void setPropertyEditorClass(Class<? extends PropertyEditor> propertyEditorClass) { 377 this.propertyEditor = ObjectUtils.newInstance(propertyEditorClass); 378 } 379 380 /** 381 * @see org.kuali.rice.krad.uif.component.DataBinding#getBindingInfo() 382 */ 383 public BindingInfo getBindingInfo() { 384 return this.bindingInfo; 385 } 386 387 /** 388 * Setter for the field's binding info 389 * 390 * @param bindingInfo 391 */ 392 public void setBindingInfo(BindingInfo bindingInfo) { 393 this.bindingInfo = bindingInfo; 394 } 395 396 /** 397 * Name of the attribute within the data dictionary the attribute field is 398 * associated with 399 * 400 * <p> 401 * During the initialize phase for the <code>View</code>, properties for 402 * attribute fields are defaulted from a corresponding 403 * <code>AttributeDefinition</code> in the data dictionary. Based on the 404 * propertyName and parent object class the framework attempts will 405 * determine the attribute definition that is associated with the field and 406 * set this property. However this property can also be set in the fields 407 * configuration to use another dictionary attribute. 408 * </p> 409 * 410 * <p> 411 * The attribute name is used along with the dictionary object entry to find 412 * the <code>AttributeDefinition</code> 413 * </p> 414 * 415 * @return String attribute name 416 */ 417 public String getDictionaryAttributeName() { 418 return this.dictionaryAttributeName; 419 } 420 421 /** 422 * Setter for the dictionary attribute name 423 * 424 * @param dictionaryAttributeName 425 */ 426 public void setDictionaryAttributeName(String dictionaryAttributeName) { 427 this.dictionaryAttributeName = dictionaryAttributeName; 428 } 429 430 /** 431 * Object entry name in the data dictionary the associated attribute is 432 * apart of 433 * 434 * <p> 435 * During the initialize phase for the <code>View</code>, properties for 436 * attribute fields are defaulted from a corresponding 437 * <code>AttributeDefinition</code> in the data dictionary. Based on the 438 * parent object class the framework will determine the object entry for the 439 * associated attribute. However the object entry can be set in the field's 440 * configuration to use another object entry for the attribute 441 * </p> 442 * 443 * <p> 444 * The attribute name is used along with the dictionary object entry to find 445 * the <code>AttributeDefinition</code> 446 * </p> 447 * 448 * @return 449 */ 450 public String getDictionaryObjectEntry() { 451 return this.dictionaryObjectEntry; 452 } 453 454 /** 455 * Setter for the dictionary object entry 456 * 457 * @param dictionaryObjectEntry 458 */ 459 public void setDictionaryObjectEntry(String dictionaryObjectEntry) { 460 this.dictionaryObjectEntry = dictionaryObjectEntry; 461 } 462 463 /** 464 * Default value for the model property the field points to 465 * 466 * <p> 467 * When a new <code>View</code> instance is requested, the corresponding 468 * model will be newly created. During this initialization process the value 469 * for the model property will be set to the given default value (if set) 470 * </p> 471 * 472 * @return String default value 473 */ 474 public String getDefaultValue() { 475 return this.defaultValue; 476 } 477 478 /** 479 * Setter for the fields default value 480 * 481 * @param defaultValue 482 */ 483 public void setDefaultValue(String defaultValue) { 484 this.defaultValue = defaultValue; 485 } 486 487 /** 488 * Gives Class that should be invoked to produce the default value for the 489 * field 490 * 491 * @return Class<? extends ValueFinder> default value finder class 492 */ 493 public Class<? extends ValueFinder> getDefaultValueFinderClass() { 494 return this.defaultValueFinderClass; 495 } 496 497 /** 498 * Setter for the default value finder class 499 * 500 * @param defaultValueFinderClass 501 */ 502 public void setDefaultValueFinderClass(Class<? extends ValueFinder> defaultValueFinderClass) { 503 this.defaultValueFinderClass = defaultValueFinderClass; 504 } 505 506 /** 507 * Summary help text for the field 508 * 509 * @return String summary help text 510 */ 511 public String getHelpSummary() { 512 return helpSummary; 513 } 514 515 /** 516 * Setter for the summary help text 517 * 518 * @param helpSummary 519 */ 520 public void setHelpSummary(String helpSummary) { 521 this.helpSummary = helpSummary; 522 } 523 524 /** 525 * Full help information text for the field 526 * 527 * @return String help description text 528 */ 529 public String getHelpDescription() { 530 return this.helpDescription; 531 } 532 533 /** 534 * Setter for the help description text 535 * 536 * @param helpDescription 537 */ 538 public void setHelpDescription(String helpDescription) { 539 this.helpDescription = helpDescription; 540 } 541 542 /** 543 * Data Field Security object that indicates what authorization (permissions) exist for the field 544 * 545 * @return DataFieldSecurity instance 546 */ 547 public DataFieldSecurity getDataFieldSecurity() { 548 return (DataFieldSecurity) super.getComponentSecurity(); 549 } 550 551 /** 552 * Override to assert a {@link DataFieldSecurity} instance is set 553 * 554 * @param componentSecurity - instance of DataFieldSecurity 555 */ 556 @Override 557 public void setComponentSecurity(ComponentSecurity componentSecurity) { 558 if (!(componentSecurity instanceof DataFieldSecurity)) { 559 throw new RiceRuntimeException("Component security for DataField should be instance of DataFieldSecurity"); 560 } 561 562 super.setComponentSecurity(componentSecurity); 563 } 564 565 @Override 566 protected Class<? extends ComponentSecurity> getComponentSecurityClass() { 567 return DataFieldSecurity.class; 568 } 569 570 /** 571 * Indicates the field should be read-only but also a hidden should be generated for the field 572 * 573 * <p> 574 * Useful for when a value is just displayed but is needed by script 575 * </p> 576 * 577 * @return boolean true if field should be readOnly hidden, false if not 578 */ 579 public boolean isReadOnlyHidden() { 580 return readOnlyHidden; 581 } 582 583 /** 584 * Setter for the read-only hidden indicator 585 * 586 * @param readOnlyHidden 587 */ 588 public void setReadOnlyHidden(boolean readOnlyHidden) { 589 this.readOnlyHidden = readOnlyHidden; 590 } 591 592 /** 593 * Inquiry widget for the field 594 * 595 * <p> 596 * The inquiry widget will render a link for the field value when read-only 597 * that points to the associated inquiry view for the field. The inquiry can 598 * be configured to point to a certain <code>InquiryView</code>, or the 599 * framework will attempt to associate the field with a inquiry based on its 600 * metadata (in particular its relationships in the model) 601 * </p> 602 * 603 * @return Inquiry field inquiry 604 */ 605 public Inquiry getFieldInquiry() { 606 return this.fieldInquiry; 607 } 608 609 /** 610 * Setter for the inquiry widget 611 * 612 * @param fieldInquiry 613 */ 614 public void setFieldInquiry(Inquiry fieldInquiry) { 615 this.fieldInquiry = fieldInquiry; 616 } 617 618 /** 619 * Additional display attribute name, which will be displayed next to the actual field value 620 * when the field is readonly with hypen inbetween like PropertyValue - AdditionalPropertyValue 621 * 622 * @param additionalDisplayPropertyName - Name of the additional display property 623 */ 624 public void setAdditionalDisplayPropertyName(String additionalDisplayPropertyName) { 625 this.additionalDisplayPropertyName = additionalDisplayPropertyName; 626 } 627 628 /** 629 * Returns the additional display attribute name to be displayed when the field is readonly 630 * 631 * @return Additional Display Attribute Name 632 */ 633 public String getAdditionalDisplayPropertyName() { 634 return this.additionalDisplayPropertyName; 635 } 636 637 /** 638 * Sets the alternate display attribute name to be displayed when the field is readonly. 639 * This properties value will be displayed instead of actual fields value when the field is readonly. 640 * 641 * @param alternateDisplayPropertyName - alternate display property name 642 */ 643 public void setAlternateDisplayPropertyName(String alternateDisplayPropertyName) { 644 this.alternateDisplayPropertyName = alternateDisplayPropertyName; 645 } 646 647 /** 648 * Returns the alternate display attribute name to be displayed when the field is readonly. 649 * 650 * @return alternate Display Property Name 651 */ 652 public String getAlternateDisplayPropertyName() { 653 return this.alternateDisplayPropertyName; 654 } 655 656 /** 657 * Returns the alternate display value 658 * 659 * @return the alternate display value set for this field 660 */ 661 public String getAlternateDisplayValue() { 662 return alternateDisplayValue; 663 } 664 665 /** 666 * Setter for the alternative display value 667 * 668 * @param value 669 */ 670 public void setAlternateDisplayValue(String value) { 671 this.alternateDisplayValue = value; 672 } 673 674 /** 675 * Returns the additional display value. 676 * 677 * @return the additional display value set for this field 678 */ 679 public String getAdditionalDisplayValue() { 680 return additionalDisplayValue; 681 } 682 683 /** 684 * Setter for the additional display value 685 * 686 * @param value 687 */ 688 public void setAdditionalDisplayValue(String value) { 689 this.additionalDisplayValue = value; 690 } 691 692 /** 693 * Indicates whether the value for the field should be masked (or partially masked) on display 694 * 695 * <p> 696 * If set to true, the field value will be masked by applying the configured {@link #getMaskFormatter()} 697 * </p> 698 * 699 * <p> 700 * If a KIM permission exists that should be checked to determine whether the value should be masked or not, 701 * this value should not be set but instead the mask or partialMask property on {@link #getComponentSecurity()} 702 * should be set to true. This indicates there is a mask permission that should be consulted. If the user 703 * does not have the permission, this flag will be set to true by the framework and the value masked using 704 * the mask formatter configured on the security object 705 * </p> 706 * 707 * @return boolean true if the field value should be masked, false if not 708 */ 709 public boolean isApplyValueMask() { 710 return applyValueMask; 711 } 712 713 /** 714 * Setter for the apply value mask flag 715 * 716 * @param applyValueMask 717 */ 718 public void setApplyValueMask(boolean applyValueMask) { 719 this.applyValueMask = applyValueMask; 720 } 721 722 /** 723 * MaskFormatter instance that will be used to mask the field value when {@link #isApplyValueMask()} is true 724 * 725 * <p> 726 * Note in cases where the mask is applied due to security (KIM permissions), the mask or partial mask formatter 727 * configured on {@link #getComponentSecurity()} will be used instead of this mask formatter 728 * </p> 729 * 730 * @return MaskFormatter instance 731 */ 732 public MaskFormatter getMaskFormatter() { 733 return maskFormatter; 734 } 735 736 /** 737 * Setter for the MaskFormatter instance to apply when the value is masked 738 * 739 * @param maskFormatter 740 */ 741 public void setMaskFormatter(MaskFormatter maskFormatter) { 742 this.maskFormatter = maskFormatter; 743 } 744 745 /** 746 * Allows specifying hidden property names without having to specify as a 747 * field in the group config (that might impact layout) 748 * 749 * @return List<String> hidden property names 750 */ 751 public List<String> getHiddenPropertyNames() { 752 return hiddenPropertyNames; 753 } 754 755 /** 756 * Setter for the hidden property names 757 * 758 * @param hiddenPropertyNames 759 */ 760 public void setHiddenPropertyNames(List<String> hiddenPropertyNames) { 761 this.hiddenPropertyNames = hiddenPropertyNames; 762 } 763 764 /** 765 * List of property names whose values should be displayed read-only under this field 766 * 767 * <p> 768 * In the attribute field template for each information property name given its values is 769 * outputted read-only. Informational property values can also be updated dynamically with 770 * the use of field attribute query 771 * </p> 772 * 773 * <p> 774 * Simple property names can be given if the property has the same binding parent as this 775 * field, in which case the binding path will be adjusted by the framework. If the property 776 * names starts with org.kuali.rice.krad.uif.UifConstants#NO_BIND_ADJUST_PREFIX, no binding 777 * prefix will be added. 778 * </p> 779 * 780 * @return List<String> informational property names 781 */ 782 public List<String> getInformationalDisplayPropertyNames() { 783 return informationalDisplayPropertyNames; 784 } 785 786 /** 787 * Setter for the list of informational property names 788 * 789 * @param informationalDisplayPropertyNames 790 */ 791 public void setInformationalDisplayPropertyNames(List<String> informationalDisplayPropertyNames) { 792 this.informationalDisplayPropertyNames = informationalDisplayPropertyNames; 793 } 794 795 /** 796 * Sets HTML escaping for this property value. HTML escaping will be handled in alternate and additional fields 797 * also. 798 */ 799 public void setEscapeHtmlInPropertyValue(boolean escapeHtmlInPropertyValue) { 800 this.escapeHtmlInPropertyValue = escapeHtmlInPropertyValue; 801 } 802 803 /** 804 * Returns true if HTML escape allowed for this field 805 * 806 * @return true if escaping allowed 807 */ 808 public boolean isEscapeHtmlInPropertyValue() { 809 return this.escapeHtmlInPropertyValue; 810 } 811 812 /** 813 * Indicates whether the value for the field is secure 814 * 815 * <p> 816 * A value will be secured if masking has been applied (by configuration or a failed KIM permission) or the field 817 * has been marked as hidden due to an authorization check 818 * </p> 819 * 820 * @return boolean true if value is secure, false if not 821 */ 822 public boolean hasSecureValue() { 823 return isApplyValueMask() || ((getComponentSecurity().isViewAuthz() 824 || getDataFieldSecurity().isViewInLineAuthz() 825 || ((getDataFieldSecurity().getAttributeSecurity() != null) && getDataFieldSecurity() 826 .getAttributeSecurity().isHide())) && isHidden()); 827 } 828 829}