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 019 package org.apache.commons.beanutils; 020 021 import java.io.Serializable; 022 import java.lang.reflect.InvocationTargetException; 023 024 025 /** 026 * <p>Implementation of <code>DynaBean</code> that wraps a standard JavaBean 027 * instance, so that DynaBean APIs can be used to access its properties.</p> 028 * 029 * <p> 030 * The most common use cases for this class involve wrapping an existing java bean. 031 * (This makes it different from the typical use cases for other <code>DynaBean</code>'s.) 032 * For example: 033 * </p> 034 * <code><pre> 035 * Object aJavaBean = ...; 036 * ... 037 * DynaBean db = new WrapDynaBean(aJavaBean); 038 * ... 039 * </pre></code> 040 * 041 * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation does not 042 * support the <code>contains()</code> and <code>remove()</code> methods.</p> 043 * 044 * @author Craig McClanahan 045 * @version $Revision: 555824 $ $Date: 2007-07-13 01:27:15 +0100 (Fri, 13 Jul 2007) $ 046 */ 047 048 public class WrapDynaBean implements DynaBean, Serializable { 049 050 051 // ---------------------------------------------------------- Constructors 052 053 054 /** 055 * Construct a new <code>DynaBean</code> associated with the specified 056 * JavaBean instance. 057 * 058 * @param instance JavaBean instance to be wrapped 059 */ 060 public WrapDynaBean(Object instance) { 061 062 super(); 063 this.instance = instance; 064 this.dynaClass = (WrapDynaClass)getDynaClass(); 065 066 } 067 068 069 // ---------------------------------------------------- Instance Variables 070 071 072 /** 073 * The <code>DynaClass</code> "base class" that this DynaBean 074 * is associated with. 075 */ 076 protected transient WrapDynaClass dynaClass = null; 077 078 079 /** 080 * The JavaBean instance wrapped by this WrapDynaBean. 081 */ 082 protected Object instance = null; 083 084 085 // ------------------------------------------------------ DynaBean Methods 086 087 088 /** 089 * Does the specified mapped property contain a value for the specified 090 * key value? 091 * 092 * @param name Name of the property to check 093 * @param key Name of the key to check 094 * @return <code>true<code> if the mapped property contains a value for 095 * the specified key, otherwise <code>false</code> 096 * 097 * @exception IllegalArgumentException if there is no property 098 * of the specified name 099 */ 100 public boolean contains(String name, String key) { 101 102 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 Object value = null; 120 try { 121 value = PropertyUtils.getSimpleProperty(instance, name); 122 } catch (InvocationTargetException ite) { 123 Throwable cause = ite.getTargetException(); 124 throw new IllegalArgumentException 125 ("Error reading property '" + name + 126 "' nested exception - " + cause); 127 } catch (Throwable t) { 128 throw new IllegalArgumentException 129 ("Error reading property '" + name + 130 "', exception - " + t); 131 } 132 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 Object value = null; 156 try { 157 value = PropertyUtils.getIndexedProperty(instance, name, index); 158 } catch (IndexOutOfBoundsException e) { 159 throw e; 160 } catch (InvocationTargetException ite) { 161 Throwable cause = ite.getTargetException(); 162 throw new IllegalArgumentException 163 ("Error reading indexed property '" + name + 164 "' nested exception - " + cause); 165 } catch (Throwable t) { 166 throw new IllegalArgumentException 167 ("Error reading indexed property '" + name + 168 "', exception - " + t); 169 } 170 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 Object value = null; 191 try { 192 value = PropertyUtils.getMappedProperty(instance, name, key); 193 } catch (InvocationTargetException ite) { 194 Throwable cause = ite.getTargetException(); 195 throw new IllegalArgumentException 196 ("Error reading mapped property '" + name + 197 "' nested exception - " + cause); 198 } catch (Throwable t) { 199 throw new IllegalArgumentException 200 ("Error reading mapped property '" + name + 201 "', exception - " + t); 202 } 203 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 if (dynaClass == null) { 216 dynaClass = WrapDynaClass.createDynaClass(instance.getClass()); 217 } 218 219 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 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 PropertyUtils.setSimpleProperty(instance, name, value); 261 } catch (InvocationTargetException ite) { 262 Throwable cause = ite.getTargetException(); 263 throw new IllegalArgumentException 264 ("Error setting property '" + name + 265 "' nested exception -" + cause); 266 } catch (Throwable t) { 267 throw new IllegalArgumentException 268 ("Error setting property '" + name + 269 "', exception - " + t); 270 } 271 272 } 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 PropertyUtils.setIndexedProperty(instance, name, index, value); 295 } catch (IndexOutOfBoundsException e) { 296 throw e; 297 } catch (InvocationTargetException ite) { 298 Throwable cause = ite.getTargetException(); 299 throw new IllegalArgumentException 300 ("Error setting indexed property '" + name + 301 "' nested exception - " + cause); 302 } catch (Throwable t) { 303 throw new IllegalArgumentException 304 ("Error setting indexed property '" + name + 305 "', exception - " + t); 306 } 307 308 } 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 PropertyUtils.setMappedProperty(instance, name, key, value); 329 } catch (InvocationTargetException ite) { 330 Throwable cause = ite.getTargetException(); 331 throw new IllegalArgumentException 332 ("Error setting mapped property '" + name + 333 "' nested exception - " + cause); 334 } catch (Throwable t) { 335 throw new IllegalArgumentException 336 ("Error setting mapped property '" + name + 337 "', exception - " + t); 338 } 339 340 } 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 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 DynaProperty descriptor = getDynaClass().getDynaProperty(name); 372 if (descriptor == null) { 373 throw new IllegalArgumentException 374 ("Invalid property name '" + name + "'"); 375 } 376 return (descriptor); 377 378 } 379 380 381 }