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 }