View Javadoc

    1   /*
    2    * $Id: BeanValidatorForm.java 472728 2006-11-09 01:10:58Z niallp $
    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.validator;
    22
    23  import org.apache.commons.beanutils.ConvertUtils;
    24  import org.apache.commons.beanutils.DynaBean;
    25  import org.apache.commons.beanutils.DynaClass;
    26  import org.apache.commons.beanutils.WrapDynaBean;
    27  import org.apache.commons.logging.Log;
    28  import org.apache.commons.logging.LogFactory;
    29  import org.apache.struts.action.ActionMapping;
    30  import org.apache.struts.config.FormBeanConfig;
    31
    32  import javax.servlet.http.HttpServletRequest;
    33
    34  import java.io.Serializable;
    35
    36  import java.lang.reflect.Array;
    37
    38  import java.util.List;
    39  import java.util.Map;
    40
    41  /**
    42   * <p>Struts <i>validator</i> <code>ActionForm</code> backed by either a
    43   * <code>DynaBean</code> or POJO JavaBean.</p>
    44   *
    45   * <p>Passing a POJO JavaBean to the constructor will automatically create an
    46   * associated <code>WrapDynaBean</code>. One use for this would be to migrate
    47   * <i>view</i> objects from an existing system which, for the usual reasons,
    48   * can't be changed to extend <ActionForm</code>.</p>
    49   *
    50   * <p>This form is based on the standard struts <code>ValidatorForm</code> for
    51   * use with the <i>Validator</i> framework and validates either using the
    52   * <i>name</i> from the Struts <code>ActionMapping</code> or the
    53   * <code>ActionMapping</code>'s path depending on whether
    54   * <code>pathValidation</code> is <code>true</code> or
    55   * <code>false</code>.</p>
    56   *
    57   * <p><b>Note</b>: WrapDynaBean is NOT serializable.  If you use this class
    58   * with a WrapDynaBean (as described above), you should not store your form in
    59   * session scope.</p>
    60   */
    61  public class BeanValidatorForm extends ValidatorForm implements DynaBean,
    62      Serializable {
    63      /**
    64       * Commons Logging
    65       */
    66      protected static Log logger = LogFactory.getLog(BeanValidatorForm.class);
    67
    68      /**
    69       * The <code>DynaBean</code> that this ActionForm is backed by.
    70       */
    71      protected DynaBean dynaBean;
    72
    73      /**
    74       * Indicates whether the ActionMapping's path should be used for the
    75       * validation key.
    76       */
    77      protected boolean pathValidation = false;
    78
    79      /**
    80       * The name used to identify the ActionForm in the struts-config.xml
    81       */
    82      private String strutsConfigFormName;
    83
    84      // ------------------- Constructor ----------------------------------
    85
    86      /**
    87       * Construct a new <code>BeanValidatorForm</code> with the specified
    88       * bean.
    89       */
    90      public BeanValidatorForm(Object bean) {
    91          if (bean instanceof DynaBean) {
    92              dynaBean = (DynaBean) bean;
    93          } else {
    94              dynaBean = new WrapDynaBean(bean);
    95          }
    96      }
    97
    98      // ------------------- Protected Methods ----------------------------------
    99
    100     /**
    101      * <p>Set whether this form should validate based on the
    102      * <code>ActionMapping</code>'s path.</p>
    103      */
    104     protected void setPathValidation(boolean pathValidation) {
    105         this.pathValidation = pathValidation;
    106     }
    107
    108     /**
    109      * <p>Indicates whether this form should validate based on the
    110      * <code>ActionMapping</code>'s path.</p>
    111      */
    112     protected boolean isPathValidation() {
    113         return pathValidation;
    114     }
    115
    116     // ------------------- Public Methods ----------------------------------
    117
    118     /**
    119      * <p>Perform intialization of the ActionForm.</p>
    120      * <p>This method is called when the form is created.</p>
    121      *
    122      * @since Struts 1.3.6
    123      */
    124     public void initialize(FormBeanConfig formBeanConfig) {
    125         strutsConfigFormName = formBeanConfig.getName();
    126     }
    127
    128     /**
    129      * Return name used to identify the ActionForm in the
    130      * struts-config.xml.
    131      *
    132      * @since Struts 1.3.6
    133      */
    134     public String getStrutsConfigFormName() {
    135         return strutsConfigFormName;
    136     }
    137
    138     /**
    139      * <p>Return the <code>DynaBean</code> that this <code>ActionForm</code>
    140      * is backed by.</p>
    141      */
    142     public DynaBean getDynaBean() {
    143         return dynaBean;
    144     }
    145
    146     /**
    147      * <p>Return the <code>Bean</code> that this <code>ActionForm</code> is
    148      * backed by.</p>
    149      *
    150      * <p>If the <code>DynaBean</code> is a <code>WrapDynaBean</code> type
    151      * then this method returns the 'Wrapped' POJO bean associated with it. If
    152      * you require the actual <code>WrapDynaBean</code> then use the
    153      * <code>getDynaBean()</code> method.</p>
    154      */
    155     public Object getInstance() {
    156         if (dynaBean instanceof WrapDynaBean) {
    157             return ((WrapDynaBean) dynaBean).getInstance();
    158         }
    159
    160         return dynaBean;
    161     }
    162
    163     /**
    164      * <p>Return the size of an indexed or mapped property.</p>
    165      */
    166     public int size(String name) {
    167         Object value = dynaBean.get(name);
    168
    169         if (value == null) {
    170             return 0;
    171         }
    172
    173         if (value instanceof Map) {
    174             return ((Map) value).size();
    175         }
    176
    177         if (value instanceof List) {
    178             return ((List) value).size();
    179         }
    180
    181         if ((value.getClass().isArray())) {
    182             return Array.getLength(value);
    183         }
    184
    185         return 0;
    186     }
    187
    188     // ------------------- ValidatorForm Methods ----------------------------------
    189
    190     /**
    191      * Returns the Validation key
    192      *
    193      * @param mapping The mapping used to select this instance
    194      * @param request The servlet request we are processing
    195      * @return validation key to use
    196      */
    197     public String getValidationKey(ActionMapping mapping,
    198         HttpServletRequest request) {
    199         String validationKey = null;
    200
    201         if (isPathValidation()) {
    202             // Get the path replacing any slashes by underscore
    203             validationKey = mapping.getPath();
    204
    205             // Remove any leading slash
    206             if (validationKey.charAt(0) == '/') {
    207                 validationKey = validationKey.substring(1);
    208             }
    209
    210             // Replace any slashes by underscore
    211             if (validationKey.indexOf("/") > 0) {
    212                 validationKey = validationKey.replace('/', '_');
    213             }
    214         } else {
    215             validationKey = mapping.getAttribute();
    216         }
    217
    218         if (logger.isDebugEnabled()) {
    219             logger.debug("Validating ActionForm '" + mapping.getName()
    220                 + "' using key '" + validationKey + "' for mapping '"
    221                 + mapping.getPath() + "'");
    222         }
    223
    224         return validationKey;
    225     }
    226
    227     // ------------------- DynaBean Methods ----------------------------------
    228
    229     /**
    230      * Return the <code>DynaClass</code> instance that describes the set of
    231      * properties available for this DynaBean.
    232      */
    233     public DynaClass getDynaClass() {
    234         return dynaBean.getDynaClass();
    235     }
    236
    237     /**
    238      * Return the value of a simple property with the specified name.
    239      *
    240      * @param name Name of the property whose value is to be retrieved
    241      */
    242     public Object get(String name) {
    243         return dynaBean.get(name);
    244     }
    245
    246     /**
    247      * Return the value of an indexed property with the specified name.
    248      *
    249      * @param name  Name of the property whose value is to be retrieved
    250      * @param index Index of the value to be retrieved
    251      */
    252     public Object get(String name, int index) {
    253         return dynaBean.get(name, index);
    254     }
    255
    256     /**
    257      * Return the value of a mapped property with the specified name, or
    258      * <code>null</code> if there is no value for the specified key.
    259      *
    260      * @param name Name of the property whose value is to be retrieved
    261      * @param key  Key of the value to be retrieved
    262      */
    263     public Object get(String name, String key) {
    264         return dynaBean.get(name, key);
    265     }
    266
    267     /**
    268      * Set the value of a simple property with the specified name.
    269      *
    270      * @param name  Name of the property whose value is to be set
    271      * @param value Value to which this property is to be set
    272      */
    273     public void set(String name, Object value) {
    274         // Set the page number (for validator)
    275         if ("page".equals(name)) {
    276             if (value == null) {
    277                 page = 0;
    278             } else if (value instanceof Integer) {
    279                 page = ((Integer) value).intValue();
    280             } else {
    281                 try {
    282                     page =
    283                         ((Integer) ConvertUtils.convert(value.toString(),
    284                             Integer.class)).intValue();
    285                 } catch (Exception ignore) {
    286                     page = 0;
    287                 }
    288             }
    289         }
    290
    291         dynaBean.set(name, value);
    292     }
    293
    294     /**
    295      * Set the value of an indexed property with the specified name.
    296      *
    297      * @param name  Name of the property whose value is to be set
    298      * @param index Index of the property to be set
    299      * @param value Value to which this property is to be set
    300      */
    301     public void set(String name, int index, Object value) {
    302         dynaBean.set(name, index, value);
    303     }
    304
    305     /**
    306      * Set the value of a mapped property with the specified name.
    307      *
    308      * @param name  Name of the property whose value is to be set
    309      * @param key   Key of the property to be set
    310      * @param value Value to which this property is to be set
    311      */
    312     public void set(String name, String key, Object value) {
    313         dynaBean.set(name, key, value);
    314     }
    315
    316     /**
    317      * Does the specified mapped property contain a value for the specified
    318      * key value?
    319      *
    320      * @param name Name of the property to check
    321      * @param key  Name of the key to check
    322      */
    323     public boolean contains(String name, String key) {
    324         return dynaBean.contains(name, key);
    325     }
    326
    327     /**
    328      * Remove any existing value for the specified key on the specified mapped
    329      * property.
    330      *
    331      * @param name Name of the property for which a value is to be removed
    332      * @param key  Key of the value to be removed
    333      */
    334     public void remove(String name, String key) {
    335         dynaBean.remove(name, key);
    336     }
    337 }