View Javadoc

1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.uif.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.service.KRADServiceLocatorWeb;
25  import org.kuali.rice.krad.uif.CssConstants;
26  import org.kuali.rice.krad.uif.control.ControlBase;
27  import org.kuali.rice.krad.uif.modifier.ComponentModifier;
28  import org.kuali.rice.krad.uif.service.ExpressionEvaluatorService;
29  import org.kuali.rice.krad.uif.util.ExpressionUtils;
30  import org.kuali.rice.krad.uif.util.ScriptUtils;
31  import org.kuali.rice.krad.uif.view.View;
32  import org.kuali.rice.krad.uif.widget.Tooltip;
33  import org.kuali.rice.krad.util.ObjectUtils;
34  
35  import java.util.ArrayList;
36  import java.util.HashMap;
37  import java.util.List;
38  import java.util.Map;
39  
40  /**
41   * Base implementation of <code>Component</code> which other component
42   * implementations should extend
43   *
44   * <p>
45   * Provides base component properties such as id and template. Also provides
46   * default implementation for the <code>ScriptEventSupport</code> and
47   * <code>Ordered</code> interfaces. By default no script events except the
48   * onDocumentReady are supported.
49   * </p>
50   *
51   * @author Kuali Rice Team (rice.collab@kuali.org)
52   */
53  @BeanTag(name = "componentBase-bean", parent = "Uif-ComponentBase")
54  public abstract class ComponentBase extends UifDictionaryBeanBase implements Component {
55      private static final long serialVersionUID = -4449335748129894350L;
56  
57      private String id;
58      private String baseId;
59      private String template;
60      private String templateName;
61  
62      private String title;
63  
64      private boolean render;
65  
66      @KeepExpression
67      private String progressiveRender;
68      private boolean progressiveRenderViaAJAX;
69      private boolean progressiveRenderAndRefresh;
70      private List<String> progressiveDisclosureControlNames;
71      private String progressiveDisclosureConditionJs;
72  
73      @KeepExpression
74      private String conditionalRefresh;
75      private String conditionalRefreshConditionJs;
76      private List<String> conditionalRefreshControlNames;
77  
78      private List<String> refreshWhenChangedPropertyNames;
79      private List<String> additionalComponentsToRefresh;
80      private String additionalComponentsToRefreshJs;
81      private boolean refreshedByAction;
82      private boolean disclosedByAction;
83  
84      private int refreshTimer;
85  
86      private boolean resetDataOnRefresh;
87      private String methodToCallOnRefresh;
88  
89      private boolean hidden;
90      private boolean readOnly;
91      private Boolean required;
92  
93      private String align;
94      private String valign;
95      private String width;
96  
97      // optional table-backed layout options
98      private int colSpan;
99      private int rowSpan;
100     private List<String> cellCssClasses;
101     private String cellStyle;
102     private String cellWidth;
103 
104     private String style;
105     private List<String> cssClasses;
106 
107     private Tooltip toolTip;
108 
109     private int order;
110 
111     private boolean skipInTabOrder;
112 
113     private String finalizeMethodToCall;
114     private List<Object> finalizeMethodAdditionalArguments;
115     private MethodInvokerConfig finalizeMethodInvoker;
116 
117     private boolean selfRendered;
118     private String renderedHtmlOutput;
119 
120     private boolean disableSessionPersistence;
121     private boolean forceSessionPersistence;
122 
123     private ComponentSecurity componentSecurity;
124 
125     private String onLoadScript;
126     private String onUnloadScript;
127     private String onCloseScript;
128     private String onBlurScript;
129     private String onChangeScript;
130     private String onClickScript;
131     private String onDblClickScript;
132     private String onFocusScript;
133     private String onSubmitScript;
134     private String onKeyPressScript;
135     private String onKeyUpScript;
136     private String onKeyDownScript;
137     private String onMouseOverScript;
138     private String onMouseOutScript;
139     private String onMouseUpScript;
140     private String onMouseDownScript;
141     private String onMouseMoveScript;
142     private String onDocumentReadyScript;
143 
144     private List<ComponentModifier> componentModifiers;
145 
146     private Map<String, String> templateOptions;
147     private String templateOptionsJSString;
148 
149     @ReferenceCopy(newCollectionInstance = true)
150     private transient Map<String, Object> context;
151 
152     private List<PropertyReplacer> propertyReplacers;
153 
154     private Map<String, String> dataAttributes;
155 
156     public ComponentBase() {
157         super();
158 
159         order = 0;
160         colSpan = 1;
161         rowSpan = 1;
162 
163         render = true;
164         selfRendered = false;
165         progressiveRenderViaAJAX = false;
166         progressiveRenderAndRefresh = false;
167         refreshedByAction = false;
168         resetDataOnRefresh = false;
169         disableSessionPersistence = false;
170         forceSessionPersistence = false;
171 
172         componentSecurity = ObjectUtils.newInstance(getComponentSecurityClass());
173 
174         refreshWhenChangedPropertyNames = new ArrayList<String>();
175         additionalComponentsToRefresh = new ArrayList<String>();
176         finalizeMethodAdditionalArguments = new ArrayList<Object>();
177         cellCssClasses = new ArrayList<String>();
178         cssClasses = new ArrayList<String>();
179         componentModifiers = new ArrayList<ComponentModifier>();
180         templateOptions = new HashMap<String, String>();
181         context = new HashMap<String, Object>();
182         propertyReplacers = new ArrayList<PropertyReplacer>();
183         dataAttributes = new HashMap<String, String>();
184     }
185 
186     /**
187      * The following updates are done here:
188      *
189      * <ul>
190      * <li></li>
191      * </ul>
192      *
193      * @see org.kuali.rice.krad.uif.component.Component#performInitialization(org.kuali.rice.krad.uif.view.View, java.lang.Object)
194      */
195     public void performInitialization(View view, Object model) {
196 
197     }
198 
199     /**
200      * The following updates are done here:
201      *
202      * <ul>
203      * <li>Evaluate the progressive render condition (if set) and combine with the current render status to set the
204      * render status</li>
205      * </ul>
206      *
207      * @see org.kuali.rice.krad.uif.component.Component#performApplyModel(org.kuali.rice.krad.uif.view.View, java.lang.Object,
208      *      org.kuali.rice.krad.uif.component.Component)
209      */
210     public void performApplyModel(View view, Object model, Component parent) {
211         if (this.render && StringUtils.isNotEmpty(progressiveRender)) {
212             // progressive anded with render, will not render at least one of the two are false
213             ExpressionEvaluatorService expressionEvaluatorService =
214                     KRADServiceLocatorWeb.getExpressionEvaluatorService();
215             String adjustedProgressiveRender = expressionEvaluatorService.replaceBindingPrefixes(view, this,
216                     progressiveRender);
217             Boolean progRenderEval = (Boolean) expressionEvaluatorService.evaluateExpression(model, context,
218                     adjustedProgressiveRender);
219 
220             this.setRender(progRenderEval);
221         }
222     }
223 
224     /**
225      * The following finalization is done here:
226      *
227      * <ul>
228      * <li>progressiveRender and conditionalRefresh variables are processed if set</li>
229      * <li>If any of the style properties were given, sets the style string on
230      * the style property</li>
231      * <li>Set the skipInTabOrder flag for nested components</li>
232      * </ul>
233      *
234      * @see org.kuali.rice.krad.uif.component.Component#performFinalize(org.kuali.rice.krad.uif.view.View, java.lang.Object,
235      *      org.kuali.rice.krad.uif.component.Component)
236      */
237     public void performFinalize(View view, Object model, Component parent) {
238         if (StringUtils.isNotEmpty(progressiveRender)) {
239             progressiveRender = KRADServiceLocatorWeb.getExpressionEvaluatorService().replaceBindingPrefixes(view, this,
240                     progressiveRender);
241             progressiveDisclosureControlNames = new ArrayList<String>();
242             progressiveDisclosureConditionJs = ExpressionUtils.parseExpression(progressiveRender,
243                     progressiveDisclosureControlNames);
244         }
245 
246         if (StringUtils.isNotEmpty(conditionalRefresh)) {
247             conditionalRefresh = KRADServiceLocatorWeb.getExpressionEvaluatorService().replaceBindingPrefixes(view,
248                     this, conditionalRefresh);
249             conditionalRefreshControlNames = new ArrayList<String>();
250             conditionalRefreshConditionJs = ExpressionUtils.parseExpression(conditionalRefresh,
251                     conditionalRefreshControlNames);
252         }
253 
254         List<String> adjustedRefreshPropertyNames = new ArrayList<String>();
255         for (String refreshPropertyName : refreshWhenChangedPropertyNames) {
256             adjustedRefreshPropertyNames.add(
257                     KRADServiceLocatorWeb.getExpressionEvaluatorService().replaceBindingPrefixes(view, this,
258                             refreshPropertyName));
259         }
260         refreshWhenChangedPropertyNames = adjustedRefreshPropertyNames;
261 
262         // add the align, valign, and width settings to style
263         if (StringUtils.isNotBlank(getAlign()) && !StringUtils.contains(getStyle(), CssConstants.TEXT_ALIGN)) {
264             appendToStyle(CssConstants.TEXT_ALIGN + getAlign() + ";");
265         }
266 
267         if (StringUtils.isNotBlank(getValign()) && !StringUtils.contains(getStyle(), CssConstants.VERTICAL_ALIGN)) {
268             appendToStyle(CssConstants.VERTICAL_ALIGN + getValign() + ";");
269         }
270 
271         if (StringUtils.isNotBlank(getWidth()) && !StringUtils.contains(getStyle(), CssConstants.WIDTH)) {
272             appendToStyle(CssConstants.WIDTH + getWidth() + ";");
273         }
274 
275         // Set the skipInTabOrder flag on all nested components
276         // Set the tabIndex on controls to -1 in order to be skipped on tabbing
277         for (Component component : getComponentsForLifecycle()) {
278             if (component != null && component instanceof ComponentBase && skipInTabOrder) {
279                 ((ComponentBase) component).setSkipInTabOrder(skipInTabOrder);
280                 if (component instanceof ControlBase) {
281                     ((ControlBase) component).setTabIndex(-1);
282                 }
283             }
284         }
285 
286         // if this is not rendering and it is not rendering via an ajax call, but still has a progressive render
287         // condition we still want to render the component, but hide it (in ajax cases, template creates a placeholder)
288         boolean hide = false;
289         if (!this.render && !this.progressiveRenderViaAJAX && !this.progressiveRenderAndRefresh && StringUtils
290                 .isNotBlank(progressiveRender)) {
291             hide = true;
292         } else if (this.isHidden()) {
293             hide = true;
294         }
295 
296         if (hide) {
297             if (StringUtils.isNotBlank(this.getStyle())) {
298                 if (this.getStyle().endsWith(";")) {
299                     this.setStyle(this.getStyle() + " display: none;");
300                 } else {
301                     this.setStyle(this.getStyle() + "; display: none;");
302                 }
303             } else {
304                 this.setStyle("display: none;");
305             }
306         }
307     }
308 
309     /**
310      * @see org.kuali.rice.krad.uif.component.Component#getComponentsForLifecycle()
311      */
312     public List<Component> getComponentsForLifecycle() {
313         List<Component> components = new ArrayList<Component>();
314 
315         components.add(toolTip);
316 
317         return components;
318     }
319 
320     /**
321      * @see org.kuali.rice.krad.uif.component.Component#getComponentPrototypes()
322      */
323     public List<Component> getComponentPrototypes() {
324         List<Component> components = new ArrayList<Component>();
325 
326         for (ComponentModifier modifier : componentModifiers) {
327             components.addAll(modifier.getComponentPrototypes());
328         }
329 
330         components.addAll(getPropertyReplacerComponents());
331 
332         return components;
333     }
334 
335     /**
336      * Returns list of components that are being held in property replacers configured for this component
337      *
338      * @return List<Component>
339      */
340     public List<Component> getPropertyReplacerComponents() {
341         List<Component> components = new ArrayList<Component>();
342         for (Object replacer : propertyReplacers) {
343             components.addAll(((PropertyReplacer) replacer).getNestedComponents());
344         }
345 
346         return components;
347     }
348 
349     /**
350      * @see org.kuali.rice.krad.uif.component.Component#getId()
351      */
352     @BeanTagAttribute(name = "id")
353     public String getId() {
354         return this.id;
355     }
356 
357     /**
358      * @see org.kuali.rice.krad.uif.component.Component#setId(java.lang.String)
359      */
360     public void setId(String id) {
361         this.id = id;
362     }
363 
364     /**
365      * @see org.kuali.rice.krad.uif.component.Component#getBaseId()
366      */
367     public String getBaseId() {
368         return this.baseId;
369     }
370 
371     /**
372      * @see org.kuali.rice.krad.uif.component.Component#setBaseId(java.lang.String)
373      */
374     public void setBaseId(String baseId) {
375         this.baseId = baseId;
376     }
377 
378     /**
379      * @see org.kuali.rice.krad.uif.component.Component#getTemplate()
380      */
381     @BeanTagAttribute(name = "template")
382     public String getTemplate() {
383         return this.template;
384     }
385 
386     /**
387      * @see org.kuali.rice.krad.uif.component.Component#setTemplate(java.lang.String)
388      */
389     public void setTemplate(String template) {
390         this.template = template;
391     }
392 
393     @BeanTagAttribute(name = "templateName")
394     public String getTemplateName() {
395         return templateName;
396     }
397 
398     public void setTemplateName(String templateName) {
399         this.templateName = templateName;
400     }
401 
402     /**
403      * @see org.kuali.rice.krad.uif.component.Component#getTitle()
404      */
405     @BeanTagAttribute(name = "title")
406     public String getTitle() {
407         return this.title;
408     }
409 
410     /**
411      * @see org.kuali.rice.krad.uif.component.Component#setTitle(java.lang.String)
412      */
413     public void setTitle(String title) {
414         this.title = title;
415     }
416 
417     /**
418      * @see org.kuali.rice.krad.uif.component.Component#isHidden()
419      */
420     @BeanTagAttribute(name = "hidden")
421     public boolean isHidden() {
422         return this.hidden;
423     }
424 
425     /**
426      * @see org.kuali.rice.krad.uif.component.Component#setHidden(boolean)
427      */
428     public void setHidden(boolean hidden) {
429         this.hidden = hidden;
430     }
431 
432     /**
433      * @see org.kuali.rice.krad.uif.component.Component#isReadOnly()
434      */
435     @BeanTagAttribute(name = "readOnly")
436     public boolean isReadOnly() {
437         return this.readOnly;
438     }
439 
440     /**
441      * @see org.kuali.rice.krad.uif.component.Component#setReadOnly(boolean)
442      */
443     public void setReadOnly(boolean readOnly) {
444         this.readOnly = readOnly;
445     }
446 
447     /**
448      * @see org.kuali.rice.krad.uif.component.Component#getRequired()
449      */
450     @BeanTagAttribute(name = "required")
451     public Boolean getRequired() {
452         return this.required;
453     }
454 
455     /**
456      * @see org.kuali.rice.krad.uif.component.Component#setRequired(java.lang.Boolean)
457      */
458     public void setRequired(Boolean required) {
459         this.required = required;
460     }
461 
462     /**
463      * @see org.kuali.rice.krad.uif.component.Component#isRender()
464      */
465     @BeanTagAttribute(name = "render")
466     public boolean isRender() {
467         return this.render;
468     }
469 
470     /**
471      * @see org.kuali.rice.krad.uif.component.Component#setRender(boolean)
472      */
473     public void setRender(boolean render) {
474         this.render = render;
475     }
476 
477     /**
478      * @see org.kuali.rice.krad.uif.component.Component#getColSpan()
479      */
480     @BeanTagAttribute(name = "ColSpan")
481     public int getColSpan() {
482         return this.colSpan;
483     }
484 
485     /**
486      * @see org.kuali.rice.krad.uif.component.Component#setColSpan(int)
487      */
488     public void setColSpan(int colSpan) {
489         this.colSpan = colSpan;
490     }
491 
492     /**
493      * @see org.kuali.rice.krad.uif.component.Component#getRowSpan()
494      */
495     @BeanTagAttribute(name = "rowSpan")
496     public int getRowSpan() {
497         return this.rowSpan;
498     }
499 
500     /**
501      * @see org.kuali.rice.krad.uif.component.Component#setRowSpan(int)
502      */
503     public void setRowSpan(int rowSpan) {
504         this.rowSpan = rowSpan;
505     }
506 
507     /**
508      * @see org.kuali.rice.krad.uif.component.Component#getCellCssClasses()
509      */
510     public List<String> getCellCssClasses() {
511         return cellCssClasses;
512     }
513 
514     /**
515      * @see org.kuali.rice.krad.uif.component.Component#setCellCssClasses(java.util.List)
516      */
517     public void setCellCssClasses(List<String> cellCssClasses) {
518         this.cellCssClasses = cellCssClasses;
519     }
520 
521     /**
522      * @see org.kuali.rice.krad.uif.component.Component#addCellCssClass(String)
523      */
524     public void addCellCssClass(String cssClass) {
525         if (this.cellCssClasses == null){
526             this.cellCssClasses = new ArrayList<String>();
527         }
528 
529         if(cssClass != null){
530             this.cellCssClasses.add(cssClass);
531         }
532     }
533 
534     /**
535      * Builds the HTML class attribute string by combining the cellStyleClasses list
536      * with a space delimiter
537      *
538      * @return String class attribute string
539      */
540     public String getCellStyleClassesAsString() {
541         if (cellCssClasses != null) {
542             return StringUtils.join(cellCssClasses, " ");
543         }
544 
545         return "";
546     }
547 
548     /**
549      * @see org.kuali.rice.krad.uif.component.Component#getCellStyle()
550      */
551     public String getCellStyle() {
552         return cellStyle;
553     }
554 
555     /**
556      * @see org.kuali.rice.krad.uif.component.Component#setCellStyle(java.lang.String)
557      */
558     public void setCellStyle(String cellStyle) {
559         this.cellStyle = cellStyle;
560     }
561 
562     /**
563      * @see org.kuali.rice.krad.uif.component.Component#getCellWidth()
564      */
565     public String getCellWidth() {
566         return cellWidth;
567     }
568 
569     /**
570      * @see org.kuali.rice.krad.uif.component.Component#setCellWidth(java.lang.String)
571      */
572     public void setCellWidth(String cellWidth) {
573         this.cellWidth = cellWidth;
574     }
575 
576     /**
577      * @see org.kuali.rice.krad.uif.component.Component#getAlign()
578      */
579     @BeanTagAttribute(name = "align")
580     public String getAlign() {
581         return this.align;
582     }
583 
584     /**
585      * @see org.kuali.rice.krad.uif.component.Component#setAlign(java.lang.String)
586      */
587     public void setAlign(String align) {
588         this.align = align;
589     }
590 
591     /**
592      * @see org.kuali.rice.krad.uif.component.Component#getValign()
593      */
594     @BeanTagAttribute(name = "valign")
595     public String getValign() {
596         return this.valign;
597     }
598 
599     /**
600      * @see org.kuali.rice.krad.uif.component.Component#setValign(java.lang.String)
601      */
602     public void setValign(String valign) {
603         this.valign = valign;
604     }
605 
606     /**
607      * @see org.kuali.rice.krad.uif.component.Component#getWidth()
608      */
609     @BeanTagAttribute(name = "width")
610     public String getWidth() {
611         return this.width;
612     }
613 
614     /**
615      * @see org.kuali.rice.krad.uif.component.Component#setWidth(java.lang.String)
616      */
617     public void setWidth(String width) {
618         this.width = width;
619     }
620 
621     /**
622      * @see org.kuali.rice.krad.uif.component.Component#getStyle()
623      */
624     @BeanTagAttribute(name = "style")
625     public String getStyle() {
626         return this.style;
627     }
628 
629     /**
630      * @see org.kuali.rice.krad.uif.component.Component#setStyle(java.lang.String)
631      */
632     public void setStyle(String style) {
633         this.style = style;
634     }
635 
636     /**
637      * @see org.kuali.rice.krad.uif.component.Component#getCssClasses()
638      */
639     @BeanTagAttribute(name = "cssClasses", type = BeanTagAttribute.AttributeType.LISTVALUE)
640     public List<String> getCssClasses() {
641         return this.cssClasses;
642     }
643 
644     /**
645      * @see org.kuali.rice.krad.uif.component.Component#setCssClasses(java.util.List)
646      */
647     public void setCssClasses(List<String> cssClasses) {
648         this.cssClasses = cssClasses;
649     }
650 
651     /**
652      * Builds the HTML class attribute string by combining the styleClasses list
653      * with a space delimiter
654      *
655      * @return String class attribute string
656      */
657     public String getStyleClassesAsString() {
658         if (cssClasses != null) {
659             return StringUtils.join(cssClasses, " ");
660         }
661 
662         return "";
663     }
664 
665     /**
666      * @see org.kuali.rice.krad.uif.component.Component#addStyleClass(java.lang.String)
667      */
668     public void addStyleClass(String styleClass) {
669         if (!cssClasses.contains(styleClass)) {
670             cssClasses.add(styleClass);
671         }
672     }
673 
674     /**
675      * @see org.kuali.rice.krad.uif.component.Component#appendToStyle(java.lang.String)
676      */
677     public void appendToStyle(String styleRules) {
678         if (style == null) {
679             style = "";
680         }
681         style = style + styleRules;
682     }
683 
684     /**
685      * @see org.kuali.rice.krad.uif.component.Component#getFinalizeMethodToCall()
686      */
687     @BeanTagAttribute(name = "finalizeMethodToCall")
688     public String getFinalizeMethodToCall() {
689         return this.finalizeMethodToCall;
690     }
691 
692     /**
693      * Setter for the finalize method
694      *
695      * @param finalizeMethodToCall
696      */
697     public void setFinalizeMethodToCall(String finalizeMethodToCall) {
698         this.finalizeMethodToCall = finalizeMethodToCall;
699     }
700 
701     /**
702      * @see org.kuali.rice.krad.uif.component.Component#getFinalizeMethodAdditionalArguments()
703      */
704     @BeanTagAttribute(name = "finalizeMethodAdditionalArguments", type = BeanTagAttribute.AttributeType.LISTBEAN)
705     public List<Object> getFinalizeMethodAdditionalArguments() {
706         return finalizeMethodAdditionalArguments;
707     }
708 
709     /**
710      * Setter for the finalize additional arguments list
711      *
712      * @param finalizeMethodAdditionalArguments
713      */
714     public void setFinalizeMethodAdditionalArguments(List<Object> finalizeMethodAdditionalArguments) {
715         this.finalizeMethodAdditionalArguments = finalizeMethodAdditionalArguments;
716     }
717 
718     /**
719      * @see org.kuali.rice.krad.uif.component.Component#getFinalizeMethodInvoker()
720      */
721     @BeanTagAttribute(name = "finalizeMethodInvoker", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
722     public MethodInvokerConfig getFinalizeMethodInvoker() {
723         return this.finalizeMethodInvoker;
724     }
725 
726     /**
727      * Setter for the method invoker instance
728      *
729      * @param finalizeMethodInvoker
730      */
731     public void setFinalizeMethodInvoker(MethodInvokerConfig finalizeMethodInvoker) {
732         this.finalizeMethodInvoker = finalizeMethodInvoker;
733     }
734 
735     /**
736      * @see org.kuali.rice.krad.uif.component.Component#isSelfRendered()
737      */
738     @BeanTagAttribute(name = "selfRendered")
739     public boolean isSelfRendered() {
740         return this.selfRendered;
741     }
742 
743     /**
744      * @see org.kuali.rice.krad.uif.component.Component#setSelfRendered(boolean)
745      */
746     public void setSelfRendered(boolean selfRendered) {
747         this.selfRendered = selfRendered;
748     }
749 
750     /**
751      * @see org.kuali.rice.krad.uif.component.Component#getRenderedHtmlOutput()
752      */
753     @BeanTagAttribute(name = "renderedHtmlOutput")
754     public String getRenderedHtmlOutput() {
755         return this.renderedHtmlOutput;
756     }
757 
758     /**
759      * @see org.kuali.rice.krad.uif.component.Component#setRenderedHtmlOutput(java.lang.String)
760      */
761     public void setRenderedHtmlOutput(String renderedHtmlOutput) {
762         this.renderedHtmlOutput = renderedHtmlOutput;
763     }
764 
765     /**
766      * @see org.kuali.rice.krad.uif.component.Component#isDisableSessionPersistence()
767      */
768     @BeanTagAttribute(name = "disableSessionPersistence")
769     public boolean isDisableSessionPersistence() {
770         return disableSessionPersistence;
771     }
772 
773     /**
774      * @see org.kuali.rice.krad.uif.component.Component#setDisableSessionPersistence(boolean)
775      */
776     public void setDisableSessionPersistence(boolean disableSessionPersistence) {
777         this.disableSessionPersistence = disableSessionPersistence;
778     }
779 
780     /**
781      * @see org.kuali.rice.krad.uif.component.Component#isForceSessionPersistence()
782      */
783     @BeanTagAttribute(name = "forceSessionPersistence")
784     public boolean isForceSessionPersistence() {
785         return forceSessionPersistence;
786     }
787 
788     /**
789      * @see org.kuali.rice.krad.uif.component.Component#setForceSessionPersistence(boolean)
790      */
791     public void setForceSessionPersistence(boolean forceSessionPersistence) {
792         this.forceSessionPersistence = forceSessionPersistence;
793     }
794 
795     /**
796      * @see org.kuali.rice.krad.uif.component.Component#getComponentSecurity()
797      */
798     @BeanTagAttribute(name = "componentSecurity", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
799     public ComponentSecurity getComponentSecurity() {
800         return componentSecurity;
801     }
802 
803     /**
804      * @see org.kuali.rice.krad.uif.component.Component#setComponentSecurity(org.kuali.rice.krad.uif.component.ComponentSecurity)
805      */
806     public void setComponentSecurity(ComponentSecurity componentSecurity) {
807         this.componentSecurity = componentSecurity;
808     }
809 
810     /**
811      * Returns the security class that is associated with the component (used for initialization and validation)
812      *
813      * @return Class<? extends ComponentSecurity>
814      */
815     protected Class<? extends ComponentSecurity> getComponentSecurityClass() {
816         return ComponentSecurity.class;
817     }
818 
819     /**
820      * @see org.kuali.rice.krad.uif.component.Component#getComponentModifiers()
821      */
822     @BeanTagAttribute(name = "componentModifiers", type = BeanTagAttribute.AttributeType.LISTBEAN)
823     public List<ComponentModifier> getComponentModifiers() {
824         return this.componentModifiers;
825     }
826 
827     /**
828      * @see org.kuali.rice.krad.uif.component.Component#setComponentModifiers(java.util.List)
829      */
830     public void setComponentModifiers(List<ComponentModifier> componentModifiers) {
831         this.componentModifiers = componentModifiers;
832     }
833 
834     /**
835      * @see org.kuali.rice.krad.uif.component.Component#getContext()
836      */
837     @BeanTagAttribute(name = "context", type = BeanTagAttribute.AttributeType.MAPBEAN)
838     public Map<String, Object> getContext() {
839         return this.context;
840     }
841 
842     /**
843      * @see org.kuali.rice.krad.uif.component.Component#setContext(java.util.Map)
844      */
845     public void setContext(Map<String, Object> context) {
846         this.context = context;
847     }
848 
849     /**
850      * @see org.kuali.rice.krad.uif.component.Component#pushObjectToContext(java.lang.String,
851      *      java.lang.Object)
852      */
853     public void pushObjectToContext(String objectName, Object object) {
854         if (this.context == null) {
855             this.context = new HashMap<String, Object>();
856         }
857         pushToPropertyReplacerContext(objectName, object);
858         this.context.put(objectName, object);
859     }
860 
861     /*
862     * Adds the object to the context of the components in the
863     * PropertyReplacer object. Only checks for a list, map or component.
864     */
865     protected void pushToPropertyReplacerContext(String objectName, Object object) {
866         for (Component replacerComponent : getPropertyReplacerComponents()) {
867             replacerComponent.pushObjectToContext(objectName, object);
868         }
869     }
870 
871     /**
872      * @see org.kuali.rice.krad.uif.component.ComponentBase#pushAllToContext
873      */
874     public void pushAllToContext(Map<String, Object> objects) {
875         if (objects != null) {
876             for (Map.Entry<String, Object> objectEntry : objects.entrySet()) {
877                 pushObjectToContext(objectEntry.getKey(), objectEntry.getValue());
878             }
879         }
880     }
881 
882     /**
883      * @see org.kuali.rice.krad.uif.component.Component#getPropertyReplacers()
884      */
885     @BeanTagAttribute(name = "propertyReplacers", type = BeanTagAttribute.AttributeType.LISTBEAN)
886     public List<PropertyReplacer> getPropertyReplacers() {
887         return this.propertyReplacers;
888     }
889 
890     /**
891      * @see org.kuali.rice.krad.uif.component.Component#setPropertyReplacers(java.util.List)
892      */
893     public void setPropertyReplacers(List<PropertyReplacer> propertyReplacers) {
894         this.propertyReplacers = propertyReplacers;
895     }
896 
897     /**
898      * @see org.springframework.core.Ordered#getOrder()
899      */
900     @BeanTagAttribute(name = "order")
901     public int getOrder() {
902         return this.order;
903     }
904 
905     /**
906      * Setter for the component's order
907      *
908      * @param order
909      */
910     public void setOrder(int order) {
911         this.order = order;
912     }
913 
914     /**
915      * @see org.kuali.rice.krad.uif.component.Component#getToolTip()
916      */
917     @BeanTagAttribute(name = "toolTip", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
918     public Tooltip getToolTip() {
919         return toolTip;
920     }
921 
922     /**
923      * @see org.kuali.rice.krad.uif.component.Component#setToolTip(Tooltip)
924      */
925     public void setToolTip(Tooltip toolTip) {
926         this.toolTip = toolTip;
927     }
928 
929     /**
930      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnLoadScript()
931      */
932     @BeanTagAttribute(name = "onLoadScript")
933     public String getOnLoadScript() {
934         return onLoadScript;
935     }
936 
937     /**
938      * Setter for the components onLoad script
939      *
940      * @param onLoadScript
941      */
942     public void setOnLoadScript(String onLoadScript) {
943         this.onLoadScript = onLoadScript;
944     }
945 
946     /**
947      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnDocumentReadyScript()
948      */
949     @BeanTagAttribute(name = "onDocumentReadyScript")
950     public String getOnDocumentReadyScript() {
951         String onDocScript = this.onDocumentReadyScript;
952         // if the refreshTimer property has been set then pre-append the call to refreshComponetUsingTimer to the onDocumentReadyScript.
953         // if the refreshTimer property is set then the methodToCallOnRefresh should also be set.
954         if (refreshTimer > 0) {
955             onDocScript = (null == onDocScript) ? "" : onDocScript;
956             onDocScript = "refreshComponentUsingTimer('"
957                     + this.id
958                     + "','"
959                     + this.methodToCallOnRefresh
960                     + "',"
961                     + refreshTimer
962                     + ");"
963                     + onDocScript;
964         }
965         return onDocScript;
966     }
967 
968     /**
969      * Setter for the components onDocumentReady script
970      *
971      * @param onDocumentReadyScript
972      */
973     public void setOnDocumentReadyScript(String onDocumentReadyScript) {
974         this.onDocumentReadyScript = onDocumentReadyScript;
975     }
976 
977     /**
978      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnUnloadScript()
979      */
980     @BeanTagAttribute(name = "onUnloadScript")
981     public String getOnUnloadScript() {
982         return onUnloadScript;
983     }
984 
985     /**
986      * Setter for the components onUnload script
987      *
988      * @param onUnloadScript
989      */
990     public void setOnUnloadScript(String onUnloadScript) {
991         this.onUnloadScript = onUnloadScript;
992     }
993 
994     /**
995      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnCloseScript()
996      */
997     @BeanTagAttribute(name = "onCloseScript")
998     public String getOnCloseScript() {
999         return onCloseScript;
1000     }
1001 
1002     /**
1003      * Setter for the components onClose script
1004      *
1005      * @param onCloseScript
1006      */
1007     public void setOnCloseScript(String onCloseScript) {
1008         this.onCloseScript = onCloseScript;
1009     }
1010 
1011     /**
1012      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnBlurScript()
1013      */
1014     @BeanTagAttribute(name = "onBlurScript")
1015     public String getOnBlurScript() {
1016         return onBlurScript;
1017     }
1018 
1019     /**
1020      * Setter for the components onBlur script
1021      *
1022      * @param onBlurScript
1023      */
1024     public void setOnBlurScript(String onBlurScript) {
1025         this.onBlurScript = onBlurScript;
1026     }
1027 
1028     /**
1029      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnChangeScript()
1030      */
1031     @BeanTagAttribute(name = "onChangeScript")
1032     public String getOnChangeScript() {
1033         return onChangeScript;
1034     }
1035 
1036     /**
1037      * Setter for the components onChange script
1038      *
1039      * @param onChangeScript
1040      */
1041     public void setOnChangeScript(String onChangeScript) {
1042         this.onChangeScript = onChangeScript;
1043     }
1044 
1045     /**
1046      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnClickScript()
1047      */
1048     @BeanTagAttribute(name = "onClickScript")
1049     public String getOnClickScript() {
1050         return onClickScript;
1051     }
1052 
1053     /**
1054      * Setter for the components onClick script
1055      *
1056      * @param onClickScript
1057      */
1058     public void setOnClickScript(String onClickScript) {
1059         this.onClickScript = onClickScript;
1060     }
1061 
1062     /**
1063      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnDblClickScript()
1064      */
1065     @BeanTagAttribute(name = "onDblClickScript")
1066     public String getOnDblClickScript() {
1067         return onDblClickScript;
1068     }
1069 
1070     /**
1071      * Setter for the components onDblClick script
1072      *
1073      * @param onDblClickScript
1074      */
1075     public void setOnDblClickScript(String onDblClickScript) {
1076         this.onDblClickScript = onDblClickScript;
1077     }
1078 
1079     /**
1080      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnFocusScript()
1081      */
1082     @BeanTagAttribute(name = "onFocusScript")
1083     public String getOnFocusScript() {
1084         return onFocusScript;
1085     }
1086 
1087     /**
1088      * Setter for the components onFocus script
1089      *
1090      * @param onFocusScript
1091      */
1092     public void setOnFocusScript(String onFocusScript) {
1093         this.onFocusScript = onFocusScript;
1094     }
1095 
1096     /**
1097      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnSubmitScript()
1098      */
1099     @BeanTagAttribute(name = "onSubmitScript")
1100     public String getOnSubmitScript() {
1101         return onSubmitScript;
1102     }
1103 
1104     /**
1105      * Setter for the components onSubmit script
1106      *
1107      * @param onSubmitScript
1108      */
1109     public void setOnSubmitScript(String onSubmitScript) {
1110         this.onSubmitScript = onSubmitScript;
1111     }
1112 
1113     /**
1114      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnKeyPressScript()
1115      */
1116     @BeanTagAttribute(name = "onKeyPressScript")
1117     public String getOnKeyPressScript() {
1118         return onKeyPressScript;
1119     }
1120 
1121     /**
1122      * Setter for the components onKeyPress script
1123      *
1124      * @param onKeyPressScript
1125      */
1126     public void setOnKeyPressScript(String onKeyPressScript) {
1127         this.onKeyPressScript = onKeyPressScript;
1128     }
1129 
1130     /**
1131      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnKeyUpScript()
1132      */
1133     @BeanTagAttribute(name = "onKeyUpScript")
1134     public String getOnKeyUpScript() {
1135         return onKeyUpScript;
1136     }
1137 
1138     /**
1139      * Setter for the components onKeyUp script
1140      *
1141      * @param onKeyUpScript
1142      */
1143     public void setOnKeyUpScript(String onKeyUpScript) {
1144         this.onKeyUpScript = onKeyUpScript;
1145     }
1146 
1147     /**
1148      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnKeyDownScript()
1149      */
1150     @BeanTagAttribute(name = "onKeyDownScript")
1151     public String getOnKeyDownScript() {
1152         return onKeyDownScript;
1153     }
1154 
1155     /**
1156      * Setter for the components onKeyDown script
1157      *
1158      * @param onKeyDownScript
1159      */
1160     public void setOnKeyDownScript(String onKeyDownScript) {
1161         this.onKeyDownScript = onKeyDownScript;
1162     }
1163 
1164     /**
1165      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseOverScript()
1166      */
1167     @BeanTagAttribute(name = "onMouseOverScript")
1168     public String getOnMouseOverScript() {
1169         return onMouseOverScript;
1170     }
1171 
1172     /**
1173      * Setter for the components onMouseOver script
1174      *
1175      * @param onMouseOverScript
1176      */
1177     public void setOnMouseOverScript(String onMouseOverScript) {
1178         this.onMouseOverScript = onMouseOverScript;
1179     }
1180 
1181     /**
1182      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseOutScript()
1183      */
1184     @BeanTagAttribute(name = "onMouseOutScript")
1185     public String getOnMouseOutScript() {
1186         return onMouseOutScript;
1187     }
1188 
1189     /**
1190      * Setter for the components onMouseOut script
1191      *
1192      * @param onMouseOutScript
1193      */
1194     public void setOnMouseOutScript(String onMouseOutScript) {
1195         this.onMouseOutScript = onMouseOutScript;
1196     }
1197 
1198     /**
1199      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseUpScript()
1200      */
1201     @BeanTagAttribute(name = "onMouseUpScript")
1202     public String getOnMouseUpScript() {
1203         return onMouseUpScript;
1204     }
1205 
1206     /**
1207      * Setter for the components onMouseUp script
1208      *
1209      * @param onMouseUpScript
1210      */
1211     public void setOnMouseUpScript(String onMouseUpScript) {
1212         this.onMouseUpScript = onMouseUpScript;
1213     }
1214 
1215     /**
1216      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseDownScript()
1217      */
1218     @BeanTagAttribute(name = "onMouseDownScript")
1219     public String getOnMouseDownScript() {
1220         return onMouseDownScript;
1221     }
1222 
1223     /**
1224      * Setter for the components onMouseDown script
1225      *
1226      * @param onMouseDownScript
1227      */
1228     public void setOnMouseDownScript(String onMouseDownScript) {
1229         this.onMouseDownScript = onMouseDownScript;
1230     }
1231 
1232     /**
1233      * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseMoveScript()
1234      */
1235     @BeanTagAttribute(name = "onMouseMoveScript")
1236     public String getOnMouseMoveScript() {
1237         return onMouseMoveScript;
1238     }
1239 
1240     /**
1241      * Setter for the components onMouseMove script
1242      *
1243      * @param onMouseMoveScript
1244      */
1245     public void setOnMouseMoveScript(String onMouseMoveScript) {
1246         this.onMouseMoveScript = onMouseMoveScript;
1247     }
1248 
1249     /**
1250      * @see org.kuali.rice.krad.uif.component.Component#getTemplateOptions()
1251      */
1252     @BeanTagAttribute(name = "templateOptions", type = BeanTagAttribute.AttributeType.MAPVALUE)
1253     public Map<String, String> getTemplateOptions() {
1254         if (templateOptions == null) {
1255             templateOptions = new HashMap<String, String>();
1256         }
1257         return this.templateOptions;
1258     }
1259 
1260     /**
1261      * @see Component#setTemplateOptions(java.util.Map)
1262      */
1263     public void setTemplateOptions(Map<String, String> templateOptions) {
1264         this.templateOptions = templateOptions;
1265     }
1266 
1267     /**
1268      * Builds a string from the underlying <code>Map</code> of template options
1269      * that will export that options as a JavaScript Map for use in js and
1270      * jQuery plugins
1271      *
1272      * @return String of widget options formatted as JS Map
1273      */
1274     @Override
1275     @BeanTagAttribute(name = "templateOptionsJSString")
1276     public String getTemplateOptionsJSString() {
1277         if (templateOptionsJSString != null) {
1278             return templateOptionsJSString;
1279         }
1280 
1281         if (templateOptions == null) {
1282             templateOptions = new HashMap<String, String>();
1283         }
1284         StringBuilder sb = new StringBuilder();
1285 
1286         sb.append("{");
1287 
1288         for (String optionKey : templateOptions.keySet()) {
1289             String optionValue = templateOptions.get(optionKey);
1290 
1291             if (sb.length() > 1) {
1292                 sb.append(",");
1293             }
1294 
1295             sb.append(optionKey);
1296             sb.append(":");
1297 
1298             sb.append(ScriptUtils.convertToJsValue(optionValue));
1299         }
1300 
1301         sb.append("}");
1302 
1303         return sb.toString();
1304     }
1305 
1306     @Override
1307     public void setTemplateOptionsJSString(String templateOptionsJSString) {
1308         this.templateOptionsJSString = templateOptionsJSString;
1309     }
1310 
1311     /**
1312      * When set if the condition is satisfied, the component will be displayed. The component MUST BE a
1313      * container or field type. progressiveRender is defined in a limited Spring EL syntax. Only valid
1314      * form property names, and, or, logical comparison operators (non-arithmetic), #listContains, #emptyList, matches
1315      * clause are allowed. String and regex values must use single quotes ('), booleans must be either true or false,
1316      * numbers must be a valid double, either negative or positive.
1317      *
1318      * <p>
1319      * DO NOT use progressiveRender and a conditional refresh statement on the same component
1320      * unless it is known that the component will always be visible in all cases when a conditional refresh happens
1321      * (ie conditional refresh has progressiveRender's condition anded with its own condition).
1322      * </p>
1323      *
1324      * <p>
1325      * <b>If a component should be refreshed every time it is shown, use the progressiveRenderAndRefresh option
1326      * with this property instead.</b>
1327      * </p>
1328      *
1329      * @return String progressiveRender expression
1330      */
1331     @BeanTagAttribute(name = "progressiveRender")
1332     public String getProgressiveRender() {
1333         return this.progressiveRender;
1334     }
1335 
1336     /**
1337      * @param progressiveRender the progressiveRender to set
1338      */
1339     public void setProgressiveRender(String progressiveRender) {
1340         this.progressiveRender = progressiveRender;
1341     }
1342 
1343     /**
1344      * When set if the condition is satisfied, the component will be refreshed.
1345      *
1346      * <p>The component MUST BE a container or field type. conditionalRefresh is
1347      * defined in a limited Spring EL syntax. Only valid form property names,
1348      * and, or, logical comparison operators (non-arithmetic), #listContains, #emptyList, and the matches
1349      * clause are allowed. String and regex values must use single quotes ('),
1350      * booleans must be either true or false, numbers must be a valid double
1351      * either negative or positive.
1352      *
1353      * <p>DO NOT use progressiveRender and conditionalRefresh on the same component
1354      * unless it is known that the component will always be visible in all cases
1355      * when a conditionalRefresh happens (ie conditionalRefresh has
1356      * progressiveRender's condition anded with its own condition). <b>If a
1357      * component should be refreshed every time it is shown, use the
1358      * progressiveRenderAndRefresh option with this property instead.</b></p>
1359      *
1360      * @return the conditionalRefresh
1361      */
1362     @BeanTagAttribute(name = "conditionalRefresh")
1363     public String getConditionalRefresh() {
1364         return this.conditionalRefresh;
1365     }
1366 
1367     /**
1368      * Set the conditional refresh condition
1369      *
1370      * @param conditionalRefresh the conditionalRefresh to set
1371      */
1372     public void setConditionalRefresh(String conditionalRefresh) {
1373         this.conditionalRefresh = conditionalRefresh;
1374     }
1375 
1376     /**
1377      * Control names used to control progressive disclosure, set internally
1378      * cannot be set.
1379      *
1380      * @return the progressiveDisclosureControlNames
1381      */
1382     public List<String> getProgressiveDisclosureControlNames() {
1383         return this.progressiveDisclosureControlNames;
1384     }
1385 
1386     /**
1387      * The condition to show this component progressively converted to a js
1388      * expression, set internally cannot be set.
1389      *
1390      * @return the progressiveDisclosureConditionJs
1391      */
1392     public String getProgressiveDisclosureConditionJs() {
1393         return this.progressiveDisclosureConditionJs;
1394     }
1395 
1396     /**
1397      * The condition to refresh this component converted to a js expression, set
1398      * internally cannot be set.
1399      *
1400      * @return the conditionalRefreshConditionJs
1401      */
1402     public String getConditionalRefreshConditionJs() {
1403         return this.conditionalRefreshConditionJs;
1404     }
1405 
1406     /**
1407      * Control names used to control conditional refresh, set internally cannot
1408      * be set.
1409      *
1410      * @return the conditionalRefreshControlNames
1411      */
1412     public List<String> getConditionalRefreshControlNames() {
1413         return this.conditionalRefreshControlNames;
1414     }
1415 
1416     /**
1417      * When progressiveRenderViaAJAX is true, this component will be retrieved
1418      * from the server when it first satisfies its progressive render condition.
1419      *
1420      * <p>After the first retrieval, it is hidden/shown in the html by the js when
1421      * its progressive condition result changes. <b>By default, this is false,
1422      * so components with progressive render capabilities will always be already
1423      * within the client html and toggled to be hidden or visible.</b></p>
1424      *
1425      * @return the progressiveRenderViaAJAX
1426      */
1427     @BeanTagAttribute(name = "progressiveRenderViaAJAX")
1428     public boolean isProgressiveRenderViaAJAX() {
1429         return this.progressiveRenderViaAJAX;
1430     }
1431 
1432     /**
1433      * @param progressiveRenderViaAJAX the progressiveRenderViaAJAX to set
1434      */
1435     public void setProgressiveRenderViaAJAX(boolean progressiveRenderViaAJAX) {
1436         this.progressiveRenderViaAJAX = progressiveRenderViaAJAX;
1437     }
1438 
1439     /**
1440      * If true, when the progressiveRender condition is satisfied, the component
1441      * will always be retrieved from the server and shown(as opposed to being
1442      * stored on the client, but hidden, after the first retrieval as is the
1443      * case with the progressiveRenderViaAJAX option).
1444      *
1445      * <p><b>By default, this is
1446      * false, so components with progressive render capabilities will always be
1447      * already within the client html and toggled to be hidden or visible.</b></p>
1448      *
1449      * @return the progressiveRenderAndRefresh
1450      */
1451     @BeanTagAttribute(name = "progressiveRenderAndRefresh")
1452     public boolean isProgressiveRenderAndRefresh() {
1453         return this.progressiveRenderAndRefresh;
1454     }
1455 
1456     /**
1457      * Set the progressive render and refresh option.
1458      *
1459      * @param progressiveRenderAndRefresh the progressiveRenderAndRefresh to set
1460      */
1461     public void setProgressiveRenderAndRefresh(boolean progressiveRenderAndRefresh) {
1462         this.progressiveRenderAndRefresh = progressiveRenderAndRefresh;
1463     }
1464 
1465     /**
1466      * @see org.kuali.rice.krad.uif.component.Component#getRefreshWhenChangedPropertyNames()
1467      */
1468     @BeanTagAttribute(name = "refreshWhenChangedPropertyNames", type = BeanTagAttribute.AttributeType.LISTVALUE)
1469     public List<String> getRefreshWhenChangedPropertyNames() {
1470         return this.refreshWhenChangedPropertyNames;
1471     }
1472 
1473     /**
1474      * @see org.kuali.rice.krad.uif.component.Component#setRefreshWhenChangedPropertyNames(java.util.List<java.lang.String>)
1475      */
1476     public void setRefreshWhenChangedPropertyNames(List<String> refreshWhenChangedPropertyNames) {
1477         this.refreshWhenChangedPropertyNames = refreshWhenChangedPropertyNames;
1478     }
1479 
1480     /**
1481      * @see org.kuali.rice.krad.uif.component.Component#getAdditionalComponentsToRefresh()
1482      */
1483     @BeanTagAttribute(name = "additionalComponentsToRefresh", type = BeanTagAttribute.AttributeType.LISTVALUE)
1484     public List<String> getAdditionalComponentsToRefresh() {
1485         return additionalComponentsToRefresh;
1486     }
1487 
1488     /**
1489      * @see org.kuali.rice.krad.uif.component.Component#setAdditionalComponentsToRefresh(java.util.List<java.lang.String>)
1490      */
1491     public void setAdditionalComponentsToRefresh(List<String> additionalComponentsToRefresh) {
1492         this.additionalComponentsToRefresh = additionalComponentsToRefresh;
1493     }
1494 
1495     /**
1496      * @see org.kuali.rice.krad.uif.component.Component#isRefreshedByAction()
1497      */
1498     public boolean isRefreshedByAction() {
1499         return refreshedByAction;
1500     }
1501 
1502     /**
1503      * @see org.kuali.rice.krad.uif.component.Component#setRefreshedByAction(boolean)
1504      */
1505     public void setRefreshedByAction(boolean refreshedByAction) {
1506         this.refreshedByAction = refreshedByAction;
1507     }
1508 
1509     /**
1510      * @see org.kuali.rice.krad.uif.component.Component#isDisclosedByAction()
1511      */
1512     public boolean isDisclosedByAction() {
1513         return disclosedByAction;
1514     }
1515 
1516     /**
1517      * @see Component#setDisclosedByAction(boolean)
1518      */
1519     public void setDisclosedByAction(boolean disclosedByAction) {
1520         this.disclosedByAction = disclosedByAction;
1521     }
1522 
1523     /**
1524      * Time in seconds that the component will be automatically refreshed
1525      *
1526      * <p>
1527      * This will invoke the refresh process just like the conditionalRefresh and refreshWhenChangedPropertyNames.
1528      * When using this property methodToCallOnRefresh and id should also be specified
1529      * </p>
1530      *
1531      * @return refreshTimer
1532      */
1533     @BeanTagAttribute(name = "refreshTimer")
1534     public int getRefreshTimer() {
1535         return refreshTimer;
1536     }
1537 
1538     /**
1539      * Setter for refreshTimer
1540      *
1541      * @param refreshTimer
1542      */
1543     public void setRefreshTimer(int refreshTimer) {
1544         this.refreshTimer = refreshTimer;
1545     }
1546 
1547     /**
1548      * @see  org.kuali.rice.krad.uif.component.Component#isResetDataOnRefresh()
1549      */
1550     @BeanTagAttribute(name = "resetDataOnRefresh")
1551     public boolean isResetDataOnRefresh() {
1552         return resetDataOnRefresh;
1553     }
1554 
1555     /**
1556      * @see org.kuali.rice.krad.uif.component.Component#setResetDataOnRefresh(boolean)
1557      */
1558     public void setResetDataOnRefresh(boolean resetDataOnRefresh) {
1559         this.resetDataOnRefresh = resetDataOnRefresh;
1560     }
1561 
1562     /**
1563      * Name of a method on the controller that should be invoked as part of the component refresh and disclosure
1564      * process
1565      *
1566      * <p>
1567      * During the component refresh or disclosure process it might be necessary to perform other operations, such as
1568      * preparing data or executing a business process. This allows the configuration of a method on the underlying
1569      * controller that should be called for the component refresh action. In this method, the necessary logic can be
1570      * performed and then the base component update method invoked to carry out the component refresh.
1571      * </p>
1572      *
1573      * <p>
1574      * Controller method to invoke must accept the form, binding result, request, and response arguments
1575      * </p>
1576      *
1577      * @return String valid controller method name
1578      */
1579     @BeanTagAttribute(name = "methodToCallOnRefresh")
1580     public String getMethodToCallOnRefresh() {
1581         return methodToCallOnRefresh;
1582     }
1583 
1584     /**
1585      * Setter for the controller method to call for a refresh or disclosure action on this component
1586      *
1587      * @param methodToCallOnRefresh
1588      */
1589     public void setMethodToCallOnRefresh(String methodToCallOnRefresh) {
1590         this.methodToCallOnRefresh = methodToCallOnRefresh;
1591     }
1592 
1593     /**
1594      * @param skipInTabOrder flag
1595      */
1596     public void setSkipInTabOrder(boolean skipInTabOrder) {
1597         this.skipInTabOrder = skipInTabOrder;
1598     }
1599 
1600     /**
1601      * Flag indicating that this component and its nested components must be
1602      * skipped when keyboard tabbing.
1603      *
1604      * @return the skipInTabOrder flag
1605      */
1606     @BeanTagAttribute(name = "skipInTabOrder")
1607     public boolean isSkipInTabOrder() {
1608         return skipInTabOrder;
1609     }
1610 
1611     /**
1612      * Get the dataAttributes setup for this component - to be written to the html/jQuery data
1613      *
1614      * <p>The attributes that are complex objects (contain {}) they will be written through script.
1615      * The attritubes that are simple (contain no objects) will be written directly to the html of the
1616      * component using standard data-.
1617      * Either way they can be access through .data() call in jQuery</p>
1618      *
1619      * @return map of dataAttributes
1620      */
1621     @BeanTagAttribute(name = "dataAttributes", type = BeanTagAttribute.AttributeType.MAPVALUE)
1622     public Map<String, String> getDataAttributes() {
1623         return dataAttributes;
1624     }
1625 
1626     /**
1627      * DataAttributes that will be written to the html and/or through script to be consumed by jQuery.
1628      *
1629      * @param dataAttributes the data attributes to set for this component
1630      */
1631     public void setDataAttributes(Map<String, String> dataAttributes) {
1632         this.dataAttributes = dataAttributes;
1633     }
1634 
1635     /**
1636      * Add a data attribute to the dataAttributes map - to be written to the html/jQuery data.
1637      *
1638      * @param key key of the data attribute
1639      * @param value value of the data attribute
1640      */
1641     public void addDataAttribute(String key, String value) {
1642         dataAttributes.put(key, value);
1643     }
1644 
1645     /**
1646      * Add a data attribute to the dataAttributes map if the given value is non null
1647      * or the empty string
1648      *
1649      * @param key - key for the data attribute entry
1650      * @param value - value for the data attribute
1651      */
1652     public void addDataAttributeIfNonEmpty(String key, String value) {
1653         if (StringUtils.isNotBlank(value)) {
1654             addDataAttribute(key, value);
1655         }
1656     }
1657 
1658     /**
1659      * Returns js that will add data to this component by the element which matches its id.
1660      * This will return script for only the complex data elements (containing {});
1661      *
1662      * @return jQuery data script for adding complex data attributes
1663      */
1664     public String getComplexDataAttributesJs() {
1665         String js = "";
1666         if (getDataAttributes() == null) {
1667             return js;
1668         } else {
1669             for (Map.Entry<String, String> data : getDataAttributes().entrySet()) {
1670                 if (data != null && data.getValue() != null &&
1671                         data.getValue().trim().startsWith("{") && data.getValue().trim().endsWith("}")) {
1672                     js = js + "jQuery('#" + this.getId() + "').data('" + data.getKey() + "', " + data.getValue() + ");";
1673                 }
1674             }
1675             return js;
1676         }
1677     }
1678 
1679     /**
1680      * Returns a string that can be put into a the tag of a component to add data attributes inline.
1681      * This does not include the complex attributes which contain {}
1682      *
1683      * @return html string for data attributes for the simple attributes
1684      */
1685     public String getSimpleDataAttributes() {
1686         String attributes = "";
1687         if (getDataAttributes() == null) {
1688             return attributes;
1689         } else {
1690             for (Map.Entry<String, String> data : getDataAttributes().entrySet()) {
1691                 if (data != null && data.getValue() != null && !data.getValue().trim().startsWith("{")) {
1692                     attributes = attributes + " " + "data-" + data.getKey() + "=\"" + data.getValue() + "\"";
1693                 }
1694             }
1695             return attributes;
1696         }
1697     }
1698 
1699     /**
1700      * @see org.kuali.rice.krad.uif.component.Component#getAllDataAttributesJs()
1701      */
1702     @Override
1703     public String getAllDataAttributesJs() {
1704         String js = "";
1705         if (getDataAttributes() == null) {
1706             return js;
1707         } else {
1708             for (Map.Entry<String, String> data : getDataAttributes().entrySet()) {
1709                 js = js + "jQuery('#" + this.getId() + "').data('" + data.getKey() + "', " + ScriptUtils
1710                         .convertToJsValue(data.getValue()) + ");";
1711             }
1712             return js;
1713         }
1714     }
1715 
1716     /**
1717      * @see org.kuali.rice.krad.uif.component.Component#getAdditionalComponentsToRefreshJs
1718      */
1719     public String getAdditionalComponentsToRefreshJs() {
1720         if (!(this.getAdditionalComponentsToRefresh().isEmpty())) {
1721             additionalComponentsToRefreshJs = ScriptUtils.convertStringListToJsArray(
1722                     this.getAdditionalComponentsToRefresh());
1723         }
1724 
1725         return additionalComponentsToRefreshJs;
1726     }
1727 
1728     /**
1729      * @see org.kuali.rice.krad.uif.component.Component#completeValidation
1730      */
1731     public void completeValidation(ValidationTrace tracer) {
1732         tracer.addBean(this);
1733 
1734         // Check for invalid characters in the components id
1735         if (getId() != null) {
1736             if (getId().contains("'")
1737                     || getId().contains("\"")
1738                     || getId().contains("[]")
1739                     || getId().contains(".")
1740                     || getId().contains("#")) {
1741                 String currentValues[] = {"id = " + getId()};
1742                 tracer.createError("Id contains invalid characters", currentValues);
1743             }
1744         }
1745 
1746         if (tracer.getValidationStage() == ValidationTrace.BUILD) {
1747             // Check for a render presence if the component is set to render
1748             if ((isProgressiveRenderViaAJAX() || isProgressiveRenderAndRefresh()) && (getProgressiveRender() == null)) {
1749                 String currentValues[] = {"progressiveRenderViaAJAX = " + isProgressiveRenderViaAJAX(),
1750                         "progressiveRenderAndRefresh = " + isProgressiveRenderAndRefresh(),
1751                         "progressiveRender = " + getProgressiveRender()};
1752                 tracer.createError(
1753                         "ProgressiveRender must be set if progressiveRenderViaAJAX or progressiveRenderAndRefresh are true",
1754                         currentValues);
1755             }
1756         }
1757 
1758         // Check for rendered html if the component is set to self render
1759         if (isSelfRendered() && getRenderedHtmlOutput() == null) {
1760             String currentValues[] =
1761                     {"selfRendered = " + isSelfRendered(), "renderedHtmlOutput = " + getRenderedHtmlOutput()};
1762             tracer.createError("RenderedHtmlOutput must be set if selfRendered is true", currentValues);
1763         }
1764 
1765         // Check to prevent over writing of session persistence status
1766         if (isDisableSessionPersistence() && isForceSessionPersistence()) {
1767             String currentValues[] = {"disableSessionPersistence = " + isDisableSessionPersistence(),
1768                     "forceSessionPersistence = " + isForceSessionPersistence()};
1769             tracer.createWarning("DisableSessionPersistence and forceSessionPersistence cannot be both true",
1770                     currentValues);
1771         }
1772 
1773         // Check for un-executable data resets when no refresh option is set
1774         if (getMethodToCallOnRefresh() != null || isResetDataOnRefresh()) {
1775             if (!isProgressiveRenderAndRefresh()
1776                     && !isRefreshedByAction()
1777                     && !isProgressiveRenderViaAJAX()
1778                     && !StringUtils.isNotEmpty(conditionalRefresh)
1779                     && !(refreshTimer > 0)) {
1780                 String currentValues[] = {"methodToCallONRefresh = " + getMethodToCallOnRefresh(),
1781                         "resetDataONRefresh = " + isResetDataOnRefresh(),
1782                         "progressiveRenderAndRefresh = " + isProgressiveRenderAndRefresh(),
1783                         "refreshedByAction = " + isRefreshedByAction(),
1784                         "progressiveRenderViaAJAX = " + isProgressiveRenderViaAJAX(),
1785                         "conditionalRefresh = " + getConditionalRefresh(), "refreshTimer = " + getRefreshTimer()};
1786                 tracer.createWarning(
1787                         "MethodToCallONRefresh and resetDataONRefresh should only be set when a trigger event is set",
1788                         currentValues);
1789             }
1790         }
1791 
1792         // Check to prevent complications with rendering and refreshing a component that is not always shown
1793         if (StringUtils.isNotEmpty(getProgressiveRender()) && StringUtils.isNotEmpty(conditionalRefresh)) {
1794             String currentValues[] = {"progressiveRender = " + getProgressiveRender(),
1795                     "conditionalRefresh = " + getConditionalRefresh()};
1796             tracer.createWarning("DO NOT use progressiveRender and conditionalRefresh on the same component unless "
1797                     + "it is known that the component will always be visible in all cases when a conditionalRefresh "
1798                     + "happens (ie conditionalRefresh has progressiveRender's condition anded with its own condition). "
1799                     + "If a component should be refreshed every time it is shown, use the progressiveRenderAndRefresh "
1800                     + "option with this property instead.", currentValues);
1801         }
1802 
1803         // Check for valid Spring EL format for progressiveRender
1804         if (!Validator.validateSpringEL(getProgressiveRender())) {
1805             String currentValues[] = {"progressiveRender =" + getProgressiveRender()};
1806             tracer.createError("ProgressiveRender must follow the Spring EL @{} format", currentValues);
1807         }
1808 
1809         // Check for valid Spring EL format for conditionalRefresh
1810         if (!Validator.validateSpringEL(getConditionalRefresh())) {
1811             String currentValues[] = {"conditionalRefresh =" + getConditionalRefresh()};
1812             tracer.createError("conditionalRefresh must follow the Spring EL @{} format", currentValues);
1813             ;
1814         }
1815     }
1816 
1817 }