1 /**
2 * Copyright 2005-2012 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 (getComponentSecurity().getAttributeSecurity() == null) {
287 getComponentSecurity().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 @Override
548 public DataFieldSecurity getComponentSecurity() {
549 return (DataFieldSecurity) super.getComponentSecurity();
550 }
551
552 /**
553 * Override to assert a {@link DataFieldSecurity} instance is set
554 *
555 * @param componentSecurity - instance of DataFieldSecurity
556 */
557 @Override
558 public void setComponentSecurity(ComponentSecurity componentSecurity) {
559 if (!(componentSecurity instanceof DataFieldSecurity)) {
560 throw new RiceRuntimeException("Component security for DataField should be instance of DataFieldSecurity");
561 }
562
563 super.setComponentSecurity(componentSecurity);
564 }
565
566 @Override
567 protected Class<? extends ComponentSecurity> getComponentSecurityClass() {
568 return DataFieldSecurity.class;
569 }
570
571 /**
572 * Indicates the field should be read-only but also a hidden should be generated for the field
573 *
574 * <p>
575 * Useful for when a value is just displayed but is needed by script
576 * </p>
577 *
578 * @return boolean true if field should be readOnly hidden, false if not
579 */
580 public boolean isReadOnlyHidden() {
581 return readOnlyHidden;
582 }
583
584 /**
585 * Setter for the read-only hidden indicator
586 *
587 * @param readOnlyHidden
588 */
589 public void setReadOnlyHidden(boolean readOnlyHidden) {
590 this.readOnlyHidden = readOnlyHidden;
591 }
592
593 /**
594 * Inquiry widget for the field
595 *
596 * <p>
597 * The inquiry widget will render a link for the field value when read-only
598 * that points to the associated inquiry view for the field. The inquiry can
599 * be configured to point to a certain <code>InquiryView</code>, or the
600 * framework will attempt to associate the field with a inquiry based on its
601 * metadata (in particular its relationships in the model)
602 * </p>
603 *
604 * @return Inquiry field inquiry
605 */
606 public Inquiry getFieldInquiry() {
607 return this.fieldInquiry;
608 }
609
610 /**
611 * Setter for the inquiry widget
612 *
613 * @param fieldInquiry
614 */
615 public void setFieldInquiry(Inquiry fieldInquiry) {
616 this.fieldInquiry = fieldInquiry;
617 }
618
619 /**
620 * Additional display attribute name, which will be displayed next to the actual field value
621 * when the field is readonly with hypen inbetween like PropertyValue - AdditionalPropertyValue
622 *
623 * @param additionalDisplayPropertyName - Name of the additional display property
624 */
625 public void setAdditionalDisplayPropertyName(String additionalDisplayPropertyName) {
626 this.additionalDisplayPropertyName = additionalDisplayPropertyName;
627 }
628
629 /**
630 * Returns the additional display attribute name to be displayed when the field is readonly
631 *
632 * @return Additional Display Attribute Name
633 */
634 public String getAdditionalDisplayPropertyName() {
635 return this.additionalDisplayPropertyName;
636 }
637
638 /**
639 * Sets the alternate display attribute name to be displayed when the field is readonly.
640 * This properties value will be displayed instead of actual fields value when the field is readonly.
641 *
642 * @param alternateDisplayPropertyName - alternate display property name
643 */
644 public void setAlternateDisplayPropertyName(String alternateDisplayPropertyName) {
645 this.alternateDisplayPropertyName = alternateDisplayPropertyName;
646 }
647
648 /**
649 * Returns the alternate display attribute name to be displayed when the field is readonly.
650 *
651 * @return alternate Display Property Name
652 */
653 public String getAlternateDisplayPropertyName() {
654 return this.alternateDisplayPropertyName;
655 }
656
657 /**
658 * Returns the alternate display value
659 *
660 * @return the alternate display value set for this field
661 */
662 public String getAlternateDisplayValue() {
663 return alternateDisplayValue;
664 }
665
666 /**
667 * Setter for the alternative display value
668 *
669 * @param value
670 */
671 public void setAlternateDisplayValue(String value) {
672 this.alternateDisplayValue = value;
673 }
674
675 /**
676 * Returns the additional display value.
677 *
678 * @return the additional display value set for this field
679 */
680 public String getAdditionalDisplayValue() {
681 return additionalDisplayValue;
682 }
683
684 /**
685 * Setter for the additional display value
686 *
687 * @param value
688 */
689 public void setAdditionalDisplayValue(String value) {
690 this.additionalDisplayValue = value;
691 }
692
693 /**
694 * Indicates whether the value for the field should be masked (or partially masked) on display
695 *
696 * <p>
697 * If set to true, the field value will be masked by applying the configured {@link #getMaskFormatter()}
698 * </p>
699 *
700 * <p>
701 * If a KIM permission exists that should be checked to determine whether the value should be masked or not,
702 * this value should not be set but instead the mask or partialMask property on {@link #getComponentSecurity()}
703 * should be set to true. This indicates there is a mask permission that should be consulted. If the user
704 * does not have the permission, this flag will be set to true by the framework and the value masked using
705 * the mask formatter configured on the security object
706 * </p>
707 *
708 * @return boolean true if the field value should be masked, false if not
709 */
710 public boolean isApplyValueMask() {
711 return applyValueMask;
712 }
713
714 /**
715 * Setter for the apply value mask flag
716 *
717 * @param applyValueMask
718 */
719 public void setApplyValueMask(boolean applyValueMask) {
720 this.applyValueMask = applyValueMask;
721 }
722
723 /**
724 * MaskFormatter instance that will be used to mask the field value when {@link #isApplyValueMask()} is true
725 *
726 * <p>
727 * Note in cases where the mask is applied due to security (KIM permissions), the mask or partial mask formatter
728 * configured on {@link #getComponentSecurity()} will be used instead of this mask formatter
729 * </p>
730 *
731 * @return MaskFormatter instance
732 */
733 public MaskFormatter getMaskFormatter() {
734 return maskFormatter;
735 }
736
737 /**
738 * Setter for the MaskFormatter instance to apply when the value is masked
739 *
740 * @param maskFormatter
741 */
742 public void setMaskFormatter(MaskFormatter maskFormatter) {
743 this.maskFormatter = maskFormatter;
744 }
745
746 /**
747 * Allows specifying hidden property names without having to specify as a
748 * field in the group config (that might impact layout)
749 *
750 * @return List<String> hidden property names
751 */
752 public List<String> getHiddenPropertyNames() {
753 return hiddenPropertyNames;
754 }
755
756 /**
757 * Setter for the hidden property names
758 *
759 * @param hiddenPropertyNames
760 */
761 public void setHiddenPropertyNames(List<String> hiddenPropertyNames) {
762 this.hiddenPropertyNames = hiddenPropertyNames;
763 }
764
765 /**
766 * List of property names whose values should be displayed read-only under this field
767 *
768 * <p>
769 * In the attribute field template for each information property name given its values is
770 * outputted read-only. Informational property values can also be updated dynamically with
771 * the use of field attribute query
772 * </p>
773 *
774 * <p>
775 * Simple property names can be given if the property has the same binding parent as this
776 * field, in which case the binding path will be adjusted by the framework. If the property
777 * names starts with org.kuali.rice.krad.uif.UifConstants#NO_BIND_ADJUST_PREFIX, no binding
778 * prefix will be added.
779 * </p>
780 *
781 * @return List<String> informational property names
782 */
783 public List<String> getInformationalDisplayPropertyNames() {
784 return informationalDisplayPropertyNames;
785 }
786
787 /**
788 * Setter for the list of informational property names
789 *
790 * @param informationalDisplayPropertyNames
791 */
792 public void setInformationalDisplayPropertyNames(List<String> informationalDisplayPropertyNames) {
793 this.informationalDisplayPropertyNames = informationalDisplayPropertyNames;
794 }
795
796 /**
797 * Sets HTML escaping for this property value. HTML escaping will be handled in alternate and additional fields
798 * also.
799 */
800 public void setEscapeHtmlInPropertyValue(boolean escapeHtmlInPropertyValue) {
801 this.escapeHtmlInPropertyValue = escapeHtmlInPropertyValue;
802 }
803
804 /**
805 * Returns true if HTML escape allowed for this field
806 *
807 * @return true if escaping allowed
808 */
809 public boolean isEscapeHtmlInPropertyValue() {
810 return this.escapeHtmlInPropertyValue;
811 }
812
813 /**
814 * Indicates whether the value for the field is secure
815 *
816 * <p>
817 * A value will be secured if masking has been applied (by configuration or a failed KIM permission) or the field
818 * has been marked as hidden due to an authorization check
819 * </p>
820 *
821 * @return boolean true if value is secure, false if not
822 */
823 public boolean hasSecureValue() {
824 return isApplyValueMask() || ((getComponentSecurity().isViewAuthz()
825 || getComponentSecurity().isViewInLineAuthz()
826 || ((getComponentSecurity().getAttributeSecurity() != null) && getComponentSecurity()
827 .getAttributeSecurity().isHide())) && isHidden());
828 }
829
830 }