View Javadoc

1   /*
2    * $Id: UIBean.java 630742 2008-02-25 06:26:12Z rgielen $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  package org.apache.struts2.components;
22  
23  import java.io.Writer;
24  import java.util.Iterator;
25  import java.util.LinkedHashMap;
26  import java.util.List;
27  import java.util.Map;
28  
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpServletResponse;
31  
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.apache.struts2.views.annotations.StrutsTagAttribute;
35  import org.apache.struts2.StrutsConstants;
36  import org.apache.struts2.components.template.Template;
37  import org.apache.struts2.components.template.TemplateEngine;
38  import org.apache.struts2.components.template.TemplateEngineManager;
39  import org.apache.struts2.components.template.TemplateRenderingContext;
40  import org.apache.struts2.views.util.ContextUtil;
41  
42  import com.opensymphony.xwork2.config.ConfigurationException;
43  import com.opensymphony.xwork2.inject.Inject;
44  import com.opensymphony.xwork2.util.ValueStack;
45  
46  /***
47   * UIBean is the standard superclass of all Struts UI componentns.
48   * It defines common Struts and html properties all UI components should present for usage.
49   *
50   * <!-- START SNIPPET: templateRelatedAttributes -->
51   *
52   * <table border="1">
53   *    <thead>
54   *       <tr>
55   *          <td>Attribute</td>
56   *          <td>Theme</td>
57   *          <td>Data Types</td>
58   *          <td>Description</td>
59   *       </tr>
60   *    </thead>
61   *    <tbody>
62   *       <tr>
63   *          <td>templateDir</td>
64   *          <td>n/a</td>
65   *          <td>String</td>
66   *          <td>define the template directory</td>
67   *       </td>
68   *       <tr>
69   *          <td>theme</td>
70   *          <td>n/a</td>
71   *          <td>String</td>
72   *          <td>define the theme name</td>
73   *       </td>
74   *       <tr>
75   *          <td>template</td>
76   *          <td>n/a</td>
77   *          <td>String</td>
78   *          <td>define the template name</td>
79   *       </td>
80   *    </tbody>
81   * </table>
82   *
83   * <!-- END SNIPPET: templateRelatedAttributes -->
84   *
85   * <p/>
86   *
87   * <!-- START SNIPPET: generalAttributes -->
88   *
89   * <table border="1">
90   *    <thead>
91   *       <tr>
92   *          <td>Attribute</td>
93   *          <td>Theme</td>
94   *          <td>Data Types</td>
95   *          <td>Description</td>
96   *       </tr>
97   *    </thead>
98   *    <tbody>
99   *       <tr>
100  *          <td>cssClass</td>
101  *          <td>simple</td>
102  *          <td>String</td>
103  *          <td>define html class attribute</td>
104  *       </tr>
105  *       <tr>
106  *          <td>cssStyle</td>
107  *          <td>simple</td>
108  *          <td>String</td>
109  *          <td>define html style attribute</td>
110  *       </tr>
111  *       <tr>
112  *          <td>title</td>
113  *          <td>simple</td>
114  *          <td>String</td>
115  *          <td>define html title attribute</td>
116  *       </tr>
117  *       <tr>
118  *          <td>disabled</td>
119  *          <td>simple</td>
120  *          <td>String</td>
121  *          <td>define html disabled attribute</td>
122  *       </tr>
123  *       <tr>
124  *          <td>label</td>
125  *          <td>xhtml</td>
126  *          <td>String</td>
127  *          <td>define label of form element</td>
128  *       </tr>
129  *       <tr>
130  *          <td>labelPosition</td>
131  *          <td>xhtml</td>
132  *          <td>String</td>
133  *          <td>define label position of form element (top/left), default to left</td>
134  *       </tr>
135  *       <tr>
136  *          <td>requiredposition</td>
137  *          <td>xhtml</td>
138  *          <td>String</td>
139  *          <td>define required label position of form element (left/right), default to right</td>
140  *       </tr>
141  *       <tr>
142  *          <td>name</td>
143  *          <td>simple</td>
144  *          <td>String</td>
145  *          <td>Form Element's field name mapping</td>
146  *       </tr>
147  *       <tr>
148  *          <td>required</td>
149  *          <td>xhtml</td>
150  *          <td>Boolean</td>
151  *          <td>add * to label (true to add false otherwise)</td>
152  *       </tr>
153  *       <tr>
154  *          <td>tabIndex</td>
155  *          <td>simple</td>
156  *          <td>String</td>
157  *          <td>define html tabindex attribute</td>
158  *       </tr>
159  *       <tr>
160  *          <td>value</td>
161  *          <td>simple</td>
162  *          <td>Object</td>
163  *          <td>define value of form element</td>
164  *       </tr>
165  *    </tbody>
166  * </table>
167  *
168  * <!-- END SNIPPET: generalAttributes -->
169  *
170  * <p/>
171  *
172  * <!-- START SNIPPET: javascriptRelatedAttributes -->
173  *
174  * <table border="1">
175  *    <thead>
176  *       <tr>
177  *          <td>Attribute</td>
178  *          <td>Theme</td>
179  *          <td>Data Types</td>
180  *          <td>Description</td>
181  *       </tr>
182  *    </thead>
183  *    <tbody>
184  *       <tr>
185  *          <td>onclick</td>
186  *          <td>simple</td>
187  *          <td>String</td>
188  *          <td>html javascript onclick attribute</td>
189  *       </tr>
190  *       <tr>
191  *          <td>ondbclick</td>
192  *          <td>simple</td>
193  *          <td>String</td>
194  *          <td>html javascript ondbclick attribute</td>
195  *       </tr>
196  *       <tr>
197  *          <td>onmousedown</td>
198  *          <td>simple</td>
199  *          <td>String</td>
200  *          <td>html javascript onmousedown attribute</td>
201  *       </tr>
202  *       <tr>
203  *          <td>onmouseup</td>
204  *          <td>simple</td>
205  *          <td>String</td>
206  *          <td>html javascript onmouseup attribute</td>
207  *       </tr>
208  *       <tr>
209  *          <td>onmouseover</td>
210  *          <td>simple</td>
211  *          <td>String</td>
212  *          <td>html javascript onmouseover attribute</td>
213  *       </tr>
214  *       <tr>
215  *          <td>onmouseout</td>
216  *          <td>simple</td>
217  *          <td>String</td>
218  *          <td>html javascript onmouseout attribute</td>
219  *       </tr>
220  *       <tr>
221  *          <td>onfocus</td>
222  *          <td>simple</td>
223  *          <td>String</td>
224  *          <td>html javascript onfocus attribute</td>
225  *       </tr>
226  *       <tr>
227  *          <td>onblur</td>
228  *          <td>simple</td>
229  *          <td>String</td>
230  *          <td>html javascript onblur attribute</td>
231  *       </tr>
232  *       <tr>
233  *          <td>onkeypress</td>
234  *          <td>simple</td>
235  *          <td>String</td>
236  *          <td>html javascript onkeypress attribute</td>
237  *       </tr>
238  *       <tr>
239  *          <td>onkeyup</td>
240  *          <td>simple</td>
241  *          <td>String</td>
242  *          <td>html javascript onkeyup attribute</td>
243  *       </tr>
244  *       <tr>
245  *          <td>onkeydown</td>
246  *          <td>simple</td>
247  *          <td>String</td>
248  *          <td>html javascript onkeydown attribute</td>
249  *       </tr>
250  *       <tr>
251  *          <td>onselect</td>
252  *          <td>simple</td>
253  *          <td>String</td>
254  *          <td>html javascript onselect attribute</td>
255  *       </tr>
256  *       <tr>
257  *          <td>onchange</td>
258  *          <td>simple</td>
259  *          <td>String</td>
260  *          <td>html javascript onchange attribute</td>
261  *       </tr>
262  *    </tbody>
263  * </table>
264  *
265  * <!-- END SNIPPET: javascriptRelatedAttributes -->
266  *
267  * <p/>
268  *
269  * <!-- START SNIPPET: tooltipattributes -->
270  *
271  * <table border="1">
272  *  <tr>
273  *     <td>Attribute</td>
274  *     <td>Data Type</td>
275  *     <td>Default</td>
276  *     <td>Description</td>
277  *  </tr>
278  *  <tr>
279  *      <td>tooltip</td>
280  *      <td>String</td>
281  *      <td>none</td>
282  *      <td>Set the tooltip of this particular component</td>
283  *  </tr>
284  *  <tr>
285  *      <td>jsTooltipEnabled</td>
286  *      <td>String</td>
287  *      <td>false</td>
288  *      <td>Enable js tooltip rendering</td>
289  *  </tr>
290  *    <tr>
291  *      <td>tooltipIcon</td>
292  *      <td>String</td>
293  *      <td>/struts/static/tooltip/tooltip.gif</td>
294  *      <td>The url to the tooltip icon</td>
295  *   <tr>
296  *      <td>tooltipDelay</td>
297  *      <td>String</td>
298  *      <td>500</td>
299  *      <td>Tooltip shows up after the specified timeout (miliseconds). A behavior similar to that of OS based tooltips.</td>
300  *   </tr>
301  *   <tr>
302  *      <td>key</td>
303  *      <td>simple</td>
304  *      <td>String</td>
305  *      <td>The name of the property this input field represents.  This will auto populate the name, label, and value</td>
306  *   </tr>
307  * </table>
308  *
309  * <!-- END SNIPPET: tooltipattributes -->
310  *
311  *
312  * <!-- START SNIPPET: tooltipdescription -->
313  *
314  * Every Form UI component (in xhtml / css_xhtml or any others that extends of them) could
315  * have tooltip assigned to a them. The Form component's tooltip related attribute once
316  * defined will be applicable to all form UI component that is created under it unless
317  * explicitly overriden by having the Form UI component itself defined that tooltip attribute.
318  *
319  * <p/>
320  *
321  * In Example 1, the textfield will inherit the tooltipDelay adn tooltipIcon attribte from
322  * its containing form. In other words, although it doesn't defined a tooltipAboveMousePointer
323  * attribute, it will have that attributes inherited from its containing form.
324  *
325  * <p/>
326  *
327  * In Example 2, the the textfield will inherite both the tooltipDelay and
328  * tooltipIcon attribute from its containing form but tooltipDelay
329  * attribute is overriden at the textfield itself. Hence, the textfield actually will
330  * have tooltipIcon defined as /myImages/myIcon.gif, inherited from its containing form and
331  * tooltipDelay defined as 5000, due to overriden at the textfield itself.
332  *
333  * <p/>
334  *
335  * Example 3, 4 and 5 shows different way of setting the tooltipConfig attribute.<br/>
336  * <b>Example 3:</b>Set tooltip config through body of param tag<br/>
337  * <b>Example 4:</b>Set tooltip config through value attribute of param tag<br/>
338  * <b>Example 5:</b>Set tooltip config through tooltipConfig attribute of component tag<br/>
339  *
340  * <!-- END SNIPPET: tooltipdescription -->
341  *
342  *
343  * <pre>
344  * <!-- START SNIPPET: tooltipexample -->
345  *
346  * &lt;!-- Example 1: --&gt;
347  * &lt;s:form
348  *          tooltipConfig="#{'tooltipDelay':'500',
349  *                           'tooltipIcon='/myImages/myIcon.gif'}" .... &gt;
350  *   ....
351  *     &lt;s:textfield label="Customer Name" tooltip="Enter the customer name" .... /&gt;
352  *   ....
353  * &lt;/s:form&gt;
354  *
355  * &lt;!-- Example 2: --&gt;
356  * &lt;s:form
357  *         tooltipConfig="#{'tooltipDelay':'500',
358  *                          'tooltipIcon':'/myImages/myIcon.gif'}" ... &gt;
359  *   ....
360  *     &lt;s:textfield label="Address"
361  *          tooltip="Enter your address"
362  *          tooltipConfig="#{'tooltipDelay':'5000'}" /&gt;
363  *   ....
364  * &lt;/s:form&gt;
365  *
366  *
367  * &lt;-- Example 3: --&gt;
368  * &lt;s:textfield
369  *        label="Customer Name"
370  *        tooltip="One of our customer Details'"&gt;
371  *        &lt;s:param name="tooltipConfig"&gt;
372  *             tooltipDelay = 500 |
373  *             tooltipIcon = /myImages/myIcon.gif
374  *        &lt;/s:param&gt;
375  * &lt;/s:textfield&gt;
376  *
377  *
378  * &lt;-- Example 4: --&gt;
379  * &lt;s:textfield
380  *          label="Customer Address"
381  *          tooltip="Enter The Customer Address" &gt;
382  *          &lt;s:param
383  *              name="tooltipConfig"
384  *              value="#{'tooltipDelay':'500',
385  *                       'tooltipIcon':'/myImages/myIcon.gif'}" /&gt;
386  * &lt;/s:textfield&gt;
387  *
388  *
389  * &lt;-- Example 5: --&gt;
390  * &lt;s:textfield
391  *          label="Customer Telephone Number"
392  *          tooltip="Enter customer Telephone Number"
393  *          tooltipConfig="#{'tooltipDelay':'500',
394  *                           'tooltipIcon':'/myImages/myIcon.gif'}" /&gt;
395  *
396  * <!-- END SNIPPET: tooltipexample -->
397  * </pre>
398  *
399  */
400 public abstract class UIBean extends Component {
401     private static final Log LOG = LogFactory.getLog(UIBean.class);
402 
403     protected HttpServletRequest request;
404     protected HttpServletResponse response;
405 
406     public UIBean(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
407         super(stack);
408         this.request = request;
409         this.response = response;
410         this.templateSuffix = ContextUtil.getTemplateSuffix(stack.getContext());
411     }
412 
413     // The templateSuffic to use, overrides the default one if not null.
414     protected String templateSuffix;
415 
416     // The template to use, overrides the default one.
417     protected String template;
418 
419     // templateDir and theme attributes
420     protected String templateDir;
421     protected String theme;
422 
423     // shortcut, sets label, name, and value
424     protected String key;
425 
426     protected String cssClass;
427     protected String cssStyle;
428     protected String disabled;
429     protected String label;
430     protected String labelPosition;
431     protected String requiredposition;
432     protected String name;
433     protected String required;
434     protected String tabindex;
435     protected String value;
436     protected String title;
437 
438     // HTML scripting events attributes
439     protected String onclick;
440     protected String ondblclick;
441     protected String onmousedown;
442     protected String onmouseup;
443     protected String onmouseover;
444     protected String onmousemove;
445     protected String onmouseout;
446     protected String onfocus;
447     protected String onblur;
448     protected String onkeypress;
449     protected String onkeydown;
450     protected String onkeyup;
451     protected String onselect;
452     protected String onchange;
453 
454     // common html attributes
455     protected String accesskey;
456 
457     // javascript tooltip attribute
458     protected String tooltip;
459     protected String tooltipConfig;
460 
461     protected String defaultTemplateDir;
462     protected String defaultUITheme;
463     protected TemplateEngineManager templateEngineManager;
464 
465     @Inject(StrutsConstants.STRUTS_UI_TEMPLATEDIR)
466     public void setDefaultTemplateDir(String dir) {
467         this.defaultTemplateDir = dir;
468     }
469 
470     @Inject(StrutsConstants.STRUTS_UI_THEME)
471     public void setDefaultUITheme(String theme) {
472         this.defaultUITheme = theme;
473     }
474 
475     @Inject
476     public void setTemplateEngineManager(TemplateEngineManager mgr) {
477         this.templateEngineManager = mgr;
478     }
479 
480     public boolean end(Writer writer, String body) {
481         evaluateParams();
482         try {
483             super.end(writer, body, false);
484             mergeTemplate(writer, buildTemplateName(template, getDefaultTemplate()));
485         } catch (Exception e) {
486             LOG.error("error when rendering", e);
487         }
488         finally {
489             popComponentStack();
490         }
491 
492         return false;
493     }
494 
495     /***
496      * A contract that requires each concrete UI Tag to specify which template should be used as a default.  For
497      * example, the CheckboxTab might return "checkbox.vm" while the RadioTag might return "radio.vm".  This value
498      * <strong>not</strong> begin with a '/' unless you intend to make the path absolute rather than relative to the
499      * current theme.
500      *
501      * @return The name of the template to be used as the default.
502      */
503     protected abstract String getDefaultTemplate();
504 
505     protected Template buildTemplateName(String myTemplate, String myDefaultTemplate) {
506         String template = myDefaultTemplate;
507 
508         if (myTemplate != null) {
509             template = findString(myTemplate);
510         }
511 
512         String templateDir = getTemplateDir();
513         String theme = getTheme();
514 
515         return new Template(templateDir, theme, template);
516 
517     }
518 
519     protected void mergeTemplate(Writer writer, Template template) throws Exception {
520         final TemplateEngine engine = templateEngineManager.getTemplateEngine(template, templateSuffix);
521         if (engine == null) {
522             throw new ConfigurationException("Unable to find a TemplateEngine for template " + template);
523         }
524 
525         if (LOG.isDebugEnabled()) {
526             LOG.debug("Rendering template " + template);
527         }
528 
529         final TemplateRenderingContext context = new TemplateRenderingContext(template, writer, getStack(), getParameters(), this);
530         engine.renderTemplate(context);
531     }
532 
533     public String getTemplateDir() {
534         String templateDir = null;
535 
536         if (this.templateDir != null) {
537             templateDir = findString(this.templateDir);
538         }
539 
540         // If templateDir is not explicitly given,
541         // try to find attribute which states the dir set to use
542         if ((templateDir == null) || (templateDir.equals(""))) {
543             templateDir = (String) stack.findValue("#attr.templateDir");
544         }
545 
546         // Default template set
547         if ((templateDir == null) || (templateDir.equals(""))) {
548             templateDir = defaultTemplateDir;
549         }
550 
551         // Defaults to 'template'
552         if ((templateDir == null) || (templateDir.equals(""))) {
553             templateDir = "template";
554         }
555 
556         return templateDir;
557     }
558 
559     public String getTheme() {
560         String theme = null;
561 
562         if (this.theme != null) {
563             theme = findString(this.theme);
564         }
565 
566         if ( theme == null || theme.equals("") ) {
567             Form form = (Form) findAncestor(Form.class);
568             if (form != null) {
569                 theme = form.getTheme();
570             }
571         }
572 
573         // If theme set is not explicitly given,
574         // try to find attribute which states the theme set to use
575         if ((theme == null) || (theme.equals(""))) {
576             theme = (String) stack.findValue("#attr.theme");
577         }
578 
579         // Default theme set
580         if ((theme == null) || (theme.equals(""))) {
581             theme = defaultUITheme;
582         }
583 
584         return theme;
585     }
586 
587     public void evaluateParams() {
588         addParameter("templateDir", getTemplateDir());
589         addParameter("theme", getTheme());
590 
591         String name = null;
592 
593         if (this.key != null) {
594 
595            if(this.name == null) {
596                 this.name = key;
597             }
598 
599             if(this.label == null) {
600                 this.label = "%{getText('"+ key +"')}";
601             }
602 
603         }
604 
605         if (this.name != null) {
606             name = findString(this.name);
607             addParameter("name", name);
608         }
609 
610         if (label != null) {
611             addParameter("label", findString(label));
612         }
613 
614         if (labelPosition != null) {
615             addParameter("labelposition", findString(labelPosition));
616         }
617 
618         if (requiredposition != null) {
619             addParameter("requiredposition", findString(requiredposition));
620         }
621 
622         if (required != null) {
623             addParameter("required", findValue(required, Boolean.class));
624         }
625 
626         if (disabled != null) {
627             addParameter("disabled", findValue(disabled, Boolean.class));
628         }
629 
630         if (tabindex != null) {
631             addParameter("tabindex", findString(tabindex));
632         }
633 
634         if (onclick != null) {
635             addParameter("onclick", findString(onclick));
636         }
637 
638         if (ondblclick != null) {
639             addParameter("ondblclick", findString(ondblclick));
640         }
641 
642         if (onmousedown != null) {
643             addParameter("onmousedown", findString(onmousedown));
644         }
645 
646         if (onmouseup != null) {
647             addParameter("onmouseup", findString(onmouseup));
648         }
649 
650         if (onmouseover != null) {
651             addParameter("onmouseover", findString(onmouseover));
652         }
653 
654         if (onmousemove != null) {
655             addParameter("onmousemove", findString(onmousemove));
656         }
657 
658         if (onmouseout != null) {
659             addParameter("onmouseout", findString(onmouseout));
660         }
661 
662         if (onfocus != null) {
663             addParameter("onfocus", findString(onfocus));
664         }
665 
666         if (onblur != null) {
667             addParameter("onblur", findString(onblur));
668         }
669 
670         if (onkeypress != null) {
671             addParameter("onkeypress", findString(onkeypress));
672         }
673 
674         if (onkeydown != null) {
675             addParameter("onkeydown", findString(onkeydown));
676         }
677 
678         if (onkeyup != null) {
679             addParameter("onkeyup", findString(onkeyup));
680         }
681 
682         if (onselect != null) {
683             addParameter("onselect", findString(onselect));
684         }
685 
686         if (onchange != null) {
687             addParameter("onchange", findString(onchange));
688         }
689 
690         if (accesskey != null) {
691             addParameter("accesskey", findString(accesskey));
692         }
693 
694         if (cssClass != null) {
695             addParameter("cssClass", findString(cssClass));
696         }
697 
698         if (cssStyle != null) {
699             addParameter("cssStyle", findString(cssStyle));
700         }
701 
702         if (title != null) {
703             addParameter("title", findString(title));
704         }
705 
706 
707         // see if the value was specified as a parameter already
708         if (parameters.containsKey("value")) {
709             parameters.put("nameValue", parameters.get("value"));
710         } else {
711             if (evaluateNameValue()) {
712                 final Class valueClazz = getValueClassType();
713 
714                 if (valueClazz != null) {
715                     if (value != null) {
716                         addParameter("nameValue", findValue(value, valueClazz));
717                     } else if (name != null) {
718                         String expr = name;
719                         if (altSyntax()) {
720                             expr = "%{" + expr + "}";
721                         }
722 
723                         addParameter("nameValue", findValue(expr, valueClazz));
724                     }
725                 } else {
726                     if (value != null) {
727                         addParameter("nameValue", findValue(value));
728                     } else if (name != null) {
729                         addParameter("nameValue", findValue(name));
730                     }
731                 }
732             }
733         }
734 
735         final Form form = (Form) findAncestor(Form.class);
736 
737         // create HTML id element
738         populateComponentHtmlId(form);
739 
740         if (form != null ) {
741             addParameter("form", form.getParameters());
742 
743             if ( name != null ) {
744                 // list should have been created by the form component
745                 List tags = (List) form.getParameters().get("tagNames");
746                 tags.add(name);
747             }
748         }
749 
750 
751 
752 
753 
754         // tooltip & tooltipConfig
755         if (tooltipConfig != null) {
756             addParameter("tooltipConfig", findValue(tooltipConfig));
757         }
758         if (tooltip != null) {
759             addParameter("tooltip", findString(tooltip));
760 
761             Map tooltipConfigMap = getTooltipConfig(this);
762 
763             if (form != null) { // inform the containing form that we need tooltip javascript included
764                 form.addParameter("hasTooltip", Boolean.TRUE);
765 
766                 // tooltipConfig defined in component itseilf will take precedence
767                 // over those defined in the containing form
768                 Map overallTooltipConfigMap = getTooltipConfig(form);
769                 overallTooltipConfigMap.putAll(tooltipConfigMap); // override parent form's tooltip config
770 
771                 for (Iterator i = overallTooltipConfigMap.entrySet().iterator(); i.hasNext(); ) {
772                     Map.Entry entry = (Map.Entry) i.next();
773                     addParameter((String) entry.getKey(), entry.getValue());
774                 }
775             }
776             else {
777                 LOG.warn("No ancestor Form found, javascript based tooltip will not work, however standard HTML tooltip using alt and title attribute will still work ");
778             }
779         }
780         evaluateExtraParams();
781 
782     }
783 
784     protected String escape(String name) {
785         // escape any possible values that can make the ID painful to work with in JavaScript
786         if (name != null) {
787             return name.replaceAll("[//.//[//]]", "_");
788         } else {
789             return "";
790         }
791     }
792 
793     /***
794      * Ensures an unescaped attribute value cannot be vulnerable to XSS attacks
795      *
796      * @param val The value to check
797      * @return The escaped value
798      */
799     protected String ensureAttributeSafelyNotEscaped(String val) {
800         if (val != null) {
801             return val.replaceAll("\"", "&#34;");
802         } else {
803             return "";
804         }
805     }
806 
807     protected void evaluateExtraParams() {
808     }
809 
810     protected boolean evaluateNameValue() {
811         return true;
812     }
813 
814     protected Class getValueClassType() {
815         return String.class;
816     }
817 
818     public void addFormParameter(String key, Object value) {
819         Form form = (Form) findAncestor(Form.class);
820         if (form != null) {
821             form.addParameter(key, value);
822         }
823     }
824 
825     protected void enableAncestorFormCustomOnsubmit() {
826         Form form = (Form) findAncestor(Form.class);
827         if (form != null) {
828             form.addParameter("customOnsubmitEnabled", Boolean.TRUE);
829         } else {
830             LOG.warn("Cannot find an Ancestor form, custom onsubmit is NOT enabled");
831         }
832     }
833 
834     protected Map getTooltipConfig(UIBean component) {
835         Object tooltipConfigObj = component.getParameters().get("tooltipConfig");
836         Map tooltipConfig = new LinkedHashMap();
837 
838         if (tooltipConfigObj instanceof Map) {
839             // we get this if its configured using
840             // 1] UI component's tooltipConfig attribute  OR
841             // 2] <param name="tooltip" value="" /> param tag value attribute
842 
843             tooltipConfig = new LinkedHashMap((Map)tooltipConfigObj);
844         } else if (tooltipConfigObj instanceof String) {
845 
846             // we get this if its configured using
847             // <param name="tooltipConfig"> ... </param> tag's body
848             String tooltipConfigStr = (String) tooltipConfigObj;
849             String[] tooltipConfigArray = tooltipConfigStr.split("//|");
850 
851             for (int a=0; a<tooltipConfigArray.length; a++) {
852                 String[] configEntry = ((String)tooltipConfigArray[a].trim()).split("=");
853                 String key = configEntry[0].trim();
854                 String value = null;
855                 if (configEntry.length > 1) {
856                     value = configEntry[1].trim();
857                     tooltipConfig.put(key, value.toString());
858                 }
859                 else {
860                     LOG.warn("component "+component+" tooltip config param "+key+" has no value defined, skipped");
861                 }
862             }
863         }
864         return tooltipConfig;
865     }
866 
867     /***
868      * Create HTML id element for the component and populate this component parmaeter
869      * map. Additionally, a parameter named escapedId is populated which contains the found id value filtered by
870      * {@link #escape(String)}, needed eg. for naming Javascript identifiers based on the id value.
871      *
872      * The order is as follows :-
873      * <ol>
874      *   <li>This component id attribute</li>
875      *   <li>[containing_form_id]_[this_component_name]</li>
876      *   <li>[this_component_name]</li>
877      * </ol>
878      *
879      * @param form
880      */
881     protected void populateComponentHtmlId(Form form) {
882         String tryId;
883         if (id != null) {
884             // this check is needed for backwards compatibility with 2.1.x
885             if (altSyntax()) {
886                 tryId = findString(id);
887             } else {
888                 tryId = id;
889             }
890         } else if (form != null) {
891             tryId = form.getParameters().get("id") + "_"
892                     + escape(name != null ? findString(name) : null);
893         } else {
894             tryId = escape(name != null ? findString(name) : null);
895         }
896         addParameter("id", tryId);
897         addParameter("escapedId", escape(tryId));
898     }
899 
900     @StrutsTagAttribute(description="The template directory.")
901     public void setTemplateDir(String templateDir) {
902         this.templateDir = templateDir;
903     }
904 
905     @StrutsTagAttribute(description="The theme (other than default) to use for rendering the element")
906     public void setTheme(String theme) {
907         this.theme = theme;
908     }
909 
910     public String getTemplate() {
911         return template;
912     }
913 
914     @StrutsTagAttribute(description="The template (other than default) to use for rendering the element")
915     public void setTemplate(String template) {
916         this.template = template;
917     }
918 
919     @StrutsTagAttribute(description="The css class to use for element")
920     public void setCssClass(String cssClass) {
921         this.cssClass = cssClass;
922     }
923 
924     @StrutsTagAttribute(description="The css style definitions for element to use")
925     public void setCssStyle(String cssStyle) {
926         this.cssStyle = cssStyle;
927     }
928 
929     @StrutsTagAttribute(description="Set the html title attribute on rendered html element")
930     public void setTitle(String title) {
931         this.title = title;
932     }
933 
934     @StrutsTagAttribute(description="Set the html disabled attribute on rendered html element")
935     public void setDisabled(String disabled) {
936         this.disabled = disabled;
937     }
938 
939     @StrutsTagAttribute(description="Label expression used for rendering a element specific label")
940     public void setLabel(String label) {
941         this.label = label;
942     }
943 
944     @StrutsTagAttribute(description="Define label position of form element (top/left)")
945     public void setLabelposition(String labelPosition) {
946         this.labelPosition = labelPosition;
947     }
948 
949     @StrutsTagAttribute(description="Define required position of required form element (left|right)")
950     public void setRequiredposition(String requiredposition) {
951         this.requiredposition = requiredposition;
952     }
953 
954     @StrutsTagAttribute(description="The name to set for element")
955     public void setName(String name) {
956         this.name = name;
957     }
958 
959     @StrutsTagAttribute(description="If set to true, the rendered element will indicate that input is required", type="Boolean", defaultValue="false")
960     public void setRequired(String required) {
961         this.required = required;
962     }
963 
964     @StrutsTagAttribute(description="Set the html tabindex attribute on rendered html element")
965     public void setTabindex(String tabindex) {
966         this.tabindex = tabindex;
967     }
968 
969     @StrutsTagAttribute(description="Preset the value of input element.")
970     public void setValue(String value) {
971         this.value = value;
972     }
973 
974     @StrutsTagAttribute(description="Set the html onclick attribute on rendered html element")
975     public void setOnclick(String onclick) {
976         this.onclick = onclick;
977     }
978 
979     @StrutsTagAttribute(description="Set the html ondblclick attribute on rendered html element")
980     public void setOndblclick(String ondblclick) {
981         this.ondblclick = ondblclick;
982     }
983 
984     @StrutsTagAttribute(description="Set the html onmousedown attribute on rendered html element")
985     public void setOnmousedown(String onmousedown) {
986         this.onmousedown = onmousedown;
987     }
988 
989     @StrutsTagAttribute(description="Set the html onmouseup attribute on rendered html element")
990     public void setOnmouseup(String onmouseup) {
991         this.onmouseup = onmouseup;
992     }
993 
994     @StrutsTagAttribute(description="Set the html onmouseover attribute on rendered html element")
995     public void setOnmouseover(String onmouseover) {
996         this.onmouseover = onmouseover;
997     }
998 
999     @StrutsTagAttribute(description="Set the html onmousemove attribute on rendered html element")
1000     public void setOnmousemove(String onmousemove) {
1001         this.onmousemove = onmousemove;
1002     }
1003 
1004     @StrutsTagAttribute(description="Set the html onmouseout attribute on rendered html element")
1005     public void setOnmouseout(String onmouseout) {
1006         this.onmouseout = onmouseout;
1007     }
1008 
1009     @StrutsTagAttribute(description="Set the html onfocus attribute on rendered html element")
1010     public void setOnfocus(String onfocus) {
1011         this.onfocus = onfocus;
1012     }
1013 
1014     @StrutsTagAttribute(description=" Set the html onblur attribute on rendered html element")
1015     public void setOnblur(String onblur) {
1016         this.onblur = onblur;
1017     }
1018 
1019     @StrutsTagAttribute(description="Set the html onkeypress attribute on rendered html element")
1020     public void setOnkeypress(String onkeypress) {
1021         this.onkeypress = onkeypress;
1022     }
1023 
1024     @StrutsTagAttribute(description="Set the html onkeydown attribute on rendered html element")
1025     public void setOnkeydown(String onkeydown) {
1026         this.onkeydown = onkeydown;
1027     }
1028 
1029     @StrutsTagAttribute(description="Set the html onkeyup attribute on rendered html element")
1030     public void setOnkeyup(String onkeyup) {
1031         this.onkeyup = onkeyup;
1032     }
1033 
1034     @StrutsTagAttribute(description="Set the html onselect attribute on rendered html element")
1035     public void setOnselect(String onselect) {
1036         this.onselect = onselect;
1037     }
1038 
1039     @StrutsTagAttribute(description="Set the html onchange attribute on rendered html element")
1040     public void setOnchange(String onchange) {
1041         this.onchange = onchange;
1042     }
1043 
1044     @StrutsTagAttribute(description="Set the html accesskey attribute on rendered html element")
1045     public void setAccesskey(String accesskey) {
1046         this.accesskey = accesskey;
1047     }
1048 
1049     @StrutsTagAttribute(description="Set the tooltip of this particular component")
1050     public void setTooltip(String tooltip) {
1051         this.tooltip = tooltip;
1052     }
1053 
1054     @StrutsTagAttribute(description="Set the tooltip configuration")
1055     public void setTooltipConfig(String tooltipConfig) {
1056         this.tooltipConfig = tooltipConfig;
1057     }
1058 
1059     @StrutsTagAttribute(description="Set the key (name, value, label) for this particular component")
1060     public void setKey(String key) {
1061         this.key = key;
1062     }
1063 }