Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
WrapDynaBean |
|
| 3.75;3.75 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
3 | * contributor license agreements. See the NOTICE file distributed with | |
4 | * this work for additional information regarding copyright ownership. | |
5 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
6 | * (the "License"); you may not use this file except in compliance with | |
7 | * the License. You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, software | |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
15 | * limitations under the License. | |
16 | */ | |
17 | ||
18 | ||
19 | package org.apache.commons.beanutils; | |
20 | ||
21 | import java.io.Serializable; | |
22 | import java.lang.reflect.InvocationTargetException; | |
23 | ||
24 | ||
25 | /** | |
26 | * <p>Implementation of <code>DynaBean</code> that wraps a standard JavaBean | |
27 | * instance, so that DynaBean APIs can be used to access its properties.</p> | |
28 | * | |
29 | * <p> | |
30 | * The most common use cases for this class involve wrapping an existing java bean. | |
31 | * (This makes it different from the typical use cases for other <code>DynaBean</code>'s.) | |
32 | * For example: | |
33 | * </p> | |
34 | * <code><pre> | |
35 | * Object aJavaBean = ...; | |
36 | * ... | |
37 | * DynaBean db = new WrapDynaBean(aJavaBean); | |
38 | * ... | |
39 | * </pre></code> | |
40 | * | |
41 | * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation does not | |
42 | * support the <code>contains()</code> and <code>remove()</code> methods.</p> | |
43 | * | |
44 | * @author Craig McClanahan | |
45 | * @version $Revision: 926529 $ $Date: 2010-03-23 07:44:24 -0400 (Tue, 23 Mar 2010) $ | |
46 | */ | |
47 | ||
48 | public class WrapDynaBean implements DynaBean, Serializable { | |
49 | ||
50 | ||
51 | // ---------------------------------------------------------- Constructors | |
52 | ||
53 | ||
54 | /** | |
55 | * Construct a new <code>DynaBean</code> associated with the specified | |
56 | * JavaBean instance. | |
57 | * | |
58 | * @param instance JavaBean instance to be wrapped | |
59 | */ | |
60 | public WrapDynaBean(Object instance) { | |
61 | ||
62 | 86 | super(); |
63 | 86 | this.instance = instance; |
64 | 86 | this.dynaClass = (WrapDynaClass)getDynaClass(); |
65 | ||
66 | 86 | } |
67 | ||
68 | ||
69 | // ---------------------------------------------------- Instance Variables | |
70 | ||
71 | ||
72 | /** | |
73 | * The <code>DynaClass</code> "base class" that this DynaBean | |
74 | * is associated with. | |
75 | */ | |
76 | 86 | protected transient WrapDynaClass dynaClass = null; |
77 | ||
78 | ||
79 | /** | |
80 | * The JavaBean instance wrapped by this WrapDynaBean. | |
81 | */ | |
82 | 86 | protected Object instance = null; |
83 | ||
84 | ||
85 | // ------------------------------------------------------ DynaBean Methods | |
86 | ||
87 | ||
88 | /** | |
89 | * Does the specified mapped property contain a value for the specified | |
90 | * key value? | |
91 | * | |
92 | * @param name Name of the property to check | |
93 | * @param key Name of the key to check | |
94 | * @return <code>true<code> if the mapped property contains a value for | |
95 | * the specified key, otherwise <code>false</code> | |
96 | * | |
97 | * @exception IllegalArgumentException if there is no property | |
98 | * of the specified name | |
99 | */ | |
100 | public boolean contains(String name, String key) { | |
101 | ||
102 | 4 | throw new UnsupportedOperationException |
103 | ("WrapDynaBean does not support contains()"); | |
104 | ||
105 | } | |
106 | ||
107 | ||
108 | /** | |
109 | * Return the value of a simple property with the specified name. | |
110 | * | |
111 | * @param name Name of the property whose value is to be retrieved | |
112 | * @return The property's value | |
113 | * | |
114 | * @exception IllegalArgumentException if there is no property | |
115 | * of the specified name | |
116 | */ | |
117 | public Object get(String name) { | |
118 | ||
119 | 33 | Object value = null; |
120 | try { | |
121 | 33 | value = PropertyUtils.getSimpleProperty(instance, name); |
122 | 0 | } catch (InvocationTargetException ite) { |
123 | 0 | Throwable cause = ite.getTargetException(); |
124 | 0 | throw new IllegalArgumentException |
125 | ("Error reading property '" + name + | |
126 | "' nested exception - " + cause); | |
127 | 3 | } catch (Throwable t) { |
128 | 3 | throw new IllegalArgumentException |
129 | ("Error reading property '" + name + | |
130 | "', exception - " + t); | |
131 | 30 | } |
132 | 30 | return (value); |
133 | ||
134 | } | |
135 | ||
136 | ||
137 | /** | |
138 | * Return the value of an indexed property with the specified name. | |
139 | * | |
140 | * @param name Name of the property whose value is to be retrieved | |
141 | * @param index Index of the value to be retrieved | |
142 | * @return The indexed property's value | |
143 | * | |
144 | * @exception IllegalArgumentException if there is no property | |
145 | * of the specified name | |
146 | * @exception IllegalArgumentException if the specified property | |
147 | * exists, but is not indexed | |
148 | * @exception IndexOutOfBoundsException if the specified index | |
149 | * is outside the range of the underlying property | |
150 | * @exception NullPointerException if no array or List has been | |
151 | * initialized for this property | |
152 | */ | |
153 | public Object get(String name, int index) { | |
154 | ||
155 | 35 | Object value = null; |
156 | try { | |
157 | 35 | value = PropertyUtils.getIndexedProperty(instance, name, index); |
158 | 1 | } catch (IndexOutOfBoundsException e) { |
159 | 1 | throw e; |
160 | 0 | } catch (InvocationTargetException ite) { |
161 | 0 | Throwable cause = ite.getTargetException(); |
162 | 0 | throw new IllegalArgumentException |
163 | ("Error reading indexed property '" + name + | |
164 | "' nested exception - " + cause); | |
165 | 2 | } catch (Throwable t) { |
166 | 2 | throw new IllegalArgumentException |
167 | ("Error reading indexed property '" + name + | |
168 | "', exception - " + t); | |
169 | 32 | } |
170 | 32 | return (value); |
171 | ||
172 | } | |
173 | ||
174 | ||
175 | /** | |
176 | * Return the value of a mapped property with the specified name, | |
177 | * or <code>null</code> if there is no value for the specified key. | |
178 | * | |
179 | * @param name Name of the property whose value is to be retrieved | |
180 | * @param key Key of the value to be retrieved | |
181 | * @return The mapped property's value | |
182 | * | |
183 | * @exception IllegalArgumentException if there is no property | |
184 | * of the specified name | |
185 | * @exception IllegalArgumentException if the specified property | |
186 | * exists, but is not mapped | |
187 | */ | |
188 | public Object get(String name, String key) { | |
189 | ||
190 | 8 | Object value = null; |
191 | try { | |
192 | 8 | value = PropertyUtils.getMappedProperty(instance, name, key); |
193 | 0 | } catch (InvocationTargetException ite) { |
194 | 0 | Throwable cause = ite.getTargetException(); |
195 | 0 | throw new IllegalArgumentException |
196 | ("Error reading mapped property '" + name + | |
197 | "' nested exception - " + cause); | |
198 | 1 | } catch (Throwable t) { |
199 | 1 | throw new IllegalArgumentException |
200 | ("Error reading mapped property '" + name + | |
201 | "', exception - " + t); | |
202 | 7 | } |
203 | 7 | return (value); |
204 | ||
205 | } | |
206 | ||
207 | ||
208 | /** | |
209 | * Return the <code>DynaClass</code> instance that describes the set of | |
210 | * properties available for this DynaBean. | |
211 | * @return The associated DynaClass | |
212 | */ | |
213 | public DynaClass getDynaClass() { | |
214 | ||
215 | 124 | if (dynaClass == null) { |
216 | 86 | dynaClass = WrapDynaClass.createDynaClass(instance.getClass()); |
217 | } | |
218 | ||
219 | 124 | return (this.dynaClass); |
220 | ||
221 | } | |
222 | ||
223 | ||
224 | /** | |
225 | * Remove any existing value for the specified key on the | |
226 | * specified mapped property. | |
227 | * | |
228 | * @param name Name of the property for which a value is to | |
229 | * be removed | |
230 | * @param key Key of the value to be removed | |
231 | * | |
232 | * @exception IllegalArgumentException if there is no property | |
233 | * of the specified name | |
234 | */ | |
235 | public void remove(String name, String key) { | |
236 | ||
237 | ||
238 | 0 | throw new UnsupportedOperationException |
239 | ("WrapDynaBean does not support remove()"); | |
240 | ||
241 | } | |
242 | ||
243 | ||
244 | /** | |
245 | * Set the value of a simple property with the specified name. | |
246 | * | |
247 | * @param name Name of the property whose value is to be set | |
248 | * @param value Value to which this property is to be set | |
249 | * | |
250 | * @exception ConversionException if the specified value cannot be | |
251 | * converted to the type required for this property | |
252 | * @exception IllegalArgumentException if there is no property | |
253 | * of the specified name | |
254 | * @exception NullPointerException if an attempt is made to set a | |
255 | * primitive property to null | |
256 | */ | |
257 | public void set(String name, Object value) { | |
258 | ||
259 | try { | |
260 | 13 | PropertyUtils.setSimpleProperty(instance, name, value); |
261 | 0 | } catch (InvocationTargetException ite) { |
262 | 0 | Throwable cause = ite.getTargetException(); |
263 | 0 | throw new IllegalArgumentException |
264 | ("Error setting property '" + name + | |
265 | "' nested exception -" + cause); | |
266 | 2 | } catch (Throwable t) { |
267 | 2 | throw new IllegalArgumentException |
268 | ("Error setting property '" + name + | |
269 | "', exception - " + t); | |
270 | 11 | } |
271 | ||
272 | 11 | } |
273 | ||
274 | ||
275 | /** | |
276 | * Set the value of an indexed property with the specified name. | |
277 | * | |
278 | * @param name Name of the property whose value is to be set | |
279 | * @param index Index of the property to be set | |
280 | * @param value Value to which this property is to be set | |
281 | * | |
282 | * @exception ConversionException if the specified value cannot be | |
283 | * converted to the type required for this property | |
284 | * @exception IllegalArgumentException if there is no property | |
285 | * of the specified name | |
286 | * @exception IllegalArgumentException if the specified property | |
287 | * exists, but is not indexed | |
288 | * @exception IndexOutOfBoundsException if the specified index | |
289 | * is outside the range of the underlying property | |
290 | */ | |
291 | public void set(String name, int index, Object value) { | |
292 | ||
293 | try { | |
294 | 10 | PropertyUtils.setIndexedProperty(instance, name, index, value); |
295 | 1 | } catch (IndexOutOfBoundsException e) { |
296 | 1 | throw e; |
297 | 0 | } catch (InvocationTargetException ite) { |
298 | 0 | Throwable cause = ite.getTargetException(); |
299 | 0 | throw new IllegalArgumentException |
300 | ("Error setting indexed property '" + name + | |
301 | "' nested exception - " + cause); | |
302 | 2 | } catch (Throwable t) { |
303 | 2 | throw new IllegalArgumentException |
304 | ("Error setting indexed property '" + name + | |
305 | "', exception - " + t); | |
306 | 7 | } |
307 | ||
308 | 7 | } |
309 | ||
310 | ||
311 | /** | |
312 | * Set the value of a mapped property with the specified name. | |
313 | * | |
314 | * @param name Name of the property whose value is to be set | |
315 | * @param key Key of the property to be set | |
316 | * @param value Value to which this property is to be set | |
317 | * | |
318 | * @exception ConversionException if the specified value cannot be | |
319 | * converted to the type required for this property | |
320 | * @exception IllegalArgumentException if there is no property | |
321 | * of the specified name | |
322 | * @exception IllegalArgumentException if the specified property | |
323 | * exists, but is not mapped | |
324 | */ | |
325 | public void set(String name, String key, Object value) { | |
326 | ||
327 | try { | |
328 | 4 | PropertyUtils.setMappedProperty(instance, name, key, value); |
329 | 0 | } catch (InvocationTargetException ite) { |
330 | 0 | Throwable cause = ite.getTargetException(); |
331 | 0 | throw new IllegalArgumentException |
332 | ("Error setting mapped property '" + name + | |
333 | "' nested exception - " + cause); | |
334 | 1 | } catch (Throwable t) { |
335 | 1 | throw new IllegalArgumentException |
336 | ("Error setting mapped property '" + name + | |
337 | "', exception - " + t); | |
338 | 3 | } |
339 | ||
340 | 3 | } |
341 | ||
342 | /** | |
343 | * Gets the bean instance wrapped by this DynaBean. | |
344 | * For most common use cases, | |
345 | * this object should already be known | |
346 | * and this method safely be ignored. | |
347 | * But some creators of frameworks using <code>DynaBean</code>'s may | |
348 | * find this useful. | |
349 | * | |
350 | * @return the java bean Object wrapped by this <code>DynaBean</code> | |
351 | */ | |
352 | public Object getInstance() { | |
353 | 58 | return instance; |
354 | } | |
355 | ||
356 | ||
357 | // ------------------------------------------------------ Protected Methods | |
358 | ||
359 | ||
360 | /** | |
361 | * Return the property descriptor for the specified property name. | |
362 | * | |
363 | * @param name Name of the property for which to retrieve the descriptor | |
364 | * @return The descriptor for the specified property | |
365 | * | |
366 | * @exception IllegalArgumentException if this is not a valid property | |
367 | * name for our DynaClass | |
368 | */ | |
369 | protected DynaProperty getDynaProperty(String name) { | |
370 | ||
371 | 0 | DynaProperty descriptor = getDynaClass().getDynaProperty(name); |
372 | 0 | if (descriptor == null) { |
373 | 0 | throw new IllegalArgumentException |
374 | ("Invalid property name '" + name + "'"); | |
375 | } | |
376 | 0 | return (descriptor); |
377 | ||
378 | } | |
379 | ||
380 | ||
381 | } |