View Javadoc
1   /**
2    * Copyright 2005-2015 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.component;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.krad.datadictionary.parse.BeanTag;
20  import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
21  import org.kuali.rice.krad.datadictionary.uif.UifDictionaryBeanBase;
22  import org.kuali.rice.krad.datadictionary.validator.ValidationTrace;
23  import org.kuali.rice.krad.datadictionary.validator.Validator;
24  import org.kuali.rice.krad.uif.CssConstants;
25  import org.kuali.rice.krad.uif.UifConstants;
26  import org.kuali.rice.krad.uif.UifConstants.ViewStatus;
27  import org.kuali.rice.krad.uif.control.ControlBase;
28  import org.kuali.rice.krad.uif.field.DataField;
29  import org.kuali.rice.krad.uif.field.Field;
30  import org.kuali.rice.krad.uif.layout.CssGridSizes;
31  import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
32  import org.kuali.rice.krad.uif.lifecycle.ViewLifecyclePhase;
33  import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleRestriction;
34  import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleUtils;
35  import org.kuali.rice.krad.uif.modifier.ComponentModifier;
36  import org.kuali.rice.krad.uif.util.LifecycleAwareMap;
37  import org.kuali.rice.krad.uif.util.LifecycleElement;
38  import org.kuali.rice.krad.uif.util.ScriptUtils;
39  import org.kuali.rice.krad.uif.view.ExpressionEvaluator;
40  import org.kuali.rice.krad.uif.view.View;
41  import org.kuali.rice.krad.uif.view.ViewIndex;
42  import org.kuali.rice.krad.uif.widget.Tooltip;
43  import org.kuali.rice.krad.util.KRADConstants;
44  import org.kuali.rice.krad.util.KRADUtils;
45  import org.kuali.rice.krad.web.form.UifFormBase;
46  
47  import java.util.ArrayList;
48  import java.util.Collections;
49  import java.util.HashMap;
50  import java.util.LinkedHashSet;
51  import java.util.List;
52  import java.util.Map;
53  import java.util.Map.Entry;
54  import java.util.Set;
55  
56  /**
57   * Base implementation of Component which other component implementations should extend.
58   *
59   * <p>
60   * Provides base component properties such as id and template. Also provides default implementation
61   * for the <code>ScriptEventSupport</code> and <code>Ordered</code> interfaces. By default no script
62   * events except the onDocumentReady are supported.
63   * </p>
64   *
65   * @author Kuali Rice Team (rice.collab@kuali.org)
66   */
67  @BeanTag(name = "componentBase", parent = "Uif-ComponentBase")
68  public abstract class ComponentBase extends UifDictionaryBeanBase implements Component {
69  
70      private static final long serialVersionUID = -4449335748129894350L;
71  
72      private String id;
73      private String containerIdSuffix;
74      private String viewPath;
75      private Map<String, String> phasePathMapping;
76  
77      private String template;
78      private String templateName;
79  
80      private String viewStatus;
81  
82      private String title;
83  
84      private boolean render;
85      private boolean retrieveViaAjax;
86  
87      @KeepExpression
88      private String progressiveRender;
89      private boolean progressiveRenderViaAJAX;
90      private boolean progressiveRenderAndRefresh;
91      private List<String> progressiveDisclosureControlNames;
92      private String progressiveDisclosureConditionJs;
93  
94      @KeepExpression
95      private String conditionalRefresh;
96      private String conditionalRefreshConditionJs;
97      private List<String> conditionalRefreshControlNames;
98  
99      private List<String> refreshWhenChangedPropertyNames;
100     private List<String> additionalComponentsToRefresh;
101     private String additionalComponentsToRefreshJs;
102     private boolean refreshedByAction;
103     private boolean disclosedByAction;
104 
105     private int refreshTimer;
106 
107     private boolean resetDataOnRefresh;
108     private String methodToCallOnRefresh;
109     private List<String> fieldsToSendOnRefresh;
110 
111     private boolean hidden;
112     private Boolean readOnly;
113     private Boolean canCopyOnReadOnly;
114     private Boolean required;
115 
116     private String align;
117     private String valign;
118     private String width;
119 
120     // optional table-backed layout options
121     private int colSpan;
122     private int rowSpan;
123     private List<String> wrapperCssClasses;
124     private String wrapperStyle;
125     private String cellWidth;
126     private CssGridSizes cssGridSizes;
127 
128     private List<String> layoutCssClasses;
129 
130     private String style;
131 
132     private List<String> libraryCssClasses;
133     private List<String> cssClasses;
134     private List<String> additionalCssClasses;
135 
136     @DelayedCopy
137     private Tooltip toolTip;
138 
139     private int order;
140 
141     private boolean skipInTabOrder;
142 
143     private String finalizeMethodToCall;
144     private List<Object> finalizeMethodAdditionalArguments;
145     private MethodInvokerConfig finalizeMethodInvoker;
146 
147     private boolean selfRendered;
148     private String renderedHtmlOutput;
149 
150     private boolean disableSessionPersistence;
151     private boolean forceSessionPersistence;
152 
153     private ComponentSecurity componentSecurity;
154 
155     private String onLoadScript;
156     private String onUnloadScript;
157     private String onCloseScript;
158     private String onBlurScript;
159     private String onChangeScript;
160     private String onClickScript;
161     private String onDblClickScript;
162     private String onFocusScript;
163     private String onSubmitScript;
164     private String onInputScript;
165     private String onKeyPressScript;
166     private String onKeyUpScript;
167     private String onKeyDownScript;
168     private String onMouseOverScript;
169     private String onMouseOutScript;
170     private String onMouseUpScript;
171     private String onMouseDownScript;
172     private String onMouseMoveScript;
173     private String onDocumentReadyScript;
174 
175     private List<ComponentModifier> componentModifiers;
176 
177     protected Map<String, String> templateOptions;
178 
179     private String templateOptionsJSString;
180 
181     @ReferenceCopy(newCollectionInstance = true)
182     private transient Map<String, Object> context;
183 
184     private List<PropertyReplacer> propertyReplacers;
185 
186     private Map<String, String> dataAttributes;
187     private Map<String, String> scriptDataAttributes;
188 
189     private String role;
190     private Map<String, String> ariaAttributes;
191 
192     private String preRenderContent;
193     private String postRenderContent;
194 
195     private String excludeIf;
196     private String excludeUnless;
197 
198     private boolean omitFromFormPost;
199 
200     public ComponentBase() {
201         super();
202 
203         order = 0;
204         colSpan = 1;
205         rowSpan = 1;
206         cssGridSizes = new CssGridSizes();
207 
208         viewStatus = ViewStatus.CREATED;
209 
210         render = true;
211         canCopyOnReadOnly = false;
212         selfRendered = false;
213         progressiveRenderViaAJAX = false;
214         progressiveRenderAndRefresh = false;
215         refreshedByAction = false;
216         resetDataOnRefresh = false;
217         disableSessionPersistence = false;
218         forceSessionPersistence = false;
219 
220         phasePathMapping = new HashMap<String, String>();
221         context = Collections.emptyMap();
222         dataAttributes = Collections.emptyMap();
223         scriptDataAttributes = Collections.emptyMap();
224         ariaAttributes = Collections.emptyMap();
225         templateOptions = Collections.emptyMap();
226 
227         cssClasses = Collections.emptyList();
228         libraryCssClasses = Collections.emptyList();
229         additionalCssClasses = Collections.emptyList();
230     }
231 
232     /**
233      * {@inheritDoc}
234      */
235     @Override
236     public boolean skipLifecycle() {
237         return this.isRetrieveViaAjax();
238     }
239 
240     /**
241      * @see LifecycleElement#checkMutable(boolean)
242      */
243     public void checkMutable(boolean legalDuringInitialization) {
244         if (UifConstants.ViewStatus.CACHED.equals(viewStatus)) {
245             ViewLifecycle.reportIllegalState("Cached component " + getClass() + " " + getId()
246                     + " is immutable, use copy() to get a mutable instance");
247             return;
248         }
249 
250         if (ViewLifecycle.isActive()) {
251             return;
252         }
253 
254         if (UifConstants.ViewStatus.CREATED.equals(viewStatus) && !legalDuringInitialization) {
255             ViewLifecycle.reportIllegalState(
256                     "View has not been fully initialized, attempting to change component " + getClass() + " "
257                             + getId());
258             return;
259         }
260     }
261 
262     /**
263      * @see LifecycleElement#isMutable(boolean)
264      */
265     public boolean isMutable(boolean legalDuringInitialization) {
266         return (UifConstants.ViewStatus.CREATED.equals(viewStatus) && legalDuringInitialization) || ViewLifecycle
267                 .isActive();
268     }
269 
270     /**
271      * Indicates what lifecycle phase the component instance is in
272      *
273      * <p>
274      * The view lifecycle begins with the CREATED status. In this status a new instance of the view
275      * has been retrieved from the dictionary, but no further processing has been done. After the
276      * initialize phase has been run the status changes to INITIALIZED. After the model has been
277      * applied and the view is ready for render the status changes to FINAL
278      * </p>
279      *
280      * @return view status
281      *
282      * @see org.kuali.rice.krad.uif.UifConstants.ViewStatus
283      */
284     public String getViewStatus() {
285         return this.viewStatus;
286     }
287 
288     /**
289      * Setter for the view status
290      *
291      * @param status view status
292      */
293     @Override
294     public void setViewStatus(String status) {
295         if (!UifConstants.ViewStatus.CREATED.equals(status) && !UifConstants.ViewStatus.CACHED.equals(status)) {
296             checkMutable(true);
297         }
298 
299         this.viewStatus = status;
300     }
301 
302     /**
303      * {@inheritDoc}
304      */
305     @Override
306     public void notifyCompleted(ViewLifecyclePhase phase) {
307         if (!UifConstants.ViewPhases.PRE_PROCESS.equals(phase.getViewPhase())) {
308             ViewIndex viewIndex = ViewLifecycle.getView().getViewIndex();
309             if (viewIndex != null) {
310                 viewIndex.indexComponent(this);
311             }
312         }
313     }
314 
315     /**
316      * Indicates whether the component has been initialized.
317      *
318      * @return True if the component has been initialized, false if not.
319      */
320     public boolean isInitialized() {
321         return StringUtils.equals(viewStatus, ViewStatus.INITIALIZED) || isModelApplied();
322     }
323 
324     /**
325      * Indicates whether the component has been updated from the model.
326      *
327      * @return True if the component has been updated, false if not.
328      */
329     public boolean isModelApplied() {
330         return StringUtils.equals(viewStatus, ViewStatus.MODEL_APPLIED) || isFinal();
331     }
332 
333     /**
334      * Indicates whether the component has been updated from the model and final updates made.
335      *
336      * @return True if the component has been updated, false if not.
337      */
338     public boolean isFinal() {
339         return StringUtils.equals(viewStatus, ViewStatus.FINAL) || isRendered();
340     }
341 
342     /**
343      * Indicates whether the component has been fully rendered.
344      *
345      * @return True if the component has fully rendered, false if not.
346      */
347     public boolean isRendered() {
348         return StringUtils.equals(viewStatus, ViewStatus.RENDERED);
349     }
350 
351     /**
352      * The following updates are done here:
353      *
354      * <ul>
355      * <li>Invoke performInitialize on component modifiers</li>
356      * </ul>
357      *
358      * {@inheritDoc}
359      */
360     @Override
361     public void performInitialization(Object model) {
362         if (this.componentModifiers != null) {
363             for (ComponentModifier modifier : this.componentModifiers) {
364                 modifier.performInitialization(model, this);
365             }
366         }
367     }
368 
369     /**
370      * The following updates are done here:
371      *
372      * <ul>
373      * <li>Evaluate the progressive render condition (if set) and combine with the current render
374      * status to set the render status</li>
375      * </ul>
376      *
377      * {@inheritDoc}
378      */
379     @Override
380     public void performApplyModel(Object model, LifecycleElement parent) {
381         View view = ViewLifecycle.getView();
382 
383         if (this.render && StringUtils.isNotEmpty(progressiveRender)) {
384             // progressive anded with render, will not render at least one of the two are false
385             ExpressionEvaluator expressionEvaluator = ViewLifecycle.getExpressionEvaluator();
386 
387             String adjustedProgressiveRender = expressionEvaluator.replaceBindingPrefixes(view, this,
388                     progressiveRender);
389 
390             Boolean progRenderEval = (Boolean) expressionEvaluator.evaluateExpression(context,
391                     adjustedProgressiveRender);
392 
393             this.setRender(progRenderEval);
394         }
395     }
396 
397     /**
398      * No-op implementation.  Override for custom behavior in subclasses.
399      *
400      * {@inheritDoc}
401      */
402     @Override
403     public void afterEvaluateExpression() {
404     }
405 
406     /**
407      * The following finalization is done here:
408      *
409      * <ul>
410      * <li>progressiveRender and conditionalRefresh variables are processed if set</li>
411      * <li>If any of the style properties were given, sets the style string on the style property</li>
412      * <li>Set the skipInTabOrder flag for nested components</li>
413      * </ul>
414      *
415      * {@inheritDoc}
416      */
417     @Override
418     public void performFinalize(Object model, LifecycleElement parent) {
419         View view = ViewLifecycle.getView();
420         ExpressionEvaluator expressionEvaluator = ViewLifecycle.getExpressionEvaluator();
421         // progressiveRender expression setup
422         if (StringUtils.isNotEmpty(progressiveRender)) {
423             progressiveRender = expressionEvaluator.replaceBindingPrefixes(view, this, progressiveRender);
424             progressiveDisclosureControlNames = new ArrayList<String>();
425             progressiveDisclosureConditionJs = expressionEvaluator.parseExpression(progressiveRender,
426                     progressiveDisclosureControlNames, this.getContext());
427         }
428 
429         // conditional refresh expression setup
430         if (StringUtils.isNotEmpty(conditionalRefresh)) {
431             conditionalRefresh = expressionEvaluator.replaceBindingPrefixes(view, this, conditionalRefresh);
432             conditionalRefreshControlNames = new ArrayList<String>();
433             conditionalRefreshConditionJs = expressionEvaluator.parseExpression(conditionalRefresh,
434                     conditionalRefreshControlNames, this.getContext());
435         }
436 
437         if (refreshWhenChangedPropertyNames != null) {
438             List<String> adjustedRefreshPropertyNames = new ArrayList<String>(refreshWhenChangedPropertyNames.size());
439             for (String refreshPropertyName : refreshWhenChangedPropertyNames) {
440                 adjustedRefreshPropertyNames.add(expressionEvaluator.replaceBindingPrefixes(view, this,
441                         refreshPropertyName));
442             }
443             refreshWhenChangedPropertyNames = adjustedRefreshPropertyNames;
444             if (!retrieveViaAjax) {
445                 //need to add the "refresh" method so that regular calls will work
446                 ViewLifecycle.getViewPostMetadata().addAccessibleMethodToCall(KRADConstants.RETURN_METHOD_TO_CALL);
447             }
448         }
449 
450         // retrieveViaAjax forces session persistence because it assumes that this component will be retrieved by
451         // some ajax retrieval call
452         if (retrieveViaAjax) {
453             forceSessionPersistence = true;
454         }
455 
456         // add the align, valign, and width settings to style
457         if (StringUtils.isNotBlank(getAlign()) && !StringUtils.contains(getStyle(), CssConstants.TEXT_ALIGN)) {
458             appendToStyle(CssConstants.TEXT_ALIGN + getAlign() + ";");
459         }
460 
461         if (StringUtils.isNotBlank(getValign()) && !StringUtils.contains(getStyle(), CssConstants.VERTICAL_ALIGN)) {
462             appendToStyle(CssConstants.VERTICAL_ALIGN + getValign() + ";");
463         }
464 
465         if (StringUtils.isNotBlank(getWidth()) && !StringUtils.contains(getStyle(), CssConstants.WIDTH)) {
466             appendToStyle(CssConstants.WIDTH + getWidth() + ";");
467         }
468 
469         // Set the skipInTabOrder flag on all nested components
470         // Set the tabIndex on controls to -1 in order to be skipped on tabbing
471         if (skipInTabOrder) {
472             for (LifecycleElement component : ViewLifecycleUtils.getElementsForLifecycle(this).values()) {
473                 if (component != null && component instanceof ComponentBase) {
474                     ((ComponentBase) component).setSkipInTabOrder(skipInTabOrder);
475                     if (component instanceof ControlBase) {
476                         ((ControlBase) component).setTabIndex(-1);
477                     }
478                 }
479             }
480         }
481 
482         // if this is not rendering and it is not rendering via an ajax call, but still has a progressive render
483         // condition we still want to render the component, but hide it (in ajax cases, template creates a placeholder)
484         boolean hide = false;
485         if (!this.render && !this.progressiveRenderViaAJAX && !this.progressiveRenderAndRefresh && StringUtils
486                 .isNotBlank(progressiveRender)) {
487             hide = true;
488         } else if (this.isHidden()) {
489             hide = true;
490         }
491 
492         if (hide) {
493             if (StringUtils.isNotBlank(this.getStyle())) {
494                 if (this.getStyle().endsWith(";")) {
495                     this.setStyle(this.getStyle() + " display: none;");
496                 } else {
497                     this.setStyle(this.getStyle() + "; display: none;");
498                 }
499             } else {
500                 this.setStyle("display: none;");
501             }
502         }
503 
504         // setup refresh timer
505         // if the refreshTimer property has been set then pre-append the call to refreshComponetUsingTimer
506         // to the onDocumentReadyScript
507         if (refreshTimer > 0) {
508             String timerScript = getOnDocumentReadyScript();
509 
510             if (StringUtils.isBlank(this.methodToCallOnRefresh)) {
511                 this.methodToCallOnRefresh = "refresh";
512             }
513 
514             timerScript = (null == timerScript) ? "" : timerScript;
515             timerScript =
516                     "refreshComponentUsingTimer('" + this.id + "','" + this.methodToCallOnRefresh + "'," + refreshTimer
517                             + ");" + timerScript;
518 
519             setOnDocumentReadyScript(timerScript);
520         }
521 
522         // Add tooltip class
523         if (this.getToolTip() != null && StringUtils.isNotBlank(this.getToolTip().getTooltipContent())) {
524             this.addStyleClass(CssConstants.Classes.TOOLTIP);
525         }
526 
527         // put together all css class names for this component, in order
528         Set<String> finalCssClasses = new LinkedHashSet<>();
529 
530         if (libraryCssClasses != null && (!ViewLifecycle.isActive() || ViewLifecycle.getView()
531                 .isUseLibraryCssClasses())) {
532             finalCssClasses.addAll(libraryCssClasses);
533             libraryCssClasses.clear();
534         }
535 
536         if (cssClasses != null) {
537             finalCssClasses.addAll(cssClasses);
538             cssClasses.clear();
539         }
540 
541         if (additionalCssClasses != null) {
542             finalCssClasses.addAll(additionalCssClasses);
543             additionalCssClasses.clear();
544         }
545 
546         // need to do this since cssClasses may be unmodifiable
547         List<String> newCssClasses = new ArrayList<>();
548         newCssClasses.addAll(finalCssClasses);
549         cssClasses = newCssClasses;
550 
551         // add the method to call as an available method
552         if (StringUtils.isNotBlank(methodToCallOnRefresh)) {
553             ViewLifecycle.getViewPostMetadata().addAvailableMethodToCall(methodToCallOnRefresh);
554         }
555 
556         if ((isRender() || StringUtils.isNotBlank(getProgressiveRender())) && StringUtils.isNotBlank(
557                 methodToCallOnRefresh)) {
558             ViewLifecycle.getViewPostMetadata().addAccessibleMethodToCall(methodToCallOnRefresh);
559         }
560     }
561 
562     /**
563      * Returns list of components that are being held in property replacers configured for this
564      * component
565      *
566      * @return List<Component>
567      */
568     @ViewLifecycleRestriction
569     public List<Component> getPropertyReplacerComponents() {
570         if (propertyReplacers == null) {
571             return Collections.emptyList();
572         }
573 
574         List<Component> components = new ArrayList<Component>();
575         for (Object replacer : propertyReplacers) {
576             components.addAll(((PropertyReplacer) replacer).getNestedComponents());
577         }
578 
579         return components;
580     }
581 
582     /**
583      * {@inheritDoc}
584      */
585     @BeanTagAttribute
586     @Override
587     public String getId() {
588         return this.id;
589     }
590 
591     /**
592      * {@inheritDoc}
593      */
594     @Override
595     public void setId(String id) {
596         checkMutable(true);
597         this.id = id;
598     }
599 
600     /**
601      * {@inheritDoc}
602      */
603     @Override
604     public String getContainerIdSuffix() {
605         return containerIdSuffix;
606     }
607 
608     /**
609      * {@inheritDoc}
610      */
611     @Override
612     public void setContainerIdSuffix(String containerIdSuffix) {
613         this.containerIdSuffix = containerIdSuffix;
614     }
615 
616     /**
617      * {@inheritDoc}
618      */
619     @Override
620     public String getViewPath() {
621         return this.viewPath;
622     }
623 
624     /**
625      * {@inheritDoc}
626      */
627     @Override
628     public void setViewPath(String viewPath) {
629         checkMutable(true);
630         this.viewPath = viewPath;
631     }
632 
633     /**
634      * {@inheritDoc}
635      */
636     @Override
637     public Map<String, String> getPhasePathMapping() {
638         return phasePathMapping;
639     }
640 
641     /**
642      * {@inheritDoc}
643      */
644     @Override
645     public void setPhasePathMapping(Map<String, String> phasePathMapping) {
646         this.phasePathMapping = phasePathMapping;
647     }
648 
649     /**
650      * {@inheritDoc}
651      */
652     @BeanTagAttribute
653     @Override
654     public String getTemplate() {
655         return this.template;
656     }
657 
658     /**
659      * {@inheritDoc}
660      */
661     @Override
662     public void setTemplate(String template) {
663         checkMutable(true);
664         this.template = template;
665     }
666 
667     /**
668      * {@inheritDoc}
669      */
670     @Override
671     public List<String> getAdditionalTemplates() {
672         return Collections.emptyList();
673     }
674 
675     /**
676      * {@inheritDoc}
677      */
678     @BeanTagAttribute
679     @Override
680     public String getTemplateName() {
681         return templateName;
682     }
683 
684     /**
685      * {@inheritDoc}
686      */
687     @Override
688     public void setTemplateName(String templateName) {
689         checkMutable(true);
690         this.templateName = templateName;
691     }
692 
693     /**
694      * {@inheritDoc}
695      */
696     @BeanTagAttribute
697     @Override
698     public String getTitle() {
699         return this.title;
700     }
701 
702     /**
703      * {@inheritDoc}
704      */
705     @Override
706     public void setTitle(String title) {
707         checkMutable(true);
708         this.title = title;
709     }
710 
711     /**
712      * {@inheritDoc}
713      */
714     @BeanTagAttribute
715     @Override
716     public boolean isHidden() {
717         return this.hidden;
718     }
719 
720     /**
721      * {@inheritDoc}
722      */
723     @Override
724     public void setHidden(boolean hidden) {
725         checkMutable(true);
726         this.hidden = hidden;
727     }
728 
729     /**
730      * {@inheritDoc}
731      */
732     @BeanTagAttribute
733     @Override
734     public Boolean getReadOnly() {
735         return this.readOnly;
736     }
737 
738     /**
739      * {@inheritDoc}
740      */
741     @Override
742     public void setReadOnly(Boolean readOnly) {
743         checkMutable(true);
744         this.readOnly = readOnly;
745     }
746 
747     /**
748      * {@inheritDoc}
749      */
750     @Override
751     public Boolean getCanCopyOnReadOnly() {
752         return canCopyOnReadOnly;
753     }
754 
755     /**
756      * {@inheritDoc}
757      */
758     @Override
759     public void setCanCopyOnReadOnly(Boolean canCopyOnReadOnly) {
760         this.canCopyOnReadOnly = canCopyOnReadOnly;
761     }
762 
763 
764     /**
765      * {@inheritDoc}
766      */
767     @BeanTagAttribute
768     @Override
769     public Boolean getRequired() {
770         return this.required;
771     }
772 
773     /**
774      * {@inheritDoc}
775      */
776     @Override
777     public void setRequired(Boolean required) {
778         checkMutable(true);
779         this.required = required;
780     }
781 
782     /**
783      * {@inheritDoc}
784      */
785     @BeanTagAttribute
786     @Override
787     public boolean isRender() {
788         return this.render;
789     }
790 
791     /**
792      * {@inheritDoc}
793      */
794     @Override
795     public void setRender(boolean render) {
796         checkMutable(true);
797         this.render = render;
798     }
799 
800     /**
801      * {@inheritDoc}
802      */
803     @BeanTagAttribute
804     @Override
805     public boolean isRetrieveViaAjax() {
806         return retrieveViaAjax;
807     }
808 
809     /**
810      * {@inheritDoc}
811      */
812     @Override
813     public void setRetrieveViaAjax(boolean retrieveViaAjax) {
814         checkMutable(true);
815         this.retrieveViaAjax = retrieveViaAjax;
816     }
817 
818     /**
819      * {@inheritDoc}
820      */
821     @BeanTagAttribute
822     @Override
823     public int getColSpan() {
824         return this.colSpan;
825     }
826 
827     /**
828      * {@inheritDoc}
829      */
830     @Override
831     public void setColSpan(int colSpan) {
832         checkMutable(true);
833         this.colSpan = colSpan;
834     }
835 
836     /**
837      * {@inheritDoc}
838      */
839     @BeanTagAttribute
840     @Override
841     public int getRowSpan() {
842         return this.rowSpan;
843     }
844 
845     /**
846      * {@inheritDoc}
847      */
848     @Override
849     public void setRowSpan(int rowSpan) {
850         checkMutable(true);
851         this.rowSpan = rowSpan;
852     }
853 
854     /**
855      * {@inheritDoc}
856      */
857     @BeanTagAttribute
858     @Override
859     public List<String> getWrapperCssClasses() {
860         return wrapperCssClasses;
861     }
862 
863     /**
864      * {@inheritDoc}
865      */
866     @Override
867     public void setWrapperCssClasses(List<String> wrapperCssClasses) {
868         checkMutable(true);
869         this.wrapperCssClasses = wrapperCssClasses;
870     }
871 
872     /**
873      * {@inheritDoc}
874      */
875     @Override
876     public void addWrapperCssClass(String cssClass) {
877         checkMutable(false);
878         if (this.wrapperCssClasses == null) {
879             this.wrapperCssClasses = new ArrayList<String>();
880         }
881 
882         if (cssClass != null) {
883             this.wrapperCssClasses.add(cssClass);
884         }
885     }
886 
887     /**
888      * Builds the HTML class attribute string by combining the cellStyleClasses list with a space
889      * delimiter.
890      *
891      * @return class attribute string
892      */
893     public String getWrapperCssClassesAsString() {
894         if (wrapperCssClasses != null) {
895             return StringUtils.join(wrapperCssClasses, " ").trim();
896         }
897 
898         return "";
899     }
900 
901     /**
902      * {@inheritDoc}
903      */
904     @BeanTagAttribute
905     @Override
906     public String getWrapperStyle() {
907         return wrapperStyle;
908     }
909 
910     /**
911      * {@inheritDoc}
912      */
913     @Override
914     public void setWrapperStyle(String wrapperStyle) {
915         checkMutable(true);
916         this.wrapperStyle = wrapperStyle;
917     }
918 
919     /**
920      * {@inheritDoc}
921      */
922     @BeanTagAttribute
923     @Override
924     public String getCellWidth() {
925         return cellWidth;
926     }
927 
928     /**
929      * {@inheritDoc}
930      */
931     @Override
932     public void setCellWidth(String cellWidth) {
933         checkMutable(true);
934         this.cellWidth = cellWidth;
935     }
936 
937     /**
938      * {@inheritDoc}
939      */
940     @Override
941     @BeanTagAttribute
942     public CssGridSizes getCssGridSizes() {
943         return cssGridSizes;
944     }
945 
946     /**
947      * {@inheritDoc}
948      */
949     @Override
950     public void setCssGridSizes(CssGridSizes cssGridSizes) {
951         this.cssGridSizes = cssGridSizes;
952     }
953 
954     /**
955      * {@inheritDoc}
956      */
957     @Override
958     @BeanTagAttribute
959     public String getAlign() {
960         return this.align;
961     }
962 
963     /**
964      * {@inheritDoc}
965      */
966     @Override
967     public void setAlign(String align) {
968         checkMutable(true);
969         this.align = align;
970     }
971 
972     /**
973      * {@inheritDoc}
974      */
975     @Override
976     @BeanTagAttribute
977     public String getValign() {
978         return this.valign;
979     }
980 
981     /**
982      * {@inheritDoc}
983      */
984     @Override
985     public void setValign(String valign) {
986         checkMutable(true);
987         this.valign = valign;
988     }
989 
990     /**
991      * {@inheritDoc}
992      */
993     @Override
994     @BeanTagAttribute
995     public String getWidth() {
996         return this.width;
997     }
998 
999     /**
1000      * {@inheritDoc}
1001      */
1002     @Override
1003     public void setWidth(String width) {
1004         checkMutable(true);
1005         this.width = width;
1006     }
1007 
1008     /**
1009      * {@inheritDoc}
1010      */
1011     @Override
1012     @BeanTagAttribute
1013     public String getStyle() {
1014         return this.style;
1015     }
1016 
1017     /**
1018      * {@inheritDoc}
1019      */
1020     @Override
1021     public void setStyle(String style) {
1022         checkMutable(true);
1023         this.style = style;
1024     }
1025 
1026     /**
1027      * Additional css classes that come before css classes listed in the cssClasses property
1028      *
1029      * <p>
1030      * These are used by the framework for styling with a library (for example, bootstrap), and
1031      * should normally not be overridden.
1032      * </p>
1033      *
1034      * @return the library cssClasses
1035      */
1036     public List<String> getLibraryCssClasses() {
1037         if (libraryCssClasses == Collections.EMPTY_LIST && isMutable(true)) {
1038             libraryCssClasses = new ArrayList<String>();
1039         }
1040 
1041         return libraryCssClasses;
1042     }
1043 
1044     /**
1045      * Set the libraryCssClasses
1046      */
1047     public void setLibraryCssClasses(List<String> libraryCssClasses) {
1048         checkMutable(true);
1049 
1050         if (libraryCssClasses == null) {
1051             this.libraryCssClasses = Collections.emptyList();
1052         } else {
1053             this.libraryCssClasses = libraryCssClasses;
1054         }
1055     }
1056 
1057     /**
1058      * {@inheritDoc}
1059      */
1060     @Override
1061     @BeanTagAttribute
1062     public List<String> getCssClasses() {
1063         if (cssClasses == Collections.EMPTY_LIST && isMutable(true)) {
1064             cssClasses = new ArrayList<String>();
1065         }
1066 
1067         return cssClasses;
1068     }
1069 
1070     /**
1071      * {@inheritDoc}
1072      */
1073     @Override
1074     public void setCssClasses(List<String> cssClasses) {
1075         checkMutable(true);
1076 
1077         if (cssClasses == null) {
1078             this.cssClasses = Collections.emptyList();
1079         } else {
1080             this.cssClasses = cssClasses;
1081         }
1082     }
1083 
1084     /**
1085      * {@inheritDoc}
1086      */
1087     @Override
1088     @BeanTagAttribute
1089     public List<String> getAdditionalCssClasses() {
1090         if (additionalCssClasses == Collections.EMPTY_LIST && isMutable(true)) {
1091             additionalCssClasses = new ArrayList<String>();
1092         }
1093 
1094         return additionalCssClasses;
1095     }
1096 
1097     /**
1098      * {@inheritDoc}
1099      */
1100     @Override
1101     public void setAdditionalCssClasses(List<String> additionalCssClasses) {
1102         checkMutable(true);
1103         if (additionalCssClasses == null) {
1104             this.additionalCssClasses = Collections.emptyList();
1105         } else {
1106             this.additionalCssClasses = additionalCssClasses;
1107         }
1108     }
1109 
1110     /**
1111      * Builds the HTML class attribute string by combining the styleClasses list with a space
1112      * delimiter
1113      *
1114      * @return class attribute string
1115      */
1116     public String getStyleClassesAsString() {
1117         if (cssClasses != null) {
1118             return StringUtils.join(cssClasses, " ").trim();
1119         }
1120 
1121         return "";
1122     }
1123 
1124     /**
1125      * {@inheritDoc}
1126      */
1127     @Override
1128     public void addStyleClass(String styleClass) {
1129         checkMutable(false);
1130         if (StringUtils.isEmpty(styleClass)) {
1131             return;
1132         }
1133 
1134         if (cssClasses.isEmpty()) {
1135             setCssClasses(new ArrayList<String>());
1136         }
1137 
1138         if (!cssClasses.contains(styleClass)) {
1139             cssClasses.add(styleClass);
1140         }
1141     }
1142 
1143     /**
1144      * {@inheritDoc}
1145      */
1146     @Override
1147     public void appendToStyle(String styleRules) {
1148         checkMutable(false);
1149         if (style == null) {
1150             style = "";
1151         }
1152         style = style + styleRules;
1153     }
1154 
1155     /**
1156      * {@inheritDoc}
1157      */
1158     @Override
1159     @BeanTagAttribute
1160     public String getFinalizeMethodToCall() {
1161         return this.finalizeMethodToCall;
1162     }
1163 
1164     /**
1165      * Setter for the finalize method
1166      */
1167     public void setFinalizeMethodToCall(String finalizeMethodToCall) {
1168         checkMutable(true);
1169         this.finalizeMethodToCall = finalizeMethodToCall;
1170     }
1171 
1172     /**
1173      * {@inheritDoc}
1174      */
1175     @Override
1176     @BeanTagAttribute
1177     public List<Object> getFinalizeMethodAdditionalArguments() {
1178         return finalizeMethodAdditionalArguments;
1179     }
1180 
1181     /**
1182      * Setter for the finalize additional arguments list
1183      */
1184     public void setFinalizeMethodAdditionalArguments(List<Object> finalizeMethodAdditionalArguments) {
1185         checkMutable(true);
1186         this.finalizeMethodAdditionalArguments = finalizeMethodAdditionalArguments;
1187     }
1188 
1189     /**
1190      * {@inheritDoc}
1191      */
1192     @Override
1193     @BeanTagAttribute
1194     public MethodInvokerConfig getFinalizeMethodInvoker() {
1195         return this.finalizeMethodInvoker;
1196     }
1197 
1198     /**
1199      * Setter for the method invoker instance
1200      */
1201     public void setFinalizeMethodInvoker(MethodInvokerConfig finalizeMethodInvoker) {
1202         checkMutable(true);
1203         this.finalizeMethodInvoker = finalizeMethodInvoker;
1204     }
1205 
1206     /**
1207      * {@inheritDoc}
1208      */
1209     @Override
1210     @BeanTagAttribute
1211     public boolean isSelfRendered() {
1212         return this.selfRendered;
1213     }
1214 
1215     /**
1216      * {@inheritDoc}
1217      */
1218     @Override
1219     public void setSelfRendered(boolean selfRendered) {
1220         this.selfRendered = selfRendered;
1221     }
1222 
1223     /**
1224      * {@inheritDoc}
1225      */
1226     @Override
1227     @BeanTagAttribute
1228     public String getRenderedHtmlOutput() {
1229         return this.renderedHtmlOutput;
1230     }
1231 
1232     /**
1233      * {@inheritDoc}
1234      */
1235     @Override
1236     public void setRenderedHtmlOutput(String renderedHtmlOutput) {
1237         this.renderedHtmlOutput = renderedHtmlOutput;
1238     }
1239 
1240     /**
1241      * {@inheritDoc}
1242      */
1243     @Override
1244     @BeanTagAttribute
1245     public boolean isDisableSessionPersistence() {
1246         return disableSessionPersistence;
1247     }
1248 
1249     /**
1250      * {@inheritDoc}
1251      */
1252     @Override
1253     public void setDisableSessionPersistence(boolean disableSessionPersistence) {
1254         checkMutable(true);
1255         this.disableSessionPersistence = disableSessionPersistence;
1256     }
1257 
1258     /**
1259      * {@inheritDoc}
1260      */
1261     @Override
1262     @BeanTagAttribute
1263     public boolean isForceSessionPersistence() {
1264         return forceSessionPersistence;
1265     }
1266 
1267     /**
1268      * {@inheritDoc}
1269      */
1270     @Override
1271     public void setForceSessionPersistence(boolean forceSessionPersistence) {
1272         checkMutable(true);
1273         this.forceSessionPersistence = forceSessionPersistence;
1274     }
1275 
1276     /**
1277      * {@inheritDoc}
1278      */
1279     @Override
1280     @BeanTagAttribute(type = BeanTagAttribute.AttributeType.DIRECTORBYTYPE)
1281     public ComponentSecurity getComponentSecurity() {
1282         return componentSecurity;
1283     }
1284 
1285     /**
1286      * {@inheritDoc}
1287      */
1288     @Override
1289     public void setComponentSecurity(ComponentSecurity componentSecurity) {
1290         checkMutable(true);
1291         this.componentSecurity = componentSecurity;
1292     }
1293 
1294     /**
1295      * Initializes (if necessary) the component security instance for the component type
1296      */
1297     protected void initializeComponentSecurity() {
1298         if (this.componentSecurity == null) {
1299             this.componentSecurity = KRADUtils.createNewObjectFromClass(ComponentSecurity.class);
1300         }
1301     }
1302 
1303     /**
1304      * @see org.kuali.rice.krad.uif.component.ComponentSecurity#isEditAuthz()
1305      */
1306     @BeanTagAttribute
1307     public Boolean isEditAuthz() {
1308         initializeComponentSecurity();
1309 
1310         return this.componentSecurity.isEditAuthz();
1311     }
1312 
1313     /**
1314      * Setter for {@link #isEditAuthz()}
1315      *
1316      * @param editAuthz property value
1317      */
1318     public void setEditAuthz(Boolean editAuthz) {
1319         checkMutable(true);
1320         initializeComponentSecurity();
1321 
1322         this.componentSecurity.setEditAuthz(editAuthz);
1323     }
1324 
1325     /**
1326      * @see org.kuali.rice.krad.uif.component.ComponentSecurity#isViewAuthz()
1327      */
1328     @BeanTagAttribute
1329     public Boolean isViewAuthz() {
1330         initializeComponentSecurity();
1331 
1332         return this.componentSecurity.isViewAuthz();
1333     }
1334 
1335     /**
1336      * Setter for {@link #isViewAuthz()}
1337      *
1338      * @param viewAuthz property value
1339      */
1340     public void setViewAuthz(Boolean viewAuthz) {
1341         checkMutable(true);
1342         initializeComponentSecurity();
1343 
1344         this.componentSecurity.setViewAuthz(viewAuthz);
1345     }
1346 
1347     /**
1348      * {@inheritDoc}
1349      */
1350     @Override
1351     @BeanTagAttribute
1352     public List<ComponentModifier> getComponentModifiers() {
1353         return this.componentModifiers;
1354     }
1355 
1356     /**
1357      * {@inheritDoc}
1358      */
1359     @Override
1360     public void setComponentModifiers(List<ComponentModifier> componentModifiers) {
1361         checkMutable(true);
1362         this.componentModifiers =
1363                 componentModifiers == null ? Collections.<ComponentModifier>emptyList() : componentModifiers;
1364     }
1365 
1366     /**
1367      * {@inheritDoc}
1368      */
1369     @Override
1370     @BeanTagAttribute
1371     public Map<String, Object> getContext() {
1372         if (context == Collections.EMPTY_MAP && isMutable(true)) {
1373             context = new HashMap<String, Object>();
1374         }
1375 
1376         return context;
1377     }
1378 
1379     /**
1380      * {@inheritDoc}
1381      */
1382     @Override
1383     public void setContext(Map<String, Object> context) {
1384         checkMutable(true);
1385 
1386         if (context == null) {
1387             this.context = Collections.emptyMap();
1388         } else {
1389             this.context = context;
1390         }
1391     }
1392 
1393     /**
1394      * {@inheritDoc}
1395      */
1396     @Override
1397     public void pushObjectToContext(String objectName, Object object) {
1398         checkMutable(true);
1399         if (context == Collections.EMPTY_MAP && isMutable(true)) {
1400             context = new HashMap<String, Object>();
1401         }
1402 
1403         pushToPropertyReplacerContext(objectName, object);
1404         context.put(objectName, object);
1405     }
1406 
1407     /*
1408     * Adds the object to the context of the components in the
1409     * PropertyReplacer object. Only checks for a list, map or component.
1410     */
1411     protected void pushToPropertyReplacerContext(String objectName, Object object) {
1412         checkMutable(true);
1413         List<Component> propertyReplacerComponents = getPropertyReplacerComponents();
1414         if (propertyReplacerComponents != null) {
1415             for (Component replacerComponent : propertyReplacerComponents) {
1416                 replacerComponent.pushObjectToContext(objectName, object);
1417             }
1418         }
1419     }
1420 
1421     /**
1422      * {@inheritDoc}
1423      */
1424     @Override
1425     public void pushAllToContext(Map<String, Object> objects) {
1426         checkMutable(true);
1427         if (objects == null || objects.isEmpty()) {
1428             return;
1429         }
1430 
1431         if (context == Collections.EMPTY_MAP && isMutable(true)) {
1432             context = new HashMap<String, Object>();
1433         }
1434 
1435         context.putAll(objects);
1436 
1437         List<Component> propertyReplacerComponents = getPropertyReplacerComponents();
1438         if (propertyReplacerComponents != null) {
1439             for (Component replacerComponent : propertyReplacerComponents) {
1440                 replacerComponent.pushAllToContext(objects);
1441             }
1442         }
1443     }
1444 
1445     /**
1446      * {@inheritDoc}
1447      */
1448     @Override
1449     @BeanTagAttribute
1450     public List<PropertyReplacer> getPropertyReplacers() {
1451         return this.propertyReplacers;
1452     }
1453 
1454     /**
1455      * {@inheritDoc}
1456      */
1457     @Override
1458     public void setPropertyReplacers(List<PropertyReplacer> propertyReplacers) {
1459         checkMutable(true);
1460         this.propertyReplacers =
1461                 propertyReplacers == null ? Collections.<PropertyReplacer>emptyList() : propertyReplacers;
1462     }
1463 
1464     /**
1465      * {@inheritDoc}
1466      */
1467     @Override
1468     @BeanTagAttribute
1469     public int getOrder() {
1470         return this.order;
1471     }
1472 
1473     /**
1474      * Setter for the component's order
1475      */
1476     public void setOrder(int order) {
1477         checkMutable(true);
1478         this.order = order;
1479     }
1480 
1481     /**
1482      * {@inheritDoc}
1483      */
1484     @Override
1485     @BeanTagAttribute(type = BeanTagAttribute.AttributeType.DIRECTORBYTYPE)
1486     public Tooltip getToolTip() {
1487         return toolTip;
1488     }
1489 
1490     /**
1491      * {@inheritDoc}
1492      */
1493     @Override
1494     public void setToolTip(Tooltip toolTip) {
1495         checkMutable(true);
1496         this.toolTip = toolTip;
1497     }
1498 
1499     /**
1500      * {@inheritDoc}
1501      */
1502     @Override
1503     public String getEventHandlerScript() {
1504         StringBuilder sb = new StringBuilder();
1505 
1506         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "load", getOnLoadScript()));
1507 
1508         // special handling for ready since it needs to bind to the document
1509         if (StringUtils.isNotBlank(getOnDocumentReadyScript())) {
1510             sb.append("jQuery(document).ready(function(e) {");
1511             sb.append(getOnDocumentReadyScript());
1512             sb.append("});");
1513         }
1514 
1515         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "unload", getOnUnloadScript()));
1516         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "blur", getOnBlurScript()));
1517         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "change", getOnChangeScript()));
1518         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "click", getOnClickScript()));
1519         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "dblclick", getOnDblClickScript()));
1520         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "focus", getOnFocusScript()));
1521         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "input", getOnInputScript()));
1522         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "keypress", getOnKeyPressScript()));
1523         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "keyup", getOnKeyUpScript()));
1524         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "keydown", getOnKeyDownScript()));
1525         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "mouseover", getOnMouseOverScript()));
1526         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "mouseout", getOnMouseOutScript()));
1527         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "mouseup", getOnMouseUpScript()));
1528         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "mousedown", getOnMouseDownScript()));
1529         sb.append(ScriptUtils.buildEventHandlerScript(getId(), "mousemove", getOnMouseMoveScript()));
1530 
1531         return sb.toString();
1532     }
1533 
1534     /**
1535      * {@inheritDoc}
1536      */
1537     @Override
1538     @BeanTagAttribute
1539     public String getOnLoadScript() {
1540         return onLoadScript;
1541     }
1542 
1543     /**
1544      * @see ScriptEventSupport#setOnLoadScript(java.lang.String)
1545      */
1546     public void setOnLoadScript(String onLoadScript) {
1547         checkMutable(true);
1548         this.onLoadScript = onLoadScript;
1549     }
1550 
1551     /**
1552      * {@inheritDoc}
1553      */
1554     @Override
1555     @BeanTagAttribute
1556     public String getOnDocumentReadyScript() {
1557         return this.onDocumentReadyScript;
1558     }
1559 
1560     /**
1561      * @see ScriptEventSupport#setOnDocumentReadyScript(java.lang.String)
1562      */
1563     public void setOnDocumentReadyScript(String onDocumentReadyScript) {
1564         checkMutable(true);
1565         this.onDocumentReadyScript = onDocumentReadyScript;
1566     }
1567 
1568     /**
1569      * {@inheritDoc}
1570      */
1571     @Override
1572     @BeanTagAttribute
1573     public String getOnUnloadScript() {
1574         return onUnloadScript;
1575     }
1576 
1577     /**
1578      * @see ScriptEventSupport#setOnUnloadScript(java.lang.String)
1579      */
1580     @Override
1581     public void setOnUnloadScript(String onUnloadScript) {
1582         checkMutable(true);
1583         this.onUnloadScript = onUnloadScript;
1584     }
1585 
1586     /**
1587      * {@inheritDoc}
1588      */
1589     @Override
1590     @BeanTagAttribute
1591     public String getOnCloseScript() {
1592         return onCloseScript;
1593     }
1594 
1595     /**
1596      * @see ScriptEventSupport#setOnCloseScript(java.lang.String)
1597      */
1598     @Override
1599     public void setOnCloseScript(String onCloseScript) {
1600         checkMutable(true);
1601         this.onCloseScript = onCloseScript;
1602     }
1603 
1604     /**
1605      * {@inheritDoc}
1606      */
1607     @Override
1608     @BeanTagAttribute
1609     public String getOnBlurScript() {
1610         return onBlurScript;
1611     }
1612 
1613     /**
1614      * @see ScriptEventSupport#setOnBlurScript(java.lang.String)
1615      */
1616     @Override
1617     public void setOnBlurScript(String onBlurScript) {
1618         checkMutable(true);
1619         this.onBlurScript = onBlurScript;
1620     }
1621 
1622     /**
1623      * {@inheritDoc}
1624      */
1625     @Override
1626     @BeanTagAttribute
1627     public String getOnChangeScript() {
1628         return onChangeScript;
1629     }
1630 
1631     /**
1632      * @see ScriptEventSupport#setOnChangeScript(java.lang.String)
1633      */
1634     @Override
1635     public void setOnChangeScript(String onChangeScript) {
1636         checkMutable(true);
1637         this.onChangeScript = onChangeScript;
1638     }
1639 
1640     /**
1641      * {@inheritDoc}
1642      */
1643     @Override
1644     @BeanTagAttribute
1645     public String getOnClickScript() {
1646         return onClickScript;
1647     }
1648 
1649     /**
1650      * @see ScriptEventSupport#setOnClickScript(java.lang.String)
1651      */
1652     @Override
1653     public void setOnClickScript(String onClickScript) {
1654         checkMutable(true);
1655         this.onClickScript = onClickScript;
1656     }
1657 
1658     /**
1659      * {@inheritDoc}
1660      */
1661     @Override
1662     @BeanTagAttribute
1663     public String getOnDblClickScript() {
1664         return onDblClickScript;
1665     }
1666 
1667     /**
1668      * @see ScriptEventSupport#setOnDblClickScript(java.lang.String)
1669      */
1670     @Override
1671     public void setOnDblClickScript(String onDblClickScript) {
1672         checkMutable(true);
1673         this.onDblClickScript = onDblClickScript;
1674     }
1675 
1676     /**
1677      * {@inheritDoc}
1678      */
1679     @Override
1680     @BeanTagAttribute
1681     public String getOnFocusScript() {
1682         return onFocusScript;
1683     }
1684 
1685     /**
1686      * @see ScriptEventSupport#setOnFocusScript(java.lang.String)
1687      */
1688     @Override
1689     public void setOnFocusScript(String onFocusScript) {
1690         checkMutable(true);
1691         this.onFocusScript = onFocusScript;
1692     }
1693 
1694     /**
1695      * {@inheritDoc}
1696      */
1697     @Override
1698     @BeanTagAttribute
1699     public String getOnSubmitScript() {
1700         return onSubmitScript;
1701     }
1702 
1703     /**
1704      * @see ScriptEventSupport#setOnSubmitScript(java.lang.String)
1705      */
1706     @Override
1707     public void setOnSubmitScript(String onSubmitScript) {
1708         checkMutable(true);
1709         this.onSubmitScript = onSubmitScript;
1710     }
1711 
1712     /**
1713      * {@inheritDoc}
1714      */
1715     @Override
1716     @BeanTagAttribute
1717     public String getOnInputScript() {
1718         return onInputScript;
1719     }
1720 
1721     /**
1722      * @see ScriptEventSupport#setOnInputScript(java.lang.String)
1723      */
1724     @Override
1725     public void setOnInputScript(String onInputScript) {
1726         checkMutable(true);
1727         this.onInputScript = onInputScript;
1728     }
1729 
1730     /**
1731      * {@inheritDoc}
1732      */
1733     @Override
1734     @BeanTagAttribute
1735     public String getOnKeyPressScript() {
1736         return onKeyPressScript;
1737     }
1738 
1739     /**
1740      * @see ScriptEventSupport#setOnKeyPressScript(java.lang.String)
1741      */
1742     @Override
1743     public void setOnKeyPressScript(String onKeyPressScript) {
1744         checkMutable(true);
1745         this.onKeyPressScript = onKeyPressScript;
1746     }
1747 
1748     /**
1749      * {@inheritDoc}
1750      */
1751     @Override
1752     @BeanTagAttribute
1753     public String getOnKeyUpScript() {
1754         return onKeyUpScript;
1755     }
1756 
1757     /**
1758      * @see ScriptEventSupport#setOnKeyUpScript(java.lang.String)
1759      */
1760     @Override
1761     public void setOnKeyUpScript(String onKeyUpScript) {
1762         checkMutable(true);
1763         this.onKeyUpScript = onKeyUpScript;
1764     }
1765 
1766     /**
1767      * {@inheritDoc}
1768      */
1769     @Override
1770     @BeanTagAttribute
1771     public String getOnKeyDownScript() {
1772         return onKeyDownScript;
1773     }
1774 
1775     /**
1776      * @see ScriptEventSupport#setOnKeyDownScript(java.lang.String)
1777      */
1778     @Override
1779     public void setOnKeyDownScript(String onKeyDownScript) {
1780         checkMutable(true);
1781         this.onKeyDownScript = onKeyDownScript;
1782     }
1783 
1784     /**
1785      * {@inheritDoc}
1786      */
1787     @Override
1788     @BeanTagAttribute
1789     public String getOnMouseOverScript() {
1790         return onMouseOverScript;
1791     }
1792 
1793     /**
1794      * @see ScriptEventSupport#setOnMouseOverScript(java.lang.String)
1795      */
1796     @Override
1797     public void setOnMouseOverScript(String onMouseOverScript) {
1798         checkMutable(true);
1799         this.onMouseOverScript = onMouseOverScript;
1800     }
1801 
1802     /**
1803      * {@inheritDoc}
1804      */
1805     @Override
1806     @BeanTagAttribute
1807     public String getOnMouseOutScript() {
1808         return onMouseOutScript;
1809     }
1810 
1811     /**
1812      * @see ScriptEventSupport#setOnMouseOutScript(java.lang.String)
1813      */
1814     @Override
1815     public void setOnMouseOutScript(String onMouseOutScript) {
1816         checkMutable(true);
1817         this.onMouseOutScript = onMouseOutScript;
1818     }
1819 
1820     /**
1821      * {@inheritDoc}
1822      */
1823     @Override
1824     @BeanTagAttribute
1825     public String getOnMouseUpScript() {
1826         return onMouseUpScript;
1827     }
1828 
1829     /**
1830      * @see ScriptEventSupport#setOnMouseUpScript(java.lang.String)
1831      */
1832     @Override
1833     public void setOnMouseUpScript(String onMouseUpScript) {
1834         checkMutable(true);
1835         this.onMouseUpScript = onMouseUpScript;
1836     }
1837 
1838     /**
1839      * {@inheritDoc}
1840      */
1841     @Override
1842     @BeanTagAttribute
1843     public String getOnMouseDownScript() {
1844         return onMouseDownScript;
1845     }
1846 
1847     /**
1848      * @see ScriptEventSupport#setOnMouseDownScript(java.lang.String)
1849      */
1850     @Override
1851     public void setOnMouseDownScript(String onMouseDownScript) {
1852         checkMutable(true);
1853         this.onMouseDownScript = onMouseDownScript;
1854     }
1855 
1856     /**
1857      * {@inheritDoc}
1858      */
1859     @Override
1860     @BeanTagAttribute
1861     public String getOnMouseMoveScript() {
1862         return onMouseMoveScript;
1863     }
1864 
1865     /**
1866      * @see ScriptEventSupport#setOnMouseMoveScript(java.lang.String)
1867      */
1868     @Override
1869     public void setOnMouseMoveScript(String onMouseMoveScript) {
1870         checkMutable(true);
1871         this.onMouseMoveScript = onMouseMoveScript;
1872     }
1873 
1874     /**
1875      * {@inheritDoc}
1876      */
1877     @Override
1878     @BeanTagAttribute
1879     public Map<String, String> getTemplateOptions() {
1880         if (templateOptions == Collections.EMPTY_MAP && isMutable(true)) {
1881             templateOptions = new HashMap<String, String>();
1882         }
1883 
1884         return templateOptions;
1885     }
1886 
1887     /**
1888      * {@inheritDoc}
1889      */
1890     @Override
1891     public void setTemplateOptions(Map<String, String> templateOptions) {
1892         checkMutable(true);
1893         if (templateOptions == null) {
1894             this.templateOptions = Collections.emptyMap();
1895         } else {
1896             this.templateOptions = templateOptions;
1897         }
1898     }
1899 
1900     /**
1901      * {@inheritDoc}
1902      */
1903     @Override
1904     @BeanTagAttribute
1905     public String getTemplateOptionsJSString() {
1906         if (templateOptionsJSString != null) {
1907             return templateOptionsJSString;
1908         }
1909 
1910         if (templateOptions == null) {
1911             return "{}";
1912         }
1913 
1914         StringBuilder sb = new StringBuilder();
1915         sb.append("{");
1916 
1917         for (Entry<String, String> option : templateOptions.entrySet()) {
1918 
1919             if (sb.length() > 1) {
1920                 sb.append(",");
1921             }
1922 
1923             sb.append(option.getKey());
1924             sb.append(":");
1925 
1926             sb.append(ScriptUtils.convertToJsValue(option.getValue()));
1927         }
1928 
1929         sb.append("}");
1930 
1931         return sb.toString();
1932     }
1933 
1934     /**
1935      * {@inheritDoc}
1936      */
1937     @Override
1938     public void setTemplateOptionsJSString(String templateOptionsJSString) {
1939         checkMutable(true);
1940         this.templateOptionsJSString = templateOptionsJSString;
1941     }
1942 
1943     /**
1944      * When set if the condition is satisfied, the component will be displayed. The component MUST
1945      * BE a container or field type. progressiveRender is defined in a limited Spring EL syntax.
1946      * Only valid form property names, and, or, logical comparison operators (non-arithmetic),
1947      * #listContains, #emptyList, matches clause are allowed. String and regex values must use
1948      * single quotes ('), booleans must be either true or false, numbers must be a valid double,
1949      * either negative or positive.
1950      *
1951      * <p>
1952      * DO NOT use progressiveRender and a conditional refresh statement on the same component unless
1953      * it is known that the component will always be visible in all cases when a conditional refresh
1954      * happens (ie conditional refresh has progressiveRender's condition anded with its own
1955      * condition).
1956      * </p>
1957      *
1958      * <p>
1959      * <b>If a component should be refreshed every time it is shown, use the
1960      * progressiveRenderAndRefresh option with this property instead.</b>
1961      * </p>
1962      *
1963      * @return progressiveRender expression
1964      */
1965     @BeanTagAttribute
1966     public String getProgressiveRender() {
1967         return this.progressiveRender;
1968     }
1969 
1970     /**
1971      * @param progressiveRender the progressiveRender to set.
1972      */
1973     public void setProgressiveRender(String progressiveRender) {
1974         checkMutable(true);
1975         this.progressiveRender = progressiveRender;
1976     }
1977 
1978     /**
1979      * When set if the condition is satisfied, the component will be refreshed.
1980      *
1981      * <p>
1982      * The component MUST BE a container or field type. conditionalRefresh is defined in a limited
1983      * Spring EL syntax. Only valid form property names, and, or, logical comparison operators
1984      * (non-arithmetic), #listContains, #emptyList, and the matches clause are allowed. String and
1985      * regex values must use single quotes ('), booleans must be either true or false, numbers must
1986      * be a valid double either negative or positive.
1987      *
1988      * <p>
1989      * DO NOT use progressiveRender and conditionalRefresh on the same component unless it is known
1990      * that the component will always be visible in all cases when a conditionalRefresh happens (ie
1991      * conditionalRefresh has progressiveRender's condition anded with its own condition). <b>If a
1992      * component should be refreshed every time it is shown, use the progressiveRenderAndRefresh
1993      * option with this property instead.</b>
1994      * </p>
1995      *
1996      * @return the conditionalRefresh
1997      */
1998     @BeanTagAttribute
1999     public String getConditionalRefresh() {
2000         return this.conditionalRefresh;
2001     }
2002 
2003     /**
2004      * Set the conditional refresh condition
2005      *
2006      * @param conditionalRefresh the conditionalRefresh to set
2007      */
2008     public void setConditionalRefresh(String conditionalRefresh) {
2009         checkMutable(true);
2010         this.conditionalRefresh = conditionalRefresh;
2011     }
2012 
2013     /**
2014      * Control names used to control progressive disclosure, set internally cannot be set.
2015      *
2016      * @return the progressiveDisclosureControlNames
2017      */
2018     public List<String> getProgressiveDisclosureControlNames() {
2019         return this.progressiveDisclosureControlNames;
2020     }
2021 
2022     /**
2023      * The condition to show this component progressively converted to a js expression, set
2024      * internally cannot be set.
2025      *
2026      * @return the progressiveDisclosureConditionJs
2027      */
2028     public String getProgressiveDisclosureConditionJs() {
2029         return this.progressiveDisclosureConditionJs;
2030     }
2031 
2032     /**
2033      * The condition to refresh this component converted to a js expression, set internally cannot
2034      * be set.
2035      *
2036      * @return the conditionalRefreshConditionJs
2037      */
2038     public String getConditionalRefreshConditionJs() {
2039         return this.conditionalRefreshConditionJs;
2040     }
2041 
2042     /**
2043      * Control names used to control conditional refresh, set internally cannot be set.
2044      *
2045      * @return the conditionalRefreshControlNames
2046      */
2047     public List<String> getConditionalRefreshControlNames() {
2048         return this.conditionalRefreshControlNames;
2049     }
2050 
2051     /**
2052      * When progressiveRenderViaAJAX is true, this component will be retrieved from the server when
2053      * it first satisfies its progressive render condition.
2054      *
2055      * <p>
2056      * After the first retrieval, it is hidden/shown in the html by the js when its progressive
2057      * condition result changes. <b>By default, this is false, so components with progressive render
2058      * capabilities will always be already within the client html and toggled to be hidden or
2059      * visible.</b>
2060      * </p>
2061      *
2062      * @return the progressiveRenderViaAJAX
2063      */
2064     @BeanTagAttribute
2065     public boolean isProgressiveRenderViaAJAX() {
2066         return this.progressiveRenderViaAJAX;
2067     }
2068 
2069     /**
2070      * @param progressiveRenderViaAJAX the progressiveRenderViaAJAX to set.
2071      */
2072     public void setProgressiveRenderViaAJAX(boolean progressiveRenderViaAJAX) {
2073         checkMutable(true);
2074         this.progressiveRenderViaAJAX = progressiveRenderViaAJAX;
2075     }
2076 
2077     /**
2078      * If true, when the progressiveRender condition is satisfied, the component will always be
2079      * retrieved from the server and shown(as opposed to being stored on the client, but hidden,
2080      * after the first retrieval as is the case with the progressiveRenderViaAJAX option).
2081      *
2082      * <p>
2083      * <b>By default, this is false, so components with progressive render capabilities will always
2084      * be already within the client html and toggled to be hidden or visible.</b>
2085      * </p>
2086      *
2087      * @return the progressiveRenderAndRefresh
2088      */
2089     @BeanTagAttribute
2090     public boolean isProgressiveRenderAndRefresh() {
2091         return this.progressiveRenderAndRefresh;
2092     }
2093 
2094     /**
2095      * Set the progressive render and refresh option.
2096      *
2097      * @param progressiveRenderAndRefresh the progressiveRenderAndRefresh to set.
2098      */
2099     public void setProgressiveRenderAndRefresh(boolean progressiveRenderAndRefresh) {
2100         checkMutable(true);
2101         this.progressiveRenderAndRefresh = progressiveRenderAndRefresh;
2102     }
2103 
2104     /**
2105      * {@inheritDoc}
2106      */
2107     @Override
2108     @BeanTagAttribute
2109     public List<String> getRefreshWhenChangedPropertyNames() {
2110         return this.refreshWhenChangedPropertyNames;
2111     }
2112 
2113     /**
2114      * {@inheritDoc}
2115      */
2116     @Override
2117     public void setRefreshWhenChangedPropertyNames(List<String> refreshWhenChangedPropertyNames) {
2118         checkMutable(true);
2119         this.refreshWhenChangedPropertyNames =
2120                 refreshWhenChangedPropertyNames == null ? Collections.<String>emptyList() :
2121                         Collections.<String>unmodifiableList(refreshWhenChangedPropertyNames);
2122     }
2123 
2124     /**
2125      * {@inheritDoc}
2126      */
2127     @Override
2128     @BeanTagAttribute(name = "additionalComponentsToRefresh", type = BeanTagAttribute.AttributeType.LISTVALUE)
2129     public List<String> getAdditionalComponentsToRefresh() {
2130         return additionalComponentsToRefresh;
2131     }
2132 
2133     /**
2134      * {@inheritDoc}
2135      */
2136     @Override
2137     public void setAdditionalComponentsToRefresh(List<String> additionalComponentsToRefresh) {
2138         checkMutable(true);
2139         this.additionalComponentsToRefresh = additionalComponentsToRefresh == null ? Collections.<String>emptyList() :
2140                 Collections.<String>unmodifiableList(additionalComponentsToRefresh);
2141         this.additionalComponentsToRefreshJs = null;
2142     }
2143 
2144     /**
2145      * {@inheritDoc}
2146      */
2147     @Override
2148     public String getAdditionalComponentsToRefreshJs() {
2149         if (additionalComponentsToRefreshJs == null && additionalComponentsToRefresh != null
2150                 && !additionalComponentsToRefresh.isEmpty()) {
2151             additionalComponentsToRefreshJs = ScriptUtils.convertStringListToJsArray(
2152                     this.getAdditionalComponentsToRefresh());
2153         }
2154 
2155         return additionalComponentsToRefreshJs;
2156     }
2157 
2158     /**
2159      * {@inheritDoc}
2160      */
2161     @Override
2162     public boolean isRefreshedByAction() {
2163         return refreshedByAction;
2164     }
2165 
2166     /**
2167      * {@inheritDoc}
2168      */
2169     @Override
2170     public void setRefreshedByAction(boolean refreshedByAction) {
2171         checkMutable(true);
2172         this.refreshedByAction = refreshedByAction;
2173     }
2174 
2175     /**
2176      * {@inheritDoc}
2177      */
2178     @Override
2179     public boolean isDisclosedByAction() {
2180         return disclosedByAction;
2181     }
2182 
2183     /**
2184      * {@inheritDoc}
2185      */
2186     @Override
2187     public void setDisclosedByAction(boolean disclosedByAction) {
2188         checkMutable(true);
2189         this.disclosedByAction = disclosedByAction;
2190     }
2191 
2192     /**
2193      * Time in seconds that the component will be automatically refreshed
2194      *
2195      * <p>
2196      * This will invoke the refresh process just like the conditionalRefresh and
2197      * refreshWhenChangedPropertyNames. When using this property methodToCallOnRefresh and id should
2198      * also be specified
2199      * </p>
2200      *
2201      * @return refreshTimer
2202      */
2203     @BeanTagAttribute
2204     public int getRefreshTimer() {
2205         return refreshTimer;
2206     }
2207 
2208     /**
2209      * Setter for refreshTimer
2210      */
2211     public void setRefreshTimer(int refreshTimer) {
2212         checkMutable(true);
2213         this.refreshTimer = refreshTimer;
2214     }
2215 
2216     /**
2217      * {@inheritDoc}
2218      */
2219     @Override
2220     @BeanTagAttribute
2221     public boolean isResetDataOnRefresh() {
2222         return resetDataOnRefresh;
2223     }
2224 
2225     /**
2226      * {@inheritDoc}
2227      */
2228     @Override
2229     public void setResetDataOnRefresh(boolean resetDataOnRefresh) {
2230         checkMutable(true);
2231         this.resetDataOnRefresh = resetDataOnRefresh;
2232     }
2233 
2234     /**
2235      * Name of a method on the controller that should be invoked as part of the component refresh
2236      * and disclosure process
2237      *
2238      * <p>
2239      * During the component refresh or disclosure process it might be necessary to perform other
2240      * operations, such as preparing data or executing a business process. This allows the
2241      * configuration of a method on the underlying controller that should be called for the
2242      * component refresh action. In this method, the necessary logic can be performed and then the
2243      * base component update method invoked to carry out the component refresh.
2244      * </p>
2245      *
2246      * <p>
2247      * Controller method to invoke must accept the form, binding result, request, and response
2248      * arguments
2249      * </p>
2250      *
2251      * @return valid controller method name
2252      */
2253     @BeanTagAttribute
2254     public String getMethodToCallOnRefresh() {
2255         return methodToCallOnRefresh;
2256     }
2257 
2258     /**
2259      * Setter for the controller method to call for a refresh or disclosure action on this component
2260      */
2261     public void setMethodToCallOnRefresh(String methodToCallOnRefresh) {
2262         checkMutable(true);
2263         this.methodToCallOnRefresh = methodToCallOnRefresh;
2264     }
2265 
2266     /**
2267      * {@inheritDoc}
2268      */
2269     @BeanTagAttribute
2270     public List<String> getFieldsToSendOnRefresh() {
2271         return fieldsToSendOnRefresh;
2272     }
2273 
2274     /**
2275      * {@inheritDoc}
2276      */
2277     public void setFieldsToSendOnRefresh(List<String> fieldsToSendOnRefresh) {
2278         this.fieldsToSendOnRefresh = fieldsToSendOnRefresh;
2279     }
2280 
2281     /**
2282      * Flag indicating that this component and its nested components must be skipped when keyboard
2283      * tabbing.
2284      *
2285      * @return the skipInTabOrder flag
2286      */
2287     @BeanTagAttribute
2288     public boolean isSkipInTabOrder() {
2289         return skipInTabOrder;
2290     }
2291 
2292     /**
2293      * @see ComponentBase#isSkipInTabOrder()
2294      */
2295     public void setSkipInTabOrder(boolean skipInTabOrder) {
2296         checkMutable(true);
2297         this.skipInTabOrder = skipInTabOrder;
2298     }
2299 
2300     /**
2301      * {@inheritDoc}
2302      */
2303     @Override
2304     @BeanTagAttribute
2305     public Map<String, String> getDataAttributes() {
2306         if (dataAttributes == Collections.EMPTY_MAP) {
2307             dataAttributes = new HashMap<String, String>();
2308         }
2309 
2310         return dataAttributes;
2311     }
2312 
2313     /**
2314      * {@inheritDoc}
2315      */
2316     @Override
2317     public void setDataAttributes(Map<String, String> dataAttributes) {
2318         checkMutable(true);
2319         if (dataAttributes == null) {
2320             this.dataAttributes = Collections.emptyMap();
2321         } else {
2322             this.dataAttributes = dataAttributes;
2323         }
2324     }
2325 
2326     /**
2327      * {@inheritDoc}
2328      */
2329     @Override
2330     @BeanTagAttribute
2331     public Map<String, String> getScriptDataAttributes() {
2332         if (scriptDataAttributes == Collections.EMPTY_MAP) {
2333             scriptDataAttributes = new HashMap<String, String>();
2334         }
2335 
2336         return scriptDataAttributes;
2337     }
2338 
2339     /**
2340      * {@inheritDoc}
2341      */
2342     @Override
2343     public void setScriptDataAttributes(Map<String, String> scriptDataAttributes) {
2344         this.scriptDataAttributes = scriptDataAttributes;
2345     }
2346 
2347     /**
2348      * {@inheritDoc}
2349      */
2350     @Override
2351     public void addDataAttribute(String key, String value) {
2352         checkMutable(true);
2353 
2354         if (dataAttributes == Collections.EMPTY_MAP) {
2355             dataAttributes = new HashMap<String, String>();
2356         }
2357 
2358         dataAttributes.put(key, value);
2359     }
2360 
2361     /**
2362      * {@inheritDoc}
2363      */
2364     @Override
2365     public void addScriptDataAttribute(String key, String value) {
2366         checkMutable(true);
2367 
2368         if (scriptDataAttributes == Collections.EMPTY_MAP) {
2369             scriptDataAttributes = new HashMap<String, String>();
2370         }
2371 
2372         scriptDataAttributes.put(key, value);
2373     }
2374 
2375     /**
2376      * {@inheritDoc}
2377      */
2378     @Override
2379     public String getSimpleDataAttributes() {
2380         String attributes = "";
2381 
2382         if (getDataAttributes() == null) {
2383             return attributes;
2384         }
2385 
2386         for (Map.Entry<String, String> data : getDataAttributes().entrySet()) {
2387             if (data != null && data.getValue() != null) {
2388                 attributes = attributes + " " + "data-" + data.getKey() + "=\"" +
2389                         KRADUtils.convertToHTMLAttributeSafeString(data.getValue()) + "\"";
2390             }
2391         }
2392 
2393         return attributes;
2394     }
2395 
2396     @Override
2397     public String getScriptDataAttributesJs() {
2398         String script = "";
2399 
2400         if (getScriptDataAttributes() == null || getScriptDataAttributes().isEmpty()) {
2401             return script;
2402         }
2403 
2404         String id = this.getId().replace(".", "\\\\.");
2405         String selector = "var dataComponent = jQuery('#" + id + "');";
2406         script = ScriptUtils.appendScript(script, selector);
2407 
2408         for (Map.Entry<String, String> data : getScriptDataAttributes().entrySet()) {
2409             if (data != null && data.getValue() != null) {
2410                 script = ScriptUtils.appendScript(script,
2411                         "dataComponent.data('" + data.getKey() + "'," + ScriptUtils.convertToJsValue(data.getValue())
2412                                 + ");");
2413             }
2414         }
2415 
2416         return script;
2417     }
2418 
2419     /**
2420      * {@inheritDoc}
2421      */
2422     @Override
2423     @BeanTagAttribute
2424     public String getRole() {
2425         return role;
2426     }
2427 
2428     /**
2429      * {@inheritDoc}
2430      */
2431     public void setRole(String role) {
2432         this.role = role;
2433     }
2434 
2435     /**
2436      * {@inheritDoc}
2437      */
2438     @Override
2439     @BeanTagAttribute
2440     public Map<String, String> getAriaAttributes() {
2441         if (ariaAttributes == Collections.EMPTY_MAP) {
2442             ariaAttributes = new LifecycleAwareMap<String, String>(this);
2443         }
2444 
2445         return ariaAttributes;
2446     }
2447 
2448     /**
2449      * {@inheritDoc}
2450      */
2451     @Override
2452     public void setAriaAttributes(Map<String, String> ariaAttributes) {
2453         checkMutable(true);
2454         if (ariaAttributes == null) {
2455             this.ariaAttributes = Collections.emptyMap();
2456         } else {
2457             this.ariaAttributes = new LifecycleAwareMap<String, String>(this, ariaAttributes);
2458         }
2459     }
2460 
2461     /**
2462      * {@inheritDoc}
2463      */
2464     @Override
2465     public void addAriaAttribute(String key, String value) {
2466         checkMutable(true);
2467 
2468         if (ariaAttributes == Collections.EMPTY_MAP) {
2469             ariaAttributes = new LifecycleAwareMap<String, String>(this);
2470         }
2471 
2472         ariaAttributes.put(key, value);
2473     }
2474 
2475     /**
2476      * {@inheritDoc}
2477      */
2478     @Override
2479     public String getAriaAttributesAsString() {
2480         String attributes = "";
2481 
2482         if (getAriaAttributes() == null) {
2483             return attributes;
2484         }
2485 
2486         for (Map.Entry<String, String> aria : getAriaAttributes().entrySet()) {
2487             if (aria != null && aria.getValue() != null) {
2488                 attributes = attributes + " " + "aria-" + aria.getKey() + "=\"" +
2489                         KRADUtils.convertToHTMLAttributeSafeString(aria.getValue()) + "\"";
2490             }
2491         }
2492 
2493         return attributes;
2494     }
2495 
2496     /**
2497      * {@inheritDoc}
2498      */
2499     @BeanTagAttribute(name = "preContent", type = BeanTagAttribute.AttributeType.ANY)
2500     public String getPreRenderContent() {
2501         return preRenderContent;
2502     }
2503 
2504     /**
2505      * {@inheritDoc}
2506      */
2507     @Override
2508     public void setPreRenderContent(String preRenderContent) {
2509         checkMutable(true);
2510         this.preRenderContent = preRenderContent;
2511     }
2512 
2513     /**
2514      * {@inheritDoc}
2515      */
2516     @Override
2517     @BeanTagAttribute(name = "postContent", type = BeanTagAttribute.AttributeType.ANY)
2518     public String getPostRenderContent() {
2519         return postRenderContent;
2520     }
2521 
2522     /**
2523      * {@inheritDoc}
2524      */
2525     @Override
2526     public void setPostRenderContent(String postRenderContent) {
2527         checkMutable(true);
2528         this.postRenderContent = postRenderContent;
2529     }
2530 
2531     /**
2532      * {@inheritDoc}
2533      */
2534     @Override
2535     public String getExcludeIf() {
2536         return this.excludeIf;
2537     }
2538 
2539     /**
2540      * @see #getExcludeIf()
2541      */
2542     public void setExcludeIf(String excludeIf) {
2543         this.excludeIf = excludeIf;
2544     }
2545 
2546     /**
2547      * {@inheritDoc}
2548      */
2549     @Override
2550     public String getExcludeUnless() {
2551         return this.excludeUnless;
2552     }
2553 
2554     /**
2555      * @see #getExcludeIf()
2556      */
2557     public void setExcludeUnless(String excludeUnless) {
2558         this.excludeUnless = excludeUnless;
2559     }
2560 
2561     /**
2562      * {@inheritDoc}
2563      */
2564     @Override
2565     public ComponentBase clone() throws CloneNotSupportedException {
2566         ComponentBase copy = (ComponentBase) super.clone();
2567 
2568         // Copy initialized status, but reset to created for others.
2569         // This allows prototypes to bypass repeating the initialized phase.
2570         if (UifConstants.ViewStatus.INITIALIZED.equals(viewStatus)) {
2571             copy.viewStatus = UifConstants.ViewStatus.INITIALIZED;
2572         } else {
2573             copy.viewStatus = UifConstants.ViewStatus.CREATED;
2574         }
2575 
2576         return copy;
2577     }
2578 
2579     /**
2580      * {@inheritDoc}
2581      */
2582     @Override
2583     public void completeValidation(ValidationTrace tracer) {
2584         tracer.addBean(this);
2585 
2586         // Check for invalid characters in the components id
2587         if (getId() != null) {
2588             if (getId().contains("'") || getId().contains("\"") || getId().contains("[]") || getId().contains(".")
2589                     || getId().contains("#")) {
2590                 String currentValues[] = {"id = " + getId()};
2591                 tracer.createError("Id contains invalid characters", currentValues);
2592             }
2593         }
2594 
2595         if (tracer.getValidationStage() == ValidationTrace.BUILD) {
2596             // Check for a render presence if the component is set to render
2597             if ((isProgressiveRenderViaAJAX() || isProgressiveRenderAndRefresh()) && (getProgressiveRender() == null)) {
2598                 String currentValues[] = {"progressiveRenderViaAJAX = " + isProgressiveRenderViaAJAX(),
2599                         "progressiveRenderAndRefresh = " + isProgressiveRenderAndRefresh(),
2600                         "progressiveRender = " + getProgressiveRender()};
2601                 tracer.createError(
2602                         "ProgressiveRender must be set if progressiveRenderViaAJAX or progressiveRenderAndRefresh are true",
2603                         currentValues);
2604             }
2605         }
2606 
2607         // Check for rendered html if the component is set to self render
2608         if (isSelfRendered() && getRenderedHtmlOutput() == null) {
2609             String currentValues[] =
2610                     {"selfRendered = " + isSelfRendered(), "renderedHtmlOutput = " + getRenderedHtmlOutput()};
2611             tracer.createError("RenderedHtmlOutput must be set if selfRendered is true", currentValues);
2612         }
2613 
2614         // Check to prevent over writing of session persistence status
2615         if (isDisableSessionPersistence() && isForceSessionPersistence()) {
2616             String currentValues[] = {"disableSessionPersistence = " + isDisableSessionPersistence(),
2617                     "forceSessionPersistence = " + isForceSessionPersistence()};
2618             tracer.createWarning("DisableSessionPersistence and forceSessionPersistence cannot be both true",
2619                     currentValues);
2620         }
2621 
2622         // Check for un-executable data resets when no refresh option is set
2623         if (getMethodToCallOnRefresh() != null || isResetDataOnRefresh()) {
2624             if (!isProgressiveRenderAndRefresh() && !isRefreshedByAction() && !isProgressiveRenderViaAJAX()
2625                     && !StringUtils.isNotEmpty(conditionalRefresh) && !(refreshTimer > 0)) {
2626                 String currentValues[] = {"methodToCallONRefresh = " + getMethodToCallOnRefresh(),
2627                         "resetDataONRefresh = " + isResetDataOnRefresh(),
2628                         "progressiveRenderAndRefresh = " + isProgressiveRenderAndRefresh(),
2629                         "refreshedByAction = " + isRefreshedByAction(),
2630                         "progressiveRenderViaAJAX = " + isProgressiveRenderViaAJAX(),
2631                         "conditionalRefresh = " + getConditionalRefresh(), "refreshTimer = " + getRefreshTimer()};
2632                 tracer.createWarning(
2633                         "MethodToCallONRefresh and resetDataONRefresh should only be set when a trigger event is set",
2634                         currentValues);
2635             }
2636         }
2637 
2638         // Check to prevent complications with rendering and refreshing a component that is not always shown
2639         if (StringUtils.isNotEmpty(getProgressiveRender()) && StringUtils.isNotEmpty(conditionalRefresh)) {
2640             String currentValues[] = {"progressiveRender = " + getProgressiveRender(),
2641                     "conditionalRefresh = " + getConditionalRefresh()};
2642             tracer.createWarning("DO NOT use progressiveRender and conditionalRefresh on the same component unless "
2643                     + "it is known that the component will always be visible in all cases when a conditionalRefresh "
2644                     + "happens (ie conditionalRefresh has progressiveRender's condition anded with its own condition). "
2645                     + "If a component should be refreshed every time it is shown, use the progressiveRenderAndRefresh "
2646                     + "option with this property instead.", currentValues);
2647         }
2648 
2649         // Check for valid Spring EL format for progressiveRender
2650         if (!Validator.validateSpringEL(getProgressiveRender())) {
2651             String currentValues[] = {"progressiveRender =" + getProgressiveRender()};
2652             tracer.createError("ProgressiveRender must follow the Spring EL @{} format", currentValues);
2653         }
2654 
2655         // Check for valid Spring EL format for conditionalRefresh
2656         if (!Validator.validateSpringEL(getConditionalRefresh())) {
2657             String currentValues[] = {"conditionalRefresh =" + getConditionalRefresh()};
2658             tracer.createError("conditionalRefresh must follow the Spring EL @{} format", currentValues);
2659         }
2660     }
2661 
2662     /**
2663      * @see org.kuali.rice.krad.uif.container.Field#isOmitFromFormPost()
2664      */
2665     public boolean isOmitFromFormPost() {
2666         return omitFromFormPost;
2667     }
2668 
2669     /**
2670      * @see #isOmitFromFormPost()
2671      */
2672     public void setOmitFromFormPost(boolean omitFromFormPost) {
2673         this.omitFromFormPost = omitFromFormPost;
2674     }
2675 }