001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.commons.beanutils;
019:
020: import java.io.Serializable;
021: import java.lang.reflect.InvocationTargetException;
022:
023: /**
024: * <p>Implementation of <code>DynaBean</code> that wraps a standard JavaBean
025: * instance, so that DynaBean APIs can be used to access its properties.</p>
026: *
027: * <p>
028: * The most common use cases for this class involve wrapping an existing java bean.
029: * (This makes it different from the typical use cases for other <code>DynaBean</code>'s.)
030: * For example:
031: * </p>
032: * <code><pre>
033: * Object aJavaBean = ...;
034: * ...
035: * DynaBean db = new WrapDynaBean(aJavaBean);
036: * ...
037: * </pre></code>
038: *
039: * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation does not
040: * support the <code>contains()</code> and <code>remove()</code> methods.</p>
041: *
042: * @author Craig McClanahan
043: * @version $Revision: 555824 $ $Date: 2007-07-13 01:27:15 +0100 (Fri, 13 Jul 2007) $
044: */
045:
046: public class WrapDynaBean implements DynaBean, Serializable {
047:
048: // ---------------------------------------------------------- Constructors
049:
050: /**
051: * Construct a new <code>DynaBean</code> associated with the specified
052: * JavaBean instance.
053: *
054: * @param instance JavaBean instance to be wrapped
055: */
056: public WrapDynaBean(Object instance) {
057:
058: super ();
059: this .instance = instance;
060: this .dynaClass = (WrapDynaClass) getDynaClass();
061:
062: }
063:
064: // ---------------------------------------------------- Instance Variables
065:
066: /**
067: * The <code>DynaClass</code> "base class" that this DynaBean
068: * is associated with.
069: */
070: protected transient WrapDynaClass dynaClass = null;
071:
072: /**
073: * The JavaBean instance wrapped by this WrapDynaBean.
074: */
075: protected Object instance = null;
076:
077: // ------------------------------------------------------ DynaBean Methods
078:
079: /**
080: * Does the specified mapped property contain a value for the specified
081: * key value?
082: *
083: * @param name Name of the property to check
084: * @param key Name of the key to check
085: * @return <code>true<code> if the mapped property contains a value for
086: * the specified key, otherwise <code>false</code>
087: *
088: * @exception IllegalArgumentException if there is no property
089: * of the specified name
090: */
091: public boolean contains(String name, String key) {
092:
093: throw new UnsupportedOperationException(
094: "WrapDynaBean does not support contains()");
095:
096: }
097:
098: /**
099: * Return the value of a simple property with the specified name.
100: *
101: * @param name Name of the property whose value is to be retrieved
102: * @return The property's value
103: *
104: * @exception IllegalArgumentException if there is no property
105: * of the specified name
106: */
107: public Object get(String name) {
108:
109: Object value = null;
110: try {
111: value = PropertyUtils.getSimpleProperty(instance, name);
112: } catch (InvocationTargetException ite) {
113: Throwable cause = ite.getTargetException();
114: throw new IllegalArgumentException(
115: "Error reading property '" + name
116: + "' nested exception - " + cause);
117: } catch (Throwable t) {
118: throw new IllegalArgumentException(
119: "Error reading property '" + name
120: + "', exception - " + t);
121: }
122: return (value);
123:
124: }
125:
126: /**
127: * Return the value of an indexed property with the specified name.
128: *
129: * @param name Name of the property whose value is to be retrieved
130: * @param index Index of the value to be retrieved
131: * @return The indexed property's value
132: *
133: * @exception IllegalArgumentException if there is no property
134: * of the specified name
135: * @exception IllegalArgumentException if the specified property
136: * exists, but is not indexed
137: * @exception IndexOutOfBoundsException if the specified index
138: * is outside the range of the underlying property
139: * @exception NullPointerException if no array or List has been
140: * initialized for this property
141: */
142: public Object get(String name, int index) {
143:
144: Object value = null;
145: try {
146: value = PropertyUtils.getIndexedProperty(instance, name,
147: index);
148: } catch (IndexOutOfBoundsException e) {
149: throw e;
150: } catch (InvocationTargetException ite) {
151: Throwable cause = ite.getTargetException();
152: throw new IllegalArgumentException(
153: "Error reading indexed property '" + name
154: + "' nested exception - " + cause);
155: } catch (Throwable t) {
156: throw new IllegalArgumentException(
157: "Error reading indexed property '" + name
158: + "', exception - " + t);
159: }
160: return (value);
161:
162: }
163:
164: /**
165: * Return the value of a mapped property with the specified name,
166: * or <code>null</code> if there is no value for the specified key.
167: *
168: * @param name Name of the property whose value is to be retrieved
169: * @param key Key of the value to be retrieved
170: * @return The mapped property's value
171: *
172: * @exception IllegalArgumentException if there is no property
173: * of the specified name
174: * @exception IllegalArgumentException if the specified property
175: * exists, but is not mapped
176: */
177: public Object get(String name, String key) {
178:
179: Object value = null;
180: try {
181: value = PropertyUtils
182: .getMappedProperty(instance, name, key);
183: } catch (InvocationTargetException ite) {
184: Throwable cause = ite.getTargetException();
185: throw new IllegalArgumentException(
186: "Error reading mapped property '" + name
187: + "' nested exception - " + cause);
188: } catch (Throwable t) {
189: throw new IllegalArgumentException(
190: "Error reading mapped property '" + name
191: + "', exception - " + t);
192: }
193: return (value);
194:
195: }
196:
197: /**
198: * Return the <code>DynaClass</code> instance that describes the set of
199: * properties available for this DynaBean.
200: * @return The associated DynaClass
201: */
202: public DynaClass getDynaClass() {
203:
204: if (dynaClass == null) {
205: dynaClass = WrapDynaClass.createDynaClass(instance
206: .getClass());
207: }
208:
209: return (this .dynaClass);
210:
211: }
212:
213: /**
214: * Remove any existing value for the specified key on the
215: * specified mapped property.
216: *
217: * @param name Name of the property for which a value is to
218: * be removed
219: * @param key Key of the value to be removed
220: *
221: * @exception IllegalArgumentException if there is no property
222: * of the specified name
223: */
224: public void remove(String name, String key) {
225:
226: throw new UnsupportedOperationException(
227: "WrapDynaBean does not support remove()");
228:
229: }
230:
231: /**
232: * Set the value of a simple property with the specified name.
233: *
234: * @param name Name of the property whose value is to be set
235: * @param value Value to which this property is to be set
236: *
237: * @exception ConversionException if the specified value cannot be
238: * converted to the type required for this property
239: * @exception IllegalArgumentException if there is no property
240: * of the specified name
241: * @exception NullPointerException if an attempt is made to set a
242: * primitive property to null
243: */
244: public void set(String name, Object value) {
245:
246: try {
247: PropertyUtils.setSimpleProperty(instance, name, value);
248: } catch (InvocationTargetException ite) {
249: Throwable cause = ite.getTargetException();
250: throw new IllegalArgumentException(
251: "Error setting property '" + name
252: + "' nested exception -" + cause);
253: } catch (Throwable t) {
254: throw new IllegalArgumentException(
255: "Error setting property '" + name
256: + "', exception - " + t);
257: }
258:
259: }
260:
261: /**
262: * Set the value of an indexed property with the specified name.
263: *
264: * @param name Name of the property whose value is to be set
265: * @param index Index of the property to be set
266: * @param value Value to which this property is to be set
267: *
268: * @exception ConversionException if the specified value cannot be
269: * converted to the type required for this property
270: * @exception IllegalArgumentException if there is no property
271: * of the specified name
272: * @exception IllegalArgumentException if the specified property
273: * exists, but is not indexed
274: * @exception IndexOutOfBoundsException if the specified index
275: * is outside the range of the underlying property
276: */
277: public void set(String name, int index, Object value) {
278:
279: try {
280: PropertyUtils.setIndexedProperty(instance, name, index,
281: value);
282: } catch (IndexOutOfBoundsException e) {
283: throw e;
284: } catch (InvocationTargetException ite) {
285: Throwable cause = ite.getTargetException();
286: throw new IllegalArgumentException(
287: "Error setting indexed property '" + name
288: + "' nested exception - " + cause);
289: } catch (Throwable t) {
290: throw new IllegalArgumentException(
291: "Error setting indexed property '" + name
292: + "', exception - " + t);
293: }
294:
295: }
296:
297: /**
298: * Set the value of a mapped property with the specified name.
299: *
300: * @param name Name of the property whose value is to be set
301: * @param key Key of the property to be set
302: * @param value Value to which this property is to be set
303: *
304: * @exception ConversionException if the specified value cannot be
305: * converted to the type required for this property
306: * @exception IllegalArgumentException if there is no property
307: * of the specified name
308: * @exception IllegalArgumentException if the specified property
309: * exists, but is not mapped
310: */
311: public void set(String name, String key, Object value) {
312:
313: try {
314: PropertyUtils.setMappedProperty(instance, name, key, value);
315: } catch (InvocationTargetException ite) {
316: Throwable cause = ite.getTargetException();
317: throw new IllegalArgumentException(
318: "Error setting mapped property '" + name
319: + "' nested exception - " + cause);
320: } catch (Throwable t) {
321: throw new IllegalArgumentException(
322: "Error setting mapped property '" + name
323: + "', exception - " + t);
324: }
325:
326: }
327:
328: /**
329: * Gets the bean instance wrapped by this DynaBean.
330: * For most common use cases,
331: * this object should already be known
332: * and this method safely be ignored.
333: * But some creators of frameworks using <code>DynaBean</code>'s may
334: * find this useful.
335: *
336: * @return the java bean Object wrapped by this <code>DynaBean</code>
337: */
338: public Object getInstance() {
339: return instance;
340: }
341:
342: // ------------------------------------------------------ Protected Methods
343:
344: /**
345: * Return the property descriptor for the specified property name.
346: *
347: * @param name Name of the property for which to retrieve the descriptor
348: * @return The descriptor for the specified property
349: *
350: * @exception IllegalArgumentException if this is not a valid property
351: * name for our DynaClass
352: */
353: protected DynaProperty getDynaProperty(String name) {
354:
355: DynaProperty descriptor = getDynaClass().getDynaProperty(name);
356: if (descriptor == null) {
357: throw new IllegalArgumentException(
358: "Invalid property name '" + name + "'");
359: }
360: return (descriptor);
361:
362: }
363:
364: }
|