View Javadoc

    1   /*
    2    * $Id: SelectTag.java 471754 2006-11-06 14:55:09Z husted $
    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.struts.taglib.html;
    22
    23  import org.apache.commons.beanutils.BeanUtils;
    24  import org.apache.struts.taglib.TagUtils;
    25  import org.apache.struts.util.MessageResources;
    26
    27  import javax.servlet.jsp.JspException;
    28
    29  import java.lang.reflect.InvocationTargetException;
    30
    31  /**
    32   * Custom tag that represents an HTML select element, associated with a bean
    33   * property specified by our attributes.  This tag must be nested inside a
    34   * form tag.
    35   *
    36   * @version $Rev: 471754 $ $Date: 2004-10-16 12:38:42 -0400 (Sat, 16 Oct 2004)
    37   *          $
    38   */
    39  public class SelectTag extends BaseHandlerTag {
    40      /**
    41       * The message resources for this package.
    42       */
    43      protected static MessageResources messages =
    44          MessageResources.getMessageResources(Constants.Package
    45              + ".LocalStrings");
    46
    47      // ----------------------------------------------------- Instance Variables
    48
    49      /**
    50       * The actual values we will match against, calculated in doStartTag().
    51       */
    52      protected String[] match = null;
    53
    54      /**
    55       * Should multiple selections be allowed.  Any non-null value will trigger
    56       * rendering this.
    57       */
    58      protected String multiple = null;
    59
    60      /**
    61       * The name of the bean containing our underlying property.
    62       */
    63      protected String name = Constants.BEAN_KEY;
    64
    65      /**
    66       * The property name we are associated with.
    67       */
    68      protected String property = null;
    69
    70      /**
    71       * The saved body content of this tag.
    72       */
    73      protected String saveBody = null;
    74
    75      /**
    76       * How many available options should be displayed when this element is
    77       * rendered?
    78       */
    79      protected String size = null;
    80
    81      /**
    82       * The value to compare with for marking an option selected.
    83       */
    84      protected String value = null;
    85
    86      public String getMultiple() {
    87          return (this.multiple);
    88      }
    89
    90      public void setMultiple(String multiple) {
    91          this.multiple = multiple;
    92      }
    93
    94      public String getName() {
    95          return (this.name);
    96      }
    97
    98      public void setName(String name) {
    99          this.name = name;
    100     }
    101
    102     public String getSize() {
    103         return (this.size);
    104     }
    105
    106     public void setSize(String size) {
    107         this.size = size;
    108     }
    109
    110     // ------------------------------------------------------------- Properties
    111
    112     /**
    113      * Does the specified value match one of those we are looking for?
    114      *
    115      * @param value Value to be compared.
    116      */
    117     public boolean isMatched(String value) {
    118         if ((this.match == null) || (value == null)) {
    119             return false;
    120         }
    121
    122         for (int i = 0; i < this.match.length; i++) {
    123             if (value.equals(this.match[i])) {
    124                 return true;
    125             }
    126         }
    127
    128         return false;
    129     }
    130
    131     /**
    132      * Return the property name.
    133      */
    134     public String getProperty() {
    135         return (this.property);
    136     }
    137
    138     /**
    139      * Set the property name.
    140      *
    141      * @param property The new property name
    142      */
    143     public void setProperty(String property) {
    144         this.property = property;
    145     }
    146
    147     /**
    148      * Return the comparison value.
    149      */
    150     public String getValue() {
    151         return (this.value);
    152     }
    153
    154     /**
    155      * Set the comparison value.
    156      *
    157      * @param value The new comparison value
    158      */
    159     public void setValue(String value) {
    160         this.value = value;
    161     }
    162
    163     // --------------------------------------------------------- Public Methods
    164
    165     /**
    166      * Render the beginning of this select tag. <p> Support for indexed
    167      * property since Struts 1.1
    168      *
    169      * @throws JspException if a JSP exception has occurred
    170      */
    171     public int doStartTag() throws JspException {
    172         TagUtils.getInstance().write(pageContext, renderSelectStartElement());
    173
    174         // Store this tag itself as a page attribute
    175         pageContext.setAttribute(Constants.SELECT_KEY, this);
    176
    177         this.calculateMatchValues();
    178
    179         return (EVAL_BODY_TAG);
    180     }
    181
    182     /**
    183      * Create an appropriate select start element based on our parameters.
    184      *
    185      * @throws JspException
    186      * @since Struts 1.1
    187      */
    188     protected String renderSelectStartElement()
    189         throws JspException {
    190         StringBuffer results = new StringBuffer("<select");
    191
    192         prepareAttribute(results, "name", prepareName());
    193         prepareAttribute(results, "accesskey", getAccesskey());
    194
    195         if (multiple != null) {
    196             results.append(" multiple=\"multiple\"");
    197         }
    198
    199         prepareAttribute(results, "size", getSize());
    200         prepareAttribute(results, "tabindex", getTabindex());
    201         results.append(prepareEventHandlers());
    202         results.append(prepareStyles());
    203         prepareOtherAttributes(results);
    204         results.append(">");
    205
    206         return results.toString();
    207     }
    208
    209     /**
    210      * Calculate the match values we will actually be using.
    211      *
    212      * @throws JspException
    213      */
    214     private void calculateMatchValues()
    215         throws JspException {
    216         if (this.value != null) {
    217             this.match = new String[1];
    218             this.match[0] = this.value;
    219         } else {
    220             Object bean =
    221                 TagUtils.getInstance().lookup(pageContext, name, null);
    222
    223             if (bean == null) {
    224                 JspException e =
    225                     new JspException(messages.getMessage("getter.bean", name));
    226
    227                 TagUtils.getInstance().saveException(pageContext, e);
    228                 throw e;
    229             }
    230
    231             try {
    232                 this.match = BeanUtils.getArrayProperty(bean, property);
    233
    234                 if (this.match == null) {
    235                     this.match = new String[0];
    236                 }
    237             } catch (IllegalAccessException e) {
    238                 TagUtils.getInstance().saveException(pageContext, e);
    239                 throw new JspException(messages.getMessage("getter.access",
    240                         property, name));
    241             } catch (InvocationTargetException e) {
    242                 Throwable t = e.getTargetException();
    243
    244                 TagUtils.getInstance().saveException(pageContext, t);
    245                 throw new JspException(messages.getMessage("getter.result",
    246                         property, t.toString()));
    247             } catch (NoSuchMethodException e) {
    248                 TagUtils.getInstance().saveException(pageContext, e);
    249                 throw new JspException(messages.getMessage("getter.method",
    250                         property, name));
    251             }
    252         }
    253     }
    254
    255     /**
    256      * Save any body content of this tag, which will generally be the
    257      * option(s) representing the values displayed to the user.
    258      *
    259      * @throws JspException if a JSP exception has occurred
    260      */
    261     public int doAfterBody() throws JspException {
    262         if (bodyContent != null) {
    263             String value = bodyContent.getString();
    264
    265             if (value == null) {
    266                 value = "";
    267             }
    268
    269             this.saveBody = value.trim();
    270         }
    271
    272         return (SKIP_BODY);
    273     }
    274
    275     /**
    276      * Render the end of this form.
    277      *
    278      * @throws JspException if a JSP exception has occurred
    279      */
    280     public int doEndTag() throws JspException {
    281         // Remove the page scope attributes we created
    282         pageContext.removeAttribute(Constants.SELECT_KEY);
    283
    284         // Render a tag representing the end of our current form
    285         StringBuffer results = new StringBuffer();
    286
    287         if (saveBody != null) {
    288             results.append(saveBody);
    289             saveBody = null;
    290         }
    291
    292         results.append("</select>");
    293
    294         TagUtils.getInstance().write(pageContext, results.toString());
    295
    296         return (EVAL_PAGE);
    297     }
    298
    299     /**
    300      * Prepare the name element
    301      *
    302      * @return The element name.
    303      */
    304     protected String prepareName()
    305         throws JspException {
    306         if (property == null) {
    307             return null;
    308         }
    309
    310         // * @since Struts 1.1
    311         if (indexed) {
    312             StringBuffer results = new StringBuffer();
    313
    314             prepareIndex(results, name);
    315             results.append(property);
    316
    317             return results.toString();
    318         }
    319
    320         return property;
    321     }
    322
    323     /**
    324      * Release any acquired resources.
    325      */
    326     public void release() {
    327         super.release();
    328         match = null;
    329         multiple = null;
    330         name = Constants.BEAN_KEY;
    331         property = null;
    332         saveBody = null;
    333         size = null;
    334         value = null;
    335     }
    336 }