1 /**
2 * Copyright 2005-2013 The Kuali Foundation
3 *
4 * Licensed under the Educational Community License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.opensource.org/licenses/ecl2.php
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.kuali.rice.krad.uif.field;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.core.api.exception.RiceRuntimeException;
20 import org.kuali.rice.krad.bo.DataObjectRelationship;
21 import org.kuali.rice.krad.bo.KualiCode;
22 import org.kuali.rice.krad.datadictionary.AttributeDefinition;
23 import org.kuali.rice.krad.datadictionary.mask.MaskFormatter;
24 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
25 import org.kuali.rice.krad.uif.component.BindingInfo;
26 import org.kuali.rice.krad.uif.component.Component;
27 import org.kuali.rice.krad.uif.component.ComponentSecurity;
28 import org.kuali.rice.krad.uif.component.DataBinding;
29 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
30 import org.kuali.rice.krad.uif.util.ViewModelUtils;
31 import org.kuali.rice.krad.uif.view.View;
32 import org.kuali.rice.krad.uif.widget.Inquiry;
33 import org.kuali.rice.krad.util.KRADPropertyConstants;
34 import org.kuali.rice.krad.util.ObjectUtils;
35 import org.kuali.rice.krad.valuefinder.ValueFinder;
36
37 import java.beans.PropertyEditor;
38 import java.util.ArrayList;
39 import java.util.List;
40
41 /**
42 * Field that renders data from the application, such as the value of a data object property
43 *
44 * @author Kuali Rice Team (rice.collab@kuali.org)
45 */
46 public class DataField extends FieldBase implements DataBinding {
47 private static final long serialVersionUID = -4129678891948564724L;
48
49 // binding
50 private String propertyName;
51 private BindingInfo bindingInfo;
52
53 private String dictionaryAttributeName;
54 private String dictionaryObjectEntry;
55
56 // value props
57 private String defaultValue;
58 private Class<? extends ValueFinder> defaultValueFinderClass;
59
60 private PropertyEditor propertyEditor;
61
62 private boolean readOnlyHidden;
63
64 // alternate and additional display properties
65 protected String alternateDisplayPropertyName;
66 protected String additionalDisplayPropertyName;
67
68 private String alternateDisplayValue;
69 private String additionalDisplayValue;
70
71 private boolean applyValueMask;
72 private MaskFormatter maskFormatter;
73
74 private List<String> hiddenPropertyNames;
75 private List<String> informationalDisplayPropertyNames;
76
77 private boolean escapeHtmlInPropertyValue = true;
78
79 private String helpSummary;
80 private String helpDescription;
81
82 // widgets
83 private Inquiry fieldInquiry;
84
85 public DataField() {
86 super();
87
88 readOnlyHidden = false;
89 applyValueMask = false;
90
91 hiddenPropertyNames = new ArrayList<String>();
92 informationalDisplayPropertyNames = new ArrayList<String>();
93 }
94
95 /**
96 * The following initialization is performed:
97 *
98 * <ul>
99 * <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 }