1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 LOCALE_BEANS_BY_CLASSLOADER = new ContextClassLoaderLocal() {
60
61 protected Object initialValue() {
62 return new LocaleBeanUtilsBean();
63 }
64 };
65
66 /***
67 * Gets singleton instance
68 *
69 * @return the singleton instance
70 */
71 public static LocaleBeanUtilsBean getLocaleBeanUtilsInstance() {
72 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 LOCALE_BEANS_BY_CLASSLOADER.set(newInstance);
84 }
85
86 /*** All logging goes through this logger */
87 private Log log = LogFactory.getLog(LocaleBeanUtilsBean.class);
88
89
90
91 /*** Convertor used by this class */
92 private LocaleConvertUtilsBean localeConvertUtils;
93
94
95
96 /*** Construct instance with standard conversion bean */
97 public LocaleBeanUtilsBean() {
98 this.localeConvertUtils = new LocaleConvertUtilsBean();
99 }
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 super(convertUtilsBean, propertyUtilsBean);
114 this.localeConvertUtils = localeConvertUtils;
115 }
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 public LocaleBeanUtilsBean(LocaleConvertUtilsBean localeConvertUtils) {
124 this.localeConvertUtils = localeConvertUtils;
125 }
126
127
128
129 /***
130 * Gets the bean instance used for conversions
131 *
132 * @return the locale converter bean instance
133 */
134 public LocaleConvertUtilsBean getLocaleConvertUtils() {
135 return localeConvertUtils;
136 }
137
138 /***
139 * Gets the default Locale
140 * @return the default locale
141 */
142 public Locale getDefaultLocale() {
143
144 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 getLocaleConvertUtils().setDefaultLocale(locale);
156 }
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 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 getLocaleConvertUtils().setApplyLocalized(newApplyLocalized);
180 }
181
182
183
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 Object value = getPropertyUtils().getIndexedProperty(bean, name);
215 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 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 Object value = getPropertyUtils().getIndexedProperty(bean, name, index);
273 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 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 Object value = getPropertyUtils().getSimpleProperty(bean, name);
324 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 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 Object value = getPropertyUtils().getMappedProperty(bean, name, key);
380 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 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 Object value = getPropertyUtils().getMappedProperty(bean, name);
441 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 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 Object value = getPropertyUtils().getNestedProperty(bean, name);
504 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 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 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 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 setProperty(bean, name, value, null);
608 }
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
635 if (log.isTraceEnabled()) {
636 StringBuffer sb = new StringBuffer(" setProperty(");
637 sb.append(bean);
638 sb.append(", ");
639 sb.append(name);
640 sb.append(", ");
641 if (value == null) {
642 sb.append("<NULL>");
643 }
644 else if (value instanceof String) {
645 sb.append((String) value);
646 }
647 else if (value instanceof String[]) {
648 String[] values = (String[]) value;
649 sb.append('[');
650 for (int i = 0; i < values.length; i++) {
651 if (i > 0) {
652 sb.append(',');
653 }
654 sb.append(values[i]);
655 }
656 sb.append(']');
657 }
658 else {
659 sb.append(value.toString());
660 }
661 sb.append(')');
662 log.trace(sb.toString());
663 }
664
665
666 Object target = bean;
667 Resolver resolver = getPropertyUtils().getResolver();
668 while (resolver.hasNested(name)) {
669 try {
670 target = getPropertyUtils().getProperty(target, resolver.next(name));
671 name = resolver.remove(name);
672 } catch (NoSuchMethodException e) {
673 return;
674 }
675 }
676 if (log.isTraceEnabled()) {
677 log.trace(" Target bean = " + target);
678 log.trace(" Target name = " + name);
679 }
680
681
682 String propName = resolver.getProperty(name);
683 int index = resolver.getIndex(name);
684 String key = resolver.getKey(name);
685
686 Class type = definePropertyType(target, name, propName);
687 if (type != null) {
688 Object newValue = convert(type, index, value, pattern);
689 invokeSetter(target, propName, key, index, newValue);
690 }
691 }
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 Class type = null;
710
711 if (target instanceof DynaBean) {
712 DynaClass dynaClass = ((DynaBean) target).getDynaClass();
713 DynaProperty dynaProperty = dynaClass.getDynaProperty(propName);
714 if (dynaProperty == null) {
715 return null;
716 }
717 type = dynaProperty.getType();
718 }
719 else {
720 PropertyDescriptor descriptor = null;
721 try {
722 descriptor =
723 getPropertyUtils().getPropertyDescriptor(target, name);
724 if (descriptor == null) {
725 return null;
726 }
727 }
728 catch (NoSuchMethodException e) {
729 return null;
730 }
731 if (descriptor instanceof MappedPropertyDescriptor) {
732 type = ((MappedPropertyDescriptor) descriptor).
733 getMappedPropertyType();
734 }
735 else if (descriptor instanceof IndexedPropertyDescriptor) {
736 type = ((IndexedPropertyDescriptor) descriptor).
737 getIndexedPropertyType();
738 }
739 else {
740 type = descriptor.getPropertyType();
741 }
742 }
743 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 if (log.isTraceEnabled()) {
759 log.trace("Converting value '" + value + "' to type:" + type);
760 }
761
762 Object newValue = null;
763
764 if (type.isArray() && (index < 0)) {
765 if (value instanceof String) {
766 String[] values = new String[1];
767 values[0] = (String) value;
768 newValue = getLocaleConvertUtils().convert(values, type, pattern);
769 }
770 else if (value instanceof String[]) {
771 newValue = getLocaleConvertUtils().convert((String[]) value, type, pattern);
772 }
773 else {
774 newValue = value;
775 }
776 }
777 else if (type.isArray()) {
778 if (value instanceof String) {
779 newValue = getLocaleConvertUtils().convert((String) value,
780 type.getComponentType(), pattern);
781 }
782 else if (value instanceof String[]) {
783 newValue = getLocaleConvertUtils().convert(((String[]) value)[0],
784 type.getComponentType(), pattern);
785 }
786 else {
787 newValue = value;
788 }
789 }
790 else {
791 if (value instanceof String) {
792 newValue = getLocaleConvertUtils().convert((String) value, type, pattern);
793 }
794 else if (value instanceof String[]) {
795 newValue = getLocaleConvertUtils().convert(((String[]) value)[0],
796 type, pattern);
797 }
798 else {
799 newValue = value;
800 }
801 }
802 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 Object newValue = null;
816
817 if (type.isArray() && (index < 0)) {
818 if (value instanceof String) {
819 String[] values = new String[1];
820 values[0] = (String) value;
821 newValue = ConvertUtils.convert(values, type);
822 }
823 else if (value instanceof String[]) {
824 newValue = ConvertUtils.convert((String[]) value, type);
825 }
826 else {
827 newValue = value;
828 }
829 }
830 else if (type.isArray()) {
831 if (value instanceof String) {
832 newValue = ConvertUtils.convert((String) value,
833 type.getComponentType());
834 }
835 else if (value instanceof String[]) {
836 newValue = ConvertUtils.convert(((String[]) value)[0],
837 type.getComponentType());
838 }
839 else {
840 newValue = value;
841 }
842 }
843 else {
844 if (value instanceof String) {
845 newValue = ConvertUtils.convert((String) value, type);
846 }
847 else if (value instanceof String[]) {
848 newValue = ConvertUtils.convert(((String[]) value)[0],
849 type);
850 }
851 else {
852 newValue = value;
853 }
854 }
855 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 if (index >= 0) {
877 getPropertyUtils().setIndexedProperty(target, propName,
878 index, newValue);
879 }
880 else if (key != null) {
881 getPropertyUtils().setMappedProperty(target, propName,
882 key, newValue);
883 }
884 else {
885 getPropertyUtils().setProperty(target, propName, newValue);
886 }
887 }
888 catch (NoSuchMethodException e) {
889 throw new InvocationTargetException
890 (e, "Cannot set " + propName);
891 }
892 }
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
913 Object target = bean;
914 Resolver resolver = getPropertyUtils().getResolver();
915 while (resolver.hasNested(name)) {
916 try {
917 target = getPropertyUtils().getProperty(target, resolver.next(name));
918 name = resolver.remove(name);
919 } catch (NoSuchMethodException e) {
920 return null;
921 }
922 }
923 if (log.isTraceEnabled()) {
924 log.trace(" Target bean = " + target);
925 log.trace(" Target name = " + name);
926 }
927
928
929 String propName = resolver.getProperty(name);
930 int index = resolver.getIndex(name);
931 String key = resolver.getKey(name);
932
933 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 private int index = -1;
944 private String name;
945 private String propName;
946 private String key;
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 public Descriptor(Object target, String name, String propName, String key, int index) {
959
960 setTarget(target);
961 setName(name);
962 setPropName(propName);
963 setKey(key);
964 setIndex(index);
965 }
966
967 /***
968 * Return the target bean.
969 *
970 * @return The descriptors target bean
971 */
972 public Object getTarget() {
973 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 this.target = target;
983 }
984
985 /***
986 * Return the mapped property key.
987 *
988 * @return the mapped property key (if any)
989 */
990 public String getKey() {
991 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 this.key = key;
1001 }
1002
1003 /***
1004 * Return indexed property index.
1005 *
1006 * @return indexed property index (if any)
1007 */
1008 public int getIndex() {
1009 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 this.index = index;
1019 }
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 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 this.name = name;
1037 }
1038
1039 /***
1040 * Return the property name.
1041 *
1042 * @return The property name
1043 */
1044 public String getPropName() {
1045 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 this.propName = propName;
1055 }
1056 }
1057 }
1058
1059