View Javadoc

    1   /*
    2    * $Id: UIBean.java 498091 2007-01-20 08:44:14Z mrdon $
    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     protected void evaluateExtraParams() {
    794     }
    795
    796     protected boolean evaluateNameValue() {
    797         return true;
    798     }
    799
    800     protected Class getValueClassType() {
    801         return String.class;
    802     }
    803
    804     public void addFormParameter(String key, Object value) {
    805         Form form = (Form) findAncestor(Form.class);
    806         if (form != null) {
    807             form.addParameter(key, value);
    808         }
    809     }
    810
    811     protected void enableAncestorFormCustomOnsubmit() {
    812         Form form = (Form) findAncestor(Form.class);
    813         if (form != null) {
    814             form.addParameter("customOnsubmitEnabled", Boolean.TRUE);
    815         } else {
    816             LOG.warn("Cannot find an Ancestor form, custom onsubmit is NOT enabled");
    817         }
    818     }
    819
    820     protected Map getTooltipConfig(UIBean component) {
    821         Object tooltipConfigObj = component.getParameters().get("tooltipConfig");
    822         Map tooltipConfig = new LinkedHashMap();
    823
    824         if (tooltipConfigObj instanceof Map) {
    825             // we get this if its configured using
    826             // 1] UI component's tooltipConfig attribute  OR
    827             // 2] <param name="tooltip" value="" /> param tag value attribute
    828
    829             tooltipConfig = new LinkedHashMap((Map)tooltipConfigObj);
    830         } else if (tooltipConfigObj instanceof String) {
    831
    832             // we get this if its configured using
    833             // <param name="tooltipConfig"> ... </param> tag's body
    834             String tooltipConfigStr = (String) tooltipConfigObj;
    835             String[] tooltipConfigArray = tooltipConfigStr.split("//|");
    836
    837             for (int a=0; a<tooltipConfigArray.length; a++) {
    838                 String[] configEntry = ((String)tooltipConfigArray[a].trim()).split("=");
    839                 String key = configEntry[0].trim();
    840                 String value = null;
    841                 if (configEntry.length > 1) {
    842                     value = configEntry[1].trim();
    843                     tooltipConfig.put(key, value.toString());
    844                 }
    845                 else {
    846                     LOG.warn("component "+component+" tooltip config param "+key+" has no value defined, skipped");
    847                 }
    848             }
    849         }
    850         return tooltipConfig;
    851     }
    852
    853     /***
    854      * Create HTML id element for the component and populate this component parmaeter
    855      * map.
    856      *
    857      * The order is as follows :-
    858      * <ol>
    859      *   <li>This component id attribute</li>
    860      *   <li>[containing_form_id]_[this_component_name]</li>
    861      *   <li>[this_component_name]</li>
    862      * </ol>
    863      *
    864      * @param form
    865      */
    866     protected void populateComponentHtmlId(Form form) {
    867         if (id != null) {
    868             // this check is needed for backwards compatibility with 2.1.x
    869             if (altSyntax()) {
    870                 addParameter("id", findString(id));
    871             } else {
    872                 addParameter("id", id);
    873             }
    874         } else if (form != null) {
    875             addParameter("id", form.getParameters().get("id") + "_"
    876                     + escape(name != null ? findString(name) : null));
    877         } else {
    878             addParameter("id", escape(name != null ? findString(name) : null));
    879         }
    880     }
    881
    882     @StrutsTagAttribute(description="The template directory.")
    883     public void setTemplateDir(String templateDir) {
    884         this.templateDir = templateDir;
    885     }
    886
    887     @StrutsTagAttribute(description="The theme (other than default) to use for rendering the element")
    888     public void setTheme(String theme) {
    889         this.theme = theme;
    890     }
    891
    892     public String getTemplate() {
    893         return template;
    894     }
    895
    896     @StrutsTagAttribute(description="The template (other than default) to use for rendering the element")
    897     public void setTemplate(String template) {
    898         this.template = template;
    899     }
    900
    901     @StrutsTagAttribute(description="The css class to use for element")
    902     public void setCssClass(String cssClass) {
    903         this.cssClass = cssClass;
    904     }
    905
    906     @StrutsTagAttribute(description="The css style definitions for element ro use")
    907     public void setCssStyle(String cssStyle) {
    908         this.cssStyle = cssStyle;
    909     }
    910
    911     @StrutsTagAttribute(description="Set the html title attribute on rendered html element")
    912     public void setTitle(String title) {
    913         this.title = title;
    914     }
    915
    916     @StrutsTagAttribute(description="Set the html disabled attribute on rendered html element")
    917     public void setDisabled(String disabled) {
    918         this.disabled = disabled;
    919     }
    920
    921     @StrutsTagAttribute(description="Label expression used for rendering a element specific label")
    922     public void setLabel(String label) {
    923         this.label = label;
    924     }
    925
    926     @StrutsTagAttribute(description="Define label position of form element (top/left)")
    927     public void setLabelposition(String labelPosition) {
    928         this.labelPosition = labelPosition;
    929     }
    930
    931     @StrutsTagAttribute(description="Define required position of required form element (left|right)")
    932     public void setRequiredposition(String requiredposition) {
    933         this.requiredposition = requiredposition;
    934     }
    935
    936     @StrutsTagAttribute(description="The name to set for element")
    937     public void setName(String name) {
    938         this.name = name;
    939     }
    940
    941     @StrutsTagAttribute(description="If set to true, the rendered element will indicate that input is required", type="Boolean", defaultValue="false")
    942     public void setRequired(String required) {
    943         this.required = required;
    944     }
    945
    946     @StrutsTagAttribute(description="Set the html tabindex attribute on rendered html element")
    947     public void setTabindex(String tabindex) {
    948         this.tabindex = tabindex;
    949     }
    950
    951     @StrutsTagAttribute(description="Preset the value of input element.")
    952     public void setValue(String value) {
    953         this.value = value;
    954     }
    955
    956     @StrutsTagAttribute(description="Set the html onclick attribute on rendered html element")
    957     public void setOnclick(String onclick) {
    958         this.onclick = onclick;
    959     }
    960
    961     @StrutsTagAttribute(description="Set the html ondblclick attribute on rendered html element")
    962     public void setOndblclick(String ondblclick) {
    963         this.ondblclick = ondblclick;
    964     }
    965
    966     @StrutsTagAttribute(description="Set the html onmousedown attribute on rendered html element")
    967     public void setOnmousedown(String onmousedown) {
    968         this.onmousedown = onmousedown;
    969     }
    970
    971     @StrutsTagAttribute(description="Set the html onmouseup attribute on rendered html element")
    972     public void setOnmouseup(String onmouseup) {
    973         this.onmouseup = onmouseup;
    974     }
    975
    976     @StrutsTagAttribute(description="Set the html onmouseover attribute on rendered html element")
    977     public void setOnmouseover(String onmouseover) {
    978         this.onmouseover = onmouseover;
    979     }
    980
    981     @StrutsTagAttribute(description="Set the html onmousemove attribute on rendered html element")
    982     public void setOnmousemove(String onmousemove) {
    983         this.onmousemove = onmousemove;
    984     }
    985
    986     @StrutsTagAttribute(description="Set the html onmouseout attribute on rendered html element")
    987     public void setOnmouseout(String onmouseout) {
    988         this.onmouseout = onmouseout;
    989     }
    990
    991     @StrutsTagAttribute(description="Set the html onfocus attribute on rendered html element")
    992     public void setOnfocus(String onfocus) {
    993         this.onfocus = onfocus;
    994     }
    995
    996     @StrutsTagAttribute(description=" Set the html onblur attribute on rendered html element")
    997     public void setOnblur(String onblur) {
    998         this.onblur = onblur;
    999     }
    1000
    1001     @StrutsTagAttribute(description="Set the html onkeypress attribute on rendered html element")
    1002     public void setOnkeypress(String onkeypress) {
    1003         this.onkeypress = onkeypress;
    1004     }
    1005
    1006     @StrutsTagAttribute(description="Set the html onkeydown attribute on rendered html element")
    1007     public void setOnkeydown(String onkeydown) {
    1008         this.onkeydown = onkeydown;
    1009     }
    1010
    1011     @StrutsTagAttribute(description="Set the html onkeyup attribute on rendered html element")
    1012     public void setOnkeyup(String onkeyup) {
    1013         this.onkeyup = onkeyup;
    1014     }
    1015
    1016     @StrutsTagAttribute(description="Set the html onselect attribute on rendered html element")
    1017     public void setOnselect(String onselect) {
    1018         this.onselect = onselect;
    1019     }
    1020
    1021     @StrutsTagAttribute(description="Set the html onchange attribute on rendered html element")
    1022     public void setOnchange(String onchange) {
    1023         this.onchange = onchange;
    1024     }
    1025
    1026     @StrutsTagAttribute(description="Set the html accesskey attribute on rendered html element")
    1027     public void setAccesskey(String accesskey) {
    1028         this.accesskey = accesskey;
    1029     }
    1030
    1031     @StrutsTagAttribute(description="Set the tooltip of this particular component")
    1032     public void setTooltip(String tooltip) {
    1033         this.tooltip = tooltip;
    1034     }
    1035
    1036     @StrutsTagAttribute(description="Set the tooltip configuration")
    1037     public void setTooltipConfig(String tooltipConfig) {
    1038         this.tooltipConfig = tooltipConfig;
    1039     }
    1040
    1041     @StrutsTagAttribute(description="Set the key (name, value, label) for this particular component")
    1042     public void setKey(String key) {
    1043         this.key = key;
    1044     }
    1045 }