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