Coverage Report - org.apache.commons.beanutils.locale.LocaleBeanUtilsBean
 
Classes in this File Line Coverage Branch Coverage Complexity
LocaleBeanUtilsBean
30%
53/175
25%
19/74
2.093
LocaleBeanUtilsBean$1
100%
2/2
N/A
2.093
LocaleBeanUtilsBean$Descriptor
0%
0/23
N/A
2.093
 
 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  
 package org.apache.commons.beanutils.locale;
 19  
 
 20  
 
 21  
 import org.apache.commons.beanutils.BeanUtilsBean;
 22  
 import org.apache.commons.beanutils.ConvertUtils;
 23  
 import org.apache.commons.beanutils.ConvertUtilsBean;
 24  
 import org.apache.commons.beanutils.DynaBean;
 25  
 import org.apache.commons.beanutils.DynaClass;
 26  
 import org.apache.commons.beanutils.DynaProperty;
 27  
 import org.apache.commons.beanutils.MappedPropertyDescriptor;
 28  
 import org.apache.commons.beanutils.PropertyUtilsBean;
 29  
 import org.apache.commons.beanutils.ContextClassLoaderLocal;
 30  
 import org.apache.commons.beanutils.expression.Resolver;
 31  
 import org.apache.commons.logging.Log;
 32  
 import org.apache.commons.logging.LogFactory;
 33  
 
 34  
 import java.beans.IndexedPropertyDescriptor;
 35  
 import java.beans.PropertyDescriptor;
 36  
 import java.lang.reflect.InvocationTargetException;
 37  
 import java.util.Locale;
 38  
 
 39  
 
 40  
 /**
 41  
  * <p>Utility methods for populating JavaBeans properties
 42  
  * via reflection in a locale-dependent manner.</p>
 43  
  *
 44  
  * @author Craig R. McClanahan
 45  
  * @author Ralph Schaer
 46  
  * @author Chris Audley
 47  
  * @author Rey Francois
 48  
  * @author Gregor Rayman
 49  
  * @author Yauheny Mikulski
 50  
  * @since 1.7
 51  
  */
 52  
 
 53  
 public class LocaleBeanUtilsBean extends BeanUtilsBean {
 54  
 
 55  
     /** 
 56  
      * Contains <code>LocaleBeanUtilsBean</code> instances indexed by context classloader.
 57  
      */
 58  
     private static final ContextClassLoaderLocal 
 59  1
             LOCALE_BEANS_BY_CLASSLOADER = new ContextClassLoaderLocal() {
 60  
                         // Creates the default instance used when the context classloader is unavailable
 61  
                         protected Object initialValue() {
 62  4
                             return new LocaleBeanUtilsBean();
 63  
                         }
 64  
                     };
 65  
      
 66  
      /**
 67  
       * Gets singleton instance
 68  
       *
 69  
       * @return the singleton instance
 70  
       */
 71  
      public static LocaleBeanUtilsBean getLocaleBeanUtilsInstance() {
 72  74
         return (LocaleBeanUtilsBean)LOCALE_BEANS_BY_CLASSLOADER.get();
 73  
      }
 74  
  
 75  
     /** 
 76  
      * Sets the instance which provides the functionality for {@link LocaleBeanUtils}.
 77  
      * This is a pseudo-singleton - an single instance is provided per (thread) context classloader.
 78  
      * This mechanism provides isolation for web apps deployed in the same container.
 79  
      * 
 80  
      * @param newInstance a new singleton instance
 81  
      */
 82  
     public static void setInstance(LocaleBeanUtilsBean newInstance) {
 83  18
         LOCALE_BEANS_BY_CLASSLOADER.set(newInstance);
 84  18
     }
 85  
 
 86  
     /** All logging goes through this logger */
 87  23
     private Log log = LogFactory.getLog(LocaleBeanUtilsBean.class);
 88  
 
 89  
     // ----------------------------------------------------- Instance Variables
 90  
         
 91  
     /** Convertor used by this class */
 92  
     private LocaleConvertUtilsBean localeConvertUtils;
 93  
     
 94  
     // --------------------------------------------------------- Constructors
 95  
     
 96  
     /** Construct instance with standard conversion bean */
 97  23
     public LocaleBeanUtilsBean() {
 98  23
         this.localeConvertUtils = new LocaleConvertUtilsBean();
 99  23
     }
 100  
     
 101  
     /** 
 102  
      * Construct instance that uses given locale conversion
 103  
      *
 104  
      * @param localeConvertUtils use this <code>localeConvertUtils</code> to perform
 105  
      * conversions
 106  
      * @param convertUtilsBean use this for standard conversions
 107  
      * @param propertyUtilsBean use this for property conversions
 108  
      */
 109  
     public LocaleBeanUtilsBean(
 110  
                             LocaleConvertUtilsBean localeConvertUtils,
 111  
                             ConvertUtilsBean convertUtilsBean,
 112  
                             PropertyUtilsBean propertyUtilsBean) {
 113  0
         super(convertUtilsBean, propertyUtilsBean);
 114  0
         this.localeConvertUtils = localeConvertUtils;
 115  0
     }
 116  
     
 117  
     /** 
 118  
      * Construct instance that uses given locale conversion
 119  
      *
 120  
      * @param localeConvertUtils use this <code>localeConvertUtils</code> to perform
 121  
      * conversions
 122  
      */
 123  0
     public LocaleBeanUtilsBean(LocaleConvertUtilsBean localeConvertUtils) {
 124  0
         this.localeConvertUtils = localeConvertUtils;
 125  0
     }
 126  
     
 127  
     // --------------------------------------------------------- Public Methods
 128  
     
 129  
     /**
 130  
      * Gets the bean instance used for conversions
 131  
      *
 132  
      * @return the locale converter bean instance
 133  
      */
 134  
     public LocaleConvertUtilsBean getLocaleConvertUtils() {
 135  64
         return localeConvertUtils;
 136  
     }
 137  
     
 138  
     /**
 139  
      * Gets the default Locale
 140  
      * @return the default locale
 141  
      */
 142  
     public Locale getDefaultLocale() {
 143  
 
 144  0
         return getLocaleConvertUtils().getDefaultLocale();
 145  
     }
 146  
 
 147  
 
 148  
     /**
 149  
      * Sets the default Locale.
 150  
      *
 151  
      * @param locale the default locale
 152  
      */
 153  
     public void setDefaultLocale(Locale locale) {
 154  
 
 155  0
         getLocaleConvertUtils().setDefaultLocale(locale);
 156  0
     }
 157  
 
 158  
     /**
 159  
      * Is the pattern to be applied localized
 160  
      * (Indicate whether the pattern is localized or not)
 161  
      *
 162  
      * @return <code>true</code> if pattern is localized,
 163  
      * otherwise <code>false</code>
 164  
      */
 165  
     public boolean getApplyLocalized() {
 166  
 
 167  0
         return getLocaleConvertUtils().getApplyLocalized();
 168  
     }
 169  
 
 170  
     /**
 171  
      * Sets whether the pattern is applied localized
 172  
      * (Indicate whether the pattern is localized or not)
 173  
      *
 174  
      * @param newApplyLocalized <code>true</code> if pattern is localized,
 175  
      * otherwise <code>false</code>
 176  
      */
 177  
     public void setApplyLocalized(boolean newApplyLocalized) {
 178  
 
 179  0
         getLocaleConvertUtils().setApplyLocalized(newApplyLocalized);
 180  0
     }
 181  
 
 182  
 
 183  
     // --------------------------------------------------------- Public Methods
 184  
 
 185  
     /**
 186  
      * Return the value of the specified locale-sensitive indexed property
 187  
      * of the specified bean, as a String. The zero-relative index of the
 188  
      * required value must be included (in square brackets) as a suffix to
 189  
      * the property name, or <code>IllegalArgumentException</code> will be
 190  
      * thrown.
 191  
      *
 192  
      * @param bean Bean whose property is to be extracted
 193  
      * @param name <code>propertyname[index]</code> of the property value
 194  
      *  to be extracted
 195  
      * @param pattern The conversion pattern
 196  
      * @return The indexed property's value, converted to a String
 197  
      *
 198  
      * @exception IllegalAccessException if the caller does not have
 199  
      *  access to the property accessor method
 200  
      * @exception InvocationTargetException if the property accessor method
 201  
      *  throws an exception
 202  
      * @exception NoSuchMethodException if an accessor method for this
 203  
      *  propety cannot be found
 204  
      */
 205  
     public String getIndexedProperty(
 206  
                                     Object bean, 
 207  
                                     String name, 
 208  
                                     String pattern)
 209  
                                         throws 
 210  
                                             IllegalAccessException, 
 211  
                                             InvocationTargetException,
 212  
                                             NoSuchMethodException {
 213  
 
 214  0
         Object value = getPropertyUtils().getIndexedProperty(bean, name);
 215  0
         return getLocaleConvertUtils().convert(value, pattern);
 216  
     }
 217  
 
 218  
     /**
 219  
      * Return the value of the specified locale-sensitive indexed property
 220  
      * of the specified bean, as a String using the default conversion pattern of
 221  
      * the corresponding {@link LocaleConverter}. The zero-relative index
 222  
      * of the required value must be included (in square brackets) as a suffix
 223  
      * to the property name, or <code>IllegalArgumentException</code> will be thrown.
 224  
      *
 225  
      * @param bean Bean whose property is to be extracted
 226  
      * @param name <code>propertyname[index]</code> of the property value
 227  
      *  to be extracted
 228  
      * @return The indexed property's value, converted to a String
 229  
      *
 230  
      * @exception IllegalAccessException if the caller does not have
 231  
      *  access to the property accessor method
 232  
      * @exception InvocationTargetException if the property accessor method
 233  
      *  throws an exception
 234  
      * @exception NoSuchMethodException if an accessor method for this
 235  
      *  propety cannot be found
 236  
      */
 237  
     public String getIndexedProperty(
 238  
                                     Object bean, 
 239  
                                     String name)
 240  
                                         throws 
 241  
                                             IllegalAccessException, 
 242  
                                             InvocationTargetException,
 243  
                                             NoSuchMethodException {
 244  
 
 245  0
         return getIndexedProperty(bean, name, null);
 246  
     }
 247  
 
 248  
     /**
 249  
      * Return the value of the specified locale-sensetive indexed property
 250  
      * of the specified bean, as a String using the specified conversion pattern.
 251  
      * The index is specified as a method parameter and
 252  
      * must *not* be included in the property name expression
 253  
      *
 254  
      * @param bean Bean whose property is to be extracted
 255  
      * @param name Simple property name of the property value to be extracted
 256  
      * @param index Index of the property value to be extracted
 257  
      * @param pattern The conversion pattern
 258  
      * @return The indexed property's value, converted to a String
 259  
      *
 260  
      * @exception IllegalAccessException if the caller does not have
 261  
      *  access to the property accessor method
 262  
      * @exception InvocationTargetException if the property accessor method
 263  
      *  throws an exception
 264  
      * @exception NoSuchMethodException if an accessor method for this
 265  
      *  propety cannot be found
 266  
      */
 267  
     public String getIndexedProperty(Object bean,
 268  
                                             String name, int index, String pattern)
 269  
             throws IllegalAccessException, InvocationTargetException,
 270  
             NoSuchMethodException {
 271  
 
 272  0
         Object value = getPropertyUtils().getIndexedProperty(bean, name, index);
 273  0
         return getLocaleConvertUtils().convert(value, pattern);
 274  
     }
 275  
 
 276  
     /**
 277  
      * Return the value of the specified locale-sensetive indexed property
 278  
      * of the specified bean, as a String using the default conversion pattern of
 279  
      * the corresponding {@link LocaleConverter}.
 280  
      * The index is specified as a method parameter and
 281  
      * must *not* be included in the property name expression
 282  
      *
 283  
      * @param bean Bean whose property is to be extracted
 284  
      * @param name Simple property name of the property value to be extracted
 285  
      * @param index Index of the property value to be extracted
 286  
      * @return The indexed property's value, converted to a String
 287  
      *
 288  
      * @exception IllegalAccessException if the caller does not have
 289  
      *  access to the property accessor method
 290  
      * @exception InvocationTargetException if the property accessor method
 291  
      *  throws an exception
 292  
      * @exception NoSuchMethodException if an accessor method for this
 293  
      *  propety cannot be found
 294  
      */
 295  
     public String getIndexedProperty(Object bean,
 296  
                                             String name, int index)
 297  
             throws IllegalAccessException, InvocationTargetException,
 298  
             NoSuchMethodException {
 299  0
         return getIndexedProperty(bean, name, index, null);
 300  
     }
 301  
 
 302  
     /**
 303  
      * Return the value of the specified simple locale-sensitive property
 304  
      * of the specified bean, converted to a String using the specified
 305  
      * conversion pattern.
 306  
      *
 307  
      * @param bean Bean whose property is to be extracted
 308  
      * @param name Name of the property to be extracted
 309  
      * @param pattern The conversion pattern
 310  
      * @return The property's value, converted to a String
 311  
      *
 312  
      * @exception IllegalAccessException if the caller does not have
 313  
      *  access to the property accessor method
 314  
      * @exception InvocationTargetException if the property accessor method
 315  
      *  throws an exception
 316  
      * @exception NoSuchMethodException if an accessor method for this
 317  
      *  propety cannot be found
 318  
      */
 319  
     public String getSimpleProperty(Object bean, String name, String pattern)
 320  
             throws IllegalAccessException, InvocationTargetException,
 321  
             NoSuchMethodException {
 322  
 
 323  0
         Object value = getPropertyUtils().getSimpleProperty(bean, name);
 324  0
         return getLocaleConvertUtils().convert(value, pattern);
 325  
     }
 326  
 
 327  
     /**
 328  
      * Return the value of the specified simple locale-sensitive property
 329  
      * of the specified bean, converted to a String using the default
 330  
      * conversion pattern of the corresponding {@link LocaleConverter}.
 331  
      *
 332  
      * @param bean Bean whose property is to be extracted
 333  
      * @param name Name of the property to be extracted
 334  
      * @return The property's value, converted to a String
 335  
      *
 336  
      * @exception IllegalAccessException if the caller does not have
 337  
      *  access to the property accessor method
 338  
      * @exception InvocationTargetException if the property accessor method
 339  
      *  throws an exception
 340  
      * @exception NoSuchMethodException if an accessor method for this
 341  
      *  propety cannot be found
 342  
      */
 343  
     public String getSimpleProperty(Object bean, String name)
 344  
             throws IllegalAccessException, InvocationTargetException,
 345  
             NoSuchMethodException {
 346  
 
 347  0
         return getSimpleProperty(bean, name, null);
 348  
     }
 349  
 
 350  
     /**
 351  
      * Return the value of the specified mapped locale-sensitive property
 352  
      * of the specified bean, as a String using the specified conversion pattern.
 353  
      * The key is specified as a method parameter and must *not* be included in
 354  
      * the property name expression.
 355  
      *
 356  
      * @param bean Bean whose property is to be extracted
 357  
      * @param name Simple property name of the property value to be extracted
 358  
      * @param key Lookup key of the property value to be extracted
 359  
      * @param pattern The conversion pattern
 360  
      * @return The mapped property's value, converted to a String
 361  
      *
 362  
      * @exception IllegalAccessException if the caller does not have
 363  
      *  access to the property accessor method
 364  
      * @exception InvocationTargetException if the property accessor method
 365  
      *  throws an exception
 366  
      * @exception NoSuchMethodException if an accessor method for this
 367  
      *  propety cannot be found
 368  
      */
 369  
     public String getMappedProperty(
 370  
                                     Object bean,
 371  
                                     String name, 
 372  
                                     String key, 
 373  
                                     String pattern)
 374  
                                         throws 
 375  
                                             IllegalAccessException, 
 376  
                                             InvocationTargetException,
 377  
                                             NoSuchMethodException {
 378  
 
 379  0
         Object value = getPropertyUtils().getMappedProperty(bean, name, key);
 380  0
         return getLocaleConvertUtils().convert(value, pattern);
 381  
     }
 382  
 
 383  
     /**
 384  
      * Return the value of the specified mapped locale-sensitive property
 385  
      * of the specified bean, as a String
 386  
      * The key is specified as a method parameter and must *not* be included
 387  
      * in the property name expression
 388  
      *
 389  
      * @param bean Bean whose property is to be extracted
 390  
      * @param name Simple property name of the property value to be extracted
 391  
      * @param key Lookup key of the property value to be extracted
 392  
      * @return The mapped property's value, converted to a String
 393  
      *
 394  
      * @exception IllegalAccessException if the caller does not have
 395  
      *  access to the property accessor method
 396  
      * @exception InvocationTargetException if the property accessor method
 397  
      *  throws an exception
 398  
      * @exception NoSuchMethodException if an accessor method for this
 399  
      *  propety cannot be found
 400  
      */
 401  
     public String getMappedProperty(Object bean,
 402  
                                            String name, String key)
 403  
             throws IllegalAccessException, InvocationTargetException,
 404  
             NoSuchMethodException {
 405  
 
 406  0
         return getMappedProperty(bean, name, key, null);
 407  
     }
 408  
 
 409  
 
 410  
     /**
 411  
      * Return the value of the specified locale-sensitive mapped property
 412  
      * of the specified bean, as a String using the specified pattern.
 413  
      * The String-valued key of the required value
 414  
      * must be included (in parentheses) as a suffix to
 415  
      * the property name, or <code>IllegalArgumentException</code> will be
 416  
      * thrown.
 417  
      *
 418  
      * @param bean Bean whose property is to be extracted
 419  
      * @param name <code>propertyname(index)</code> of the property value
 420  
      *  to be extracted
 421  
      * @param pattern The conversion pattern
 422  
      * @return The mapped property's value, converted to a String
 423  
      *
 424  
      * @exception IllegalAccessException if the caller does not have
 425  
      *  access to the property accessor method
 426  
      * @exception InvocationTargetException if the property accessor method
 427  
      *  throws an exception
 428  
      * @exception NoSuchMethodException if an accessor method for this
 429  
      *  propety cannot be found
 430  
      */
 431  
     public String getMappedPropertyLocale(
 432  
                                         Object bean, 
 433  
                                         String name, 
 434  
                                         String pattern)
 435  
                                             throws 
 436  
                                                 IllegalAccessException, 
 437  
                                                 InvocationTargetException,
 438  
                                                 NoSuchMethodException {
 439  
 
 440  0
         Object value = getPropertyUtils().getMappedProperty(bean, name);
 441  0
         return getLocaleConvertUtils().convert(value, pattern);
 442  
     }
 443  
 
 444  
 
 445  
     /**
 446  
      * Return the value of the specified locale-sensitive mapped property
 447  
      * of the specified bean, as a String using the default
 448  
      * conversion pattern of the corresponding {@link LocaleConverter}.
 449  
      * The String-valued key of the required value
 450  
      * must be included (in parentheses) as a suffix to
 451  
      * the property name, or <code>IllegalArgumentException</code> will be
 452  
      * thrown.
 453  
      *
 454  
      * @param bean Bean whose property is to be extracted
 455  
      * @param name <code>propertyname(index)</code> of the property value
 456  
      *  to be extracted
 457  
      * @return The mapped property's value, converted to a String
 458  
      *
 459  
      * @exception IllegalAccessException if the caller does not have
 460  
      *  access to the property accessor method
 461  
      * @exception InvocationTargetException if the property accessor method
 462  
      *  throws an exception
 463  
      * @exception NoSuchMethodException if an accessor method for this
 464  
      *  propety cannot be found
 465  
      */
 466  
     public String getMappedProperty(Object bean, String name)
 467  
                                     throws 
 468  
                                         IllegalAccessException, 
 469  
                                         InvocationTargetException,
 470  
                                         NoSuchMethodException {
 471  
 
 472  0
         return getMappedPropertyLocale(bean, name, null);
 473  
     }
 474  
 
 475  
     /**
 476  
      * Return the value of the (possibly nested) locale-sensitive property
 477  
      * of the specified name, for the specified bean,
 478  
      * as a String using the specified pattern.
 479  
      *
 480  
      * @param bean Bean whose property is to be extracted
 481  
      * @param name Possibly nested name of the property to be extracted
 482  
      * @param pattern The conversion pattern
 483  
      * @return The nested property's value, converted to a String
 484  
      *
 485  
      * @exception IllegalAccessException if the caller does not have
 486  
      *  access to the property accessor method
 487  
      * @exception IllegalArgumentException if a nested reference to a
 488  
      *  property returns null
 489  
      * @exception InvocationTargetException if the property accessor method
 490  
      *  throws an exception
 491  
      * @exception NoSuchMethodException if an accessor method for this
 492  
      *  propety cannot be found
 493  
      */
 494  
     public String getNestedProperty(    
 495  
                                     Object bean, 
 496  
                                     String name, 
 497  
                                     String pattern)
 498  
                                         throws 
 499  
                                             IllegalAccessException, 
 500  
                                             InvocationTargetException,
 501  
                                             NoSuchMethodException {
 502  
 
 503  0
         Object value = getPropertyUtils().getNestedProperty(bean, name);
 504  0
         return getLocaleConvertUtils().convert(value, pattern);
 505  
     }
 506  
 
 507  
     /**
 508  
      * Return the value of the (possibly nested) locale-sensitive property
 509  
      * of the specified name, for the specified bean, as a String using the default
 510  
      * conversion pattern of the corresponding {@link LocaleConverter}.
 511  
      *
 512  
      * @param bean Bean whose property is to be extracted
 513  
      * @param name Possibly nested name of the property to be extracted
 514  
      * @return The nested property's value, converted to a String
 515  
      *
 516  
      * @exception IllegalAccessException if the caller does not have
 517  
      *  access to the property accessor method
 518  
      * @exception IllegalArgumentException if a nested reference to a
 519  
      *  property returns null
 520  
      * @exception InvocationTargetException if the property accessor method
 521  
      *  throws an exception
 522  
      * @exception NoSuchMethodException if an accessor method for this
 523  
      *  propety cannot be found
 524  
      */
 525  
     public String getNestedProperty(Object bean, String name)
 526  
                                     throws 
 527  
                                         IllegalAccessException, 
 528  
                                         InvocationTargetException,
 529  
                                         NoSuchMethodException {
 530  
 
 531  0
         return getNestedProperty(bean, name, null);
 532  
     }
 533  
 
 534  
     /**
 535  
      * Return the value of the specified locale-sensitive property
 536  
      * of the specified bean, no matter which property reference
 537  
      * format is used, as a String using the specified conversion pattern.
 538  
      *
 539  
      * @param bean Bean whose property is to be extracted
 540  
      * @param name Possibly indexed and/or nested name of the property
 541  
      *  to be extracted
 542  
      * @param pattern The conversion pattern
 543  
      * @return The nested property's value, converted to a String
 544  
      *
 545  
      * @exception IllegalAccessException if the caller does not have
 546  
      *  access to the property accessor method
 547  
      * @exception InvocationTargetException if the property accessor method
 548  
      *  throws an exception
 549  
      * @exception NoSuchMethodException if an accessor method for this
 550  
      *  propety cannot be found
 551  
      */
 552  
     public String getProperty(Object bean, String name, String pattern)
 553  
                                 throws 
 554  
                                     IllegalAccessException, 
 555  
                                     InvocationTargetException,
 556  
                                     NoSuchMethodException {
 557  
 
 558  0
         return getNestedProperty(bean, name, pattern);
 559  
     }
 560  
 
 561  
     /**
 562  
      * Return the value of the specified locale-sensitive property
 563  
      * of the specified bean, no matter which property reference
 564  
      * format is used, as a String using the default
 565  
      * conversion pattern of the corresponding {@link LocaleConverter}.
 566  
      *
 567  
      * @param bean Bean whose property is to be extracted
 568  
      * @param name Possibly indexed and/or nested name of the property
 569  
      *  to be extracted
 570  
      * @return The property's value, converted to a String
 571  
      *
 572  
      * @exception IllegalAccessException if the caller does not have
 573  
      *  access to the property accessor method
 574  
      * @exception InvocationTargetException if the property accessor method
 575  
      *  throws an exception
 576  
      * @exception NoSuchMethodException if an accessor method for this
 577  
      *  propety cannot be found
 578  
      */
 579  
     public String getProperty(Object bean, String name)
 580  
                                 throws 
 581  
                                     IllegalAccessException, 
 582  
                                     InvocationTargetException,
 583  
                                     NoSuchMethodException {
 584  
 
 585  0
         return getNestedProperty(bean, name);
 586  
     }
 587  
 
 588  
     /**
 589  
      * Set the specified locale-sensitive property value, performing type
 590  
      * conversions as required to conform to the type of the destination property
 591  
      * using the default conversion pattern of the corresponding {@link LocaleConverter}.
 592  
      *
 593  
      * @param bean Bean on which setting is to be performed
 594  
      * @param name Property name (can be nested/indexed/mapped/combo)
 595  
      * @param value Value to be set
 596  
      *
 597  
      * @exception IllegalAccessException if the caller does not have
 598  
      *  access to the property accessor method
 599  
      * @exception InvocationTargetException if the property accessor method
 600  
      *  throws an exception
 601  
      */
 602  
     public void setProperty(Object bean, String name, Object value)
 603  
                                 throws 
 604  
                                     IllegalAccessException, 
 605  
                                     InvocationTargetException {
 606  
 
 607  3
         setProperty(bean, name, value, null);
 608  3
     }
 609  
 
 610  
     /**
 611  
      * Set the specified locale-sensitive property value, performing type
 612  
      * conversions as required to conform to the type of the destination
 613  
      * property using the specified conversion pattern.
 614  
      *
 615  
      * @param bean Bean on which setting is to be performed
 616  
      * @param name Property name (can be nested/indexed/mapped/combo)
 617  
      * @param value Value to be set
 618  
      * @param pattern The conversion pattern
 619  
      *
 620  
      * @exception IllegalAccessException if the caller does not have
 621  
      *  access to the property accessor method
 622  
      * @exception InvocationTargetException if the property accessor method
 623  
      *  throws an exception
 624  
      */
 625  
     public void setProperty(
 626  
                             Object bean, 
 627  
                             String name, 
 628  
                             Object value, 
 629  
                             String pattern)
 630  
                                 throws 
 631  
                                     IllegalAccessException, 
 632  
                                     InvocationTargetException {
 633  
 
 634  
         // Trace logging (if enabled)
 635  5
         if (log.isTraceEnabled()) {
 636  0
             StringBuffer sb = new StringBuffer("  setProperty(");
 637  0
             sb.append(bean);
 638  0
             sb.append(", ");
 639  0
             sb.append(name);
 640  0
             sb.append(", ");
 641  0
             if (value == null) {
 642  0
                 sb.append("<NULL>");
 643  
             }
 644  0
             else if (value instanceof String) {
 645  0
                 sb.append((String) value);
 646  
             }
 647  0
             else if (value instanceof String[]) {
 648  0
                 String[] values = (String[]) value;
 649  0
                 sb.append('[');
 650  0
                 for (int i = 0; i < values.length; i++) {
 651  0
                     if (i > 0) {
 652  0
                         sb.append(',');
 653  
                     }
 654  0
                     sb.append(values[i]);
 655  
                 }
 656  0
                 sb.append(']');
 657  0
             }
 658  
             else {
 659  0
                 sb.append(value.toString());
 660  
             }
 661  0
             sb.append(')');
 662  0
             log.trace(sb.toString());
 663  
         }
 664  
 
 665  
         // Resolve any nested expression to get the actual target bean
 666  5
         Object target = bean;
 667  5
         Resolver resolver = getPropertyUtils().getResolver();
 668  7
         while (resolver.hasNested(name)) {
 669  
             try {
 670  2
                 target = getPropertyUtils().getProperty(target, resolver.next(name));
 671  2
                 name = resolver.remove(name);
 672  0
             } catch (NoSuchMethodException e) {
 673  0
                 return; // Skip this property setter
 674  2
             }
 675  
         }
 676  5
         if (log.isTraceEnabled()) {
 677  0
             log.trace("    Target bean = " + target);
 678  0
             log.trace("    Target name = " + name);
 679  
         }
 680  
 
 681  
         // Declare local variables we will require
 682  5
         String propName = resolver.getProperty(name); // Simple name of target property
 683  5
         int index  = resolver.getIndex(name);         // Indexed subscript value (if any)
 684  5
         String key = resolver.getKey(name);           // Mapped key value (if any)
 685  
 
 686  5
         Class type = definePropertyType(target, name, propName);
 687  5
         if (type != null) {
 688  5
             Object newValue = convert(type, index, value, pattern);
 689  5
             invokeSetter(target, propName, key, index, newValue);
 690  
         }
 691  5
     }
 692  
 
 693  
     /**
 694  
      * Calculate the property type.
 695  
      *
 696  
      * @param target The bean
 697  
      * @param name The property name
 698  
      * @param propName The Simple name of target property
 699  
      * @return The property's type
 700  
      *
 701  
      * @exception IllegalAccessException if the caller does not have
 702  
      *  access to the property accessor method
 703  
      * @exception InvocationTargetException if the property accessor method
 704  
      *  throws an exception
 705  
      */
 706  
     protected Class definePropertyType(Object target, String name, String propName)
 707  
             throws IllegalAccessException, InvocationTargetException {
 708  
 
 709  5
         Class type = null;               // Java type of target property
 710  
 
 711  5
         if (target instanceof DynaBean) {
 712  0
             DynaClass dynaClass = ((DynaBean) target).getDynaClass();
 713  0
             DynaProperty dynaProperty = dynaClass.getDynaProperty(propName);
 714  0
             if (dynaProperty == null) {
 715  0
                 return null; // Skip this property setter
 716  
             }
 717  0
             type = dynaProperty.getType();
 718  0
         }
 719  
         else {
 720  5
             PropertyDescriptor descriptor = null;
 721  
             try {
 722  5
                 descriptor =
 723  
                         getPropertyUtils().getPropertyDescriptor(target, name);
 724  5
                 if (descriptor == null) {
 725  0
                     return null; // Skip this property setter
 726  
                 }
 727  
             }
 728  0
             catch (NoSuchMethodException e) {
 729  0
                 return null; // Skip this property setter
 730  5
             }
 731  5
             if (descriptor instanceof MappedPropertyDescriptor) {
 732  0
                 type = ((MappedPropertyDescriptor) descriptor).
 733  
                         getMappedPropertyType();
 734  
             }
 735  5
             else if (descriptor instanceof IndexedPropertyDescriptor) {
 736  1
                 type = ((IndexedPropertyDescriptor) descriptor).
 737  
                         getIndexedPropertyType();
 738  
             }
 739  
             else {
 740  4
                 type = descriptor.getPropertyType();
 741  
             }
 742  
         }
 743  5
         return type;
 744  
     }
 745  
 
 746  
     /**
 747  
      * Convert the specified value to the required type using the
 748  
      * specified conversion pattern.
 749  
      *
 750  
      * @param type The Java type of target property
 751  
      * @param index The indexed subscript value (if any)
 752  
      * @param value The value to be converted
 753  
      * @param pattern The conversion pattern
 754  
      * @return The converted value
 755  
      */
 756  
     protected Object convert(Class type, int index, Object value, String pattern) {
 757  
 
 758  5
         if (log.isTraceEnabled()) {
 759  0
             log.trace("Converting value '" + value + "' to type:" + type);
 760  
         }
 761  
 
 762  5
         Object newValue = null;
 763  
 
 764  5
         if (type.isArray() && (index < 0)) { // Scalar value into array
 765  0
             if (value instanceof String) {
 766  0
                 String[] values = new String[1];
 767  0
                 values[0] = (String) value;
 768  0
                 newValue = getLocaleConvertUtils().convert(values, type, pattern);
 769  0
             }
 770  0
             else if (value instanceof String[]) {
 771  0
                 newValue = getLocaleConvertUtils().convert((String[]) value, type, pattern);
 772  
             }
 773  
             else {
 774  0
                 newValue = value;
 775  
             }
 776  
         }
 777  5
         else if (type.isArray()) {         // Indexed value into array
 778  0
             if (value instanceof String) {
 779  0
                 newValue = getLocaleConvertUtils().convert((String) value,
 780  
                         type.getComponentType(), pattern);
 781  
             }
 782  0
             else if (value instanceof String[]) {
 783  0
                 newValue = getLocaleConvertUtils().convert(((String[]) value)[0],
 784  
                         type.getComponentType(), pattern);
 785  
             }
 786  
             else {
 787  0
                 newValue = value;
 788  
             }
 789  
         }
 790  
         else {                             // Value into scalar
 791  5
             if (value instanceof String) {
 792  4
                 newValue = getLocaleConvertUtils().convert((String) value, type, pattern);
 793  
             }
 794  1
             else if (value instanceof String[]) {
 795  0
                 newValue = getLocaleConvertUtils().convert(((String[]) value)[0],
 796  
                         type, pattern);
 797  
             }
 798  
             else {
 799  1
                 newValue = value;
 800  
             }
 801  
         }
 802  5
         return newValue;
 803  
     }
 804  
 
 805  
     /**
 806  
      *  Convert the specified value to the required type.
 807  
      *
 808  
      * @param type The Java type of target property
 809  
      * @param index The indexed subscript value (if any)
 810  
      * @param value The value to be converted
 811  
      * @return The converted value
 812  
      */
 813  
     protected Object convert(Class type, int index, Object value) {
 814  
 
 815  0
         Object newValue = null;
 816  
 
 817  0
         if (type.isArray() && (index < 0)) { // Scalar value into array
 818  0
             if (value instanceof String) {
 819  0
                 String[] values = new String[1];
 820  0
                 values[0] = (String) value;
 821  0
                 newValue = ConvertUtils.convert(values, type);
 822  0
             }
 823  0
             else if (value instanceof String[]) {
 824  0
                 newValue = ConvertUtils.convert((String[]) value, type);
 825  
             }
 826  
             else {
 827  0
                 newValue = value;
 828  
             }
 829  
         }
 830  0
         else if (type.isArray()) {         // Indexed value into array
 831  0
             if (value instanceof String) {
 832  0
                 newValue = ConvertUtils.convert((String) value,
 833  
                         type.getComponentType());
 834  
             }
 835  0
             else if (value instanceof String[]) {
 836  0
                 newValue = ConvertUtils.convert(((String[]) value)[0],
 837  
                         type.getComponentType());
 838  
             }
 839  
             else {
 840  0
                 newValue = value;
 841  
             }
 842  
         }
 843  
         else {                             // Value into scalar
 844  0
             if (value instanceof String) {
 845  0
                 newValue = ConvertUtils.convert((String) value, type);
 846  
             }
 847  0
             else if (value instanceof String[]) {
 848  0
                 newValue = ConvertUtils.convert(((String[]) value)[0],
 849  
                         type);
 850  
             }
 851  
             else {
 852  0
                 newValue = value;
 853  
             }
 854  
         }
 855  0
         return newValue;
 856  
     }
 857  
 
 858  
     /**
 859  
      * Invoke the setter method.
 860  
      *
 861  
      * @param target The bean
 862  
      * @param propName The Simple name of target property
 863  
      * @param key The Mapped key value (if any)
 864  
      * @param index The indexed subscript value (if any)
 865  
      * @param newValue The value to be set
 866  
      *
 867  
      * @exception IllegalAccessException if the caller does not have
 868  
      *  access to the property accessor method
 869  
      * @exception InvocationTargetException if the property accessor method
 870  
      *  throws an exception
 871  
      */
 872  
     protected void invokeSetter(Object target, String propName, String key, int index, Object newValue)
 873  
             throws IllegalAccessException, InvocationTargetException {
 874  
 
 875  
         try {
 876  5
             if (index >= 0) {
 877  1
                 getPropertyUtils().setIndexedProperty(target, propName,
 878  
                         index, newValue);
 879  
             }
 880  4
             else if (key != null) {
 881  0
                 getPropertyUtils().setMappedProperty(target, propName,
 882  
                         key, newValue);
 883  
             }
 884  
             else {
 885  4
                 getPropertyUtils().setProperty(target, propName, newValue);
 886  
             }
 887  
         }
 888  0
         catch (NoSuchMethodException e) {
 889  0
             throw new InvocationTargetException
 890  
                     (e, "Cannot set " + propName);
 891  5
         }
 892  5
     }
 893  
 
 894  
     /**
 895  
      * Resolve any nested expression to get the actual target property.
 896  
      *
 897  
      * @param bean The bean
 898  
      * @param name The property name
 899  
      * @return The property's descriptor
 900  
      *
 901  
      * @exception IllegalAccessException if the caller does not have
 902  
      *  access to the property accessor method
 903  
      * @exception InvocationTargetException if the property accessor method
 904  
      *  throws an exception
 905  
      * @deprecated Property name expressions are now processed by
 906  
      * the configured {@link Resolver} implementation and this method
 907  
      * is no longer used by BeanUtils.
 908  
      */
 909  
     protected Descriptor calculate(Object bean, String name)
 910  
             throws IllegalAccessException, InvocationTargetException {
 911  
 
 912  
         // Resolve any nested expression to get the actual target bean
 913  0
         Object target = bean;
 914  0
         Resolver resolver = getPropertyUtils().getResolver();
 915  0
         while (resolver.hasNested(name)) {
 916  
             try {
 917  0
                 target = getPropertyUtils().getProperty(target, resolver.next(name));
 918  0
                 name = resolver.remove(name);
 919  0
             } catch (NoSuchMethodException e) {
 920  0
                 return null; // Skip this property setter
 921  0
             }
 922  
         }
 923  0
         if (log.isTraceEnabled()) {
 924  0
             log.trace("    Target bean = " + target);
 925  0
             log.trace("    Target name = " + name);
 926  
         }
 927  
 
 928  
         // Declare local variables we will require
 929  0
         String propName = resolver.getProperty(name); // Simple name of target property
 930  0
         int index  = resolver.getIndex(name);         // Indexed subscript value (if any)
 931  0
         String key = resolver.getKey(name);           // Mapped key value (if any)
 932  
 
 933  0
         return new Descriptor(target, name, propName, key, index);
 934  
     }
 935  
 
 936  
     /**
 937  
      * @deprecated Property name expressions are now processed by
 938  
      * the configured {@link Resolver} implementation and this class
 939  
      * is no longer used by BeanUtils.
 940  
      */
 941  
     protected class Descriptor {
 942  
 
 943  0
         private int index = -1;    // Indexed subscript value (if any)
 944  
         private String name;
 945  
         private String propName;   // Simple name of target property
 946  
         private String key;        // Mapped key value (if any)
 947  
         private Object target;
 948  
 
 949  
         /**
 950  
          * Construct a descriptor instance for the target bean and property.
 951  
          *
 952  
          * @param target The target bean
 953  
          * @param name The property name (includes indexed/mapped expr)
 954  
          * @param propName The property name
 955  
          * @param key The mapped property key (if any)
 956  
          * @param index The indexed property index (if any)
 957  
          */
 958  0
         public Descriptor(Object target, String name, String propName, String key, int index) {
 959  
 
 960  0
             setTarget(target);
 961  0
             setName(name);
 962  0
             setPropName(propName);
 963  0
             setKey(key);
 964  0
             setIndex(index);
 965  0
         }
 966  
 
 967  
         /**
 968  
          * Return the target bean.
 969  
          *
 970  
          * @return The descriptors target bean
 971  
          */
 972  
         public Object getTarget() {
 973  0
             return target;
 974  
         }
 975  
 
 976  
         /**
 977  
          * Set the target bean.
 978  
          *
 979  
          * @param target The target bean
 980  
          */
 981  
         public void setTarget(Object target) {
 982  0
             this.target = target;
 983  0
         }
 984  
 
 985  
         /**
 986  
          * Return the mapped property key.
 987  
          *
 988  
          * @return the mapped property key (if any)
 989  
          */
 990  
         public String getKey() {
 991  0
             return key;
 992  
         }
 993  
 
 994  
         /**
 995  
          * Set the mapped property key.
 996  
          *
 997  
          * @param key The mapped property key (if any)
 998  
          */
 999  
         public void setKey(String key) {
 1000  0
             this.key = key;
 1001  0
         }
 1002  
 
 1003  
         /**
 1004  
          * Return indexed property index.
 1005  
          *
 1006  
          * @return indexed property index (if any)
 1007  
          */
 1008  
         public int getIndex() {
 1009  0
             return index;
 1010  
         }
 1011  
 
 1012  
         /**
 1013  
          * Set the indexed property index.
 1014  
          *
 1015  
          * @param index The indexed property index (if any)
 1016  
          */
 1017  
         public void setIndex(int index) {
 1018  0
             this.index = index;
 1019  0
         }
 1020  
 
 1021  
         /**
 1022  
          * Return property name (includes indexed/mapped expr).
 1023  
          *
 1024  
          * @return The property name (includes indexed/mapped expr)
 1025  
          */
 1026  
         public String getName() {
 1027  0
             return name;
 1028  
         }
 1029  
 
 1030  
         /**
 1031  
          * Set the property name (includes indexed/mapped expr).
 1032  
          *
 1033  
          * @param name The property name (includes indexed/mapped expr)
 1034  
          */
 1035  
         public void setName(String name) {
 1036  0
             this.name = name;
 1037  0
         }
 1038  
 
 1039  
         /**
 1040  
          * Return the property name.
 1041  
          *
 1042  
          * @return The property name
 1043  
          */
 1044  
         public String getPropName() {
 1045  0
             return propName;
 1046  
         }
 1047  
 
 1048  
         /**
 1049  
          * Set the property name.
 1050  
          *
 1051  
          * @param propName The property name
 1052  
          */
 1053  
         public void setPropName(String propName) {
 1054  0
             this.propName = propName;
 1055  0
         }
 1056  
     }
 1057  
 }
 1058  
 
 1059