1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
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
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
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
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
203 validationKey = mapping.getPath();
204
205
206 if (validationKey.charAt(0) == '/') {
207 validationKey = validationKey.substring(1);
208 }
209
210
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
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
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 }