View Javadoc
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    *      https://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.beanutils2;
19  
20  import java.lang.reflect.InvocationTargetException;
21  import java.util.Map;
22  
23  import org.apache.commons.collections4.map.ConcurrentReferenceHashMap;
24  
25  /**
26   * <p>
27   * Utility methods for populating JavaBeans properties via reflection.
28   * </p>
29   *
30   * <p>
31   * The implementations are provided by {@link BeanUtilsBean}. These static utility methods use the default instance. More sophisticated behavior can be provided
32   * by using a {@code BeanUtilsBean} instance.
33   * </p>
34   *
35   * @see BeanUtilsBean
36   */
37  public final class BeanUtils {
38  
39      /** An empty class array */
40      static final Class<?>[] EMPTY_CLASS_ARRAY = {};
41  
42      /** An empty object array */
43      static final Object[] EMPTY_OBJECT_ARRAY = {};
44  
45      /**
46       * <p>
47       * Clones a bean based on the available property getters and setters, even if the bean class itself does not implement Cloneable.
48       * </p>
49       *
50       * <p>
51       * For more details see {@code BeanUtilsBean}.
52       * </p>
53       *
54       * @param bean Bean to be cloned
55       * @return the cloned bean
56       * @throws IllegalAccessException    if the caller does not have access to the property accessor method
57       * @throws InstantiationException    if a new instance of the bean's class cannot be instantiated
58       * @throws InvocationTargetException if the property accessor method throws an exception
59       * @throws NoSuchMethodException     if an accessor method for this property cannot be found
60       * @see BeanUtilsBean#cloneBean
61       */
62      public static Object cloneBean(final Object bean) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
63          return BeanUtilsBean.getInstance().cloneBean(bean);
64      }
65  
66      /**
67       * <p>
68       * Copies property values from the origin bean to the destination bean for all cases where the property names are the same.
69       * </p>
70       *
71       * <p>
72       * For more details see {@code BeanUtilsBean}.
73       * </p>
74       *
75       * @param dest Destination bean whose properties are modified
76       * @param orig Origin bean whose properties are retrieved
77       * @throws IllegalAccessException    if the caller does not have access to the property accessor method
78       * @throws IllegalArgumentException  if the {@code dest} or {@code orig</code> argument is null or if the <code>dest} property type is different from the
79       *                                   source type and the relevant converter has not been registered.
80       * @throws InvocationTargetException if the property accessor method throws an exception
81       * @see BeanUtilsBean#copyProperties
82       */
83      public static void copyProperties(final Object dest, final Object orig) throws IllegalAccessException, InvocationTargetException {
84          BeanUtilsBean.getInstance().copyProperties(dest, orig);
85      }
86  
87      /**
88       * <p>
89       * Copy the specified property value to the specified destination bean, performing any type conversion that is required.
90       * </p>
91       *
92       * <p>
93       * For more details see {@code BeanUtilsBean}.
94       * </p>
95       *
96       * @param bean  Bean on which setting is to be performed
97       * @param name  Property name (can be nested/indexed/mapped/combo)
98       * @param value Value to be set
99       * @throws IllegalAccessException    if the caller does not have access to the property accessor method
100      * @throws InvocationTargetException if the property accessor method throws an exception
101      * @see BeanUtilsBean#copyProperty
102      */
103     public static void copyProperty(final Object bean, final String name, final Object value) throws IllegalAccessException, InvocationTargetException {
104         BeanUtilsBean.getInstance().copyProperty(bean, name, value);
105     }
106 
107     /**
108      * Creates a cache.
109      *
110      * @param <K> the key type of the cache
111      * @param <V> the value type of the cache
112      * @return a new cache
113      * @since 1.8.0
114      */
115     public static <K, V> Map<K, V> createCache() {
116         return ConcurrentReferenceHashMap.<K, V>builder().get();
117         // return new ConcurrentHashMap<>();
118     }
119 
120     /**
121      * <p>
122      * Return the entire set of properties for which the specified bean provides a read method.
123      * </p>
124      *
125      * <p>
126      * For more details see {@code BeanUtilsBean}.
127      * </p>
128      *
129      * @param bean Bean whose properties are to be extracted
130      * @return Map of property descriptors
131      * @throws IllegalAccessException    if the caller does not have access to the property accessor method
132      * @throws InvocationTargetException if the property accessor method throws an exception
133      * @throws NoSuchMethodException     if an accessor method for this property cannot be found
134      * @see BeanUtilsBean#describe
135      */
136     public static Map<String, String> describe(final Object bean) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
137         return BeanUtilsBean.getInstance().describe(bean);
138     }
139 
140     /**
141      * <p>
142      * Return the value of the specified array property of the specified bean, as a String array.
143      * </p>
144      *
145      * <p>
146      * For more details see {@code BeanUtilsBean}.
147      * </p>
148      *
149      * @param bean Bean whose property is to be extracted
150      * @param name Name of the property to be extracted
151      * @return The array property value
152      * @throws IllegalAccessException    if the caller does not have access to the property accessor method
153      * @throws InvocationTargetException if the property accessor method throws an exception
154      * @throws NoSuchMethodException     if an accessor method for this property cannot be found
155      * @see BeanUtilsBean#getArrayProperty
156      */
157     public static String[] getArrayProperty(final Object bean, final String name)
158             throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
159         return BeanUtilsBean.getInstance().getArrayProperty(bean, name);
160     }
161 
162     /**
163      * <p>
164      * Return the value of the specified indexed property of the specified bean, as a String.
165      * </p>
166      *
167      * <p>
168      * For more details see {@code BeanUtilsBean}.
169      * </p>
170      *
171      * @param bean Bean whose property is to be extracted
172      * @param name {@code propertyname[index]} of the property value to be extracted
173      * @return The indexed property's value, converted to a String
174      * @throws IllegalAccessException    if the caller does not have access to the property accessor method
175      * @throws InvocationTargetException if the property accessor method throws an exception
176      * @throws NoSuchMethodException     if an accessor method for this property cannot be found
177      * @see BeanUtilsBean#getIndexedProperty(Object, String)
178      */
179     public static String getIndexedProperty(final Object bean, final String name)
180             throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
181         return BeanUtilsBean.getInstance().getIndexedProperty(bean, name);
182 
183     }
184 
185     /**
186      * Gets the value of the specified indexed property of the specified bean, as a String. The index is specified as a method parameter and must *not* be
187      * included in the property name expression
188      *
189      * <p>
190      * For more details see {@code BeanUtilsBean}.
191      * </p>
192      *
193      * @param bean  Bean whose property is to be extracted
194      * @param name  Simple property name of the property value to be extracted
195      * @param index Index of the property value to be extracted
196      * @return The indexed property's value, converted to a String
197      * @throws IllegalAccessException    if the caller does not have access to the property accessor method
198      * @throws InvocationTargetException if the property accessor method throws an exception
199      * @throws NoSuchMethodException     if an accessor method for this property cannot be found
200      * @see BeanUtilsBean#getIndexedProperty(Object, String, int)
201      */
202     public static String getIndexedProperty(final Object bean, final String name, final int index)
203             throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
204         return BeanUtilsBean.getInstance().getIndexedProperty(bean, name, index);
205 
206     }
207 
208     /**
209      * <p>
210      * Return the value of the specified indexed property of the specified bean, as a String.
211      * </p>
212      *
213      * <p>
214      * For more details see {@code BeanUtilsBean}.
215      * </p>
216      *
217      * @param bean Bean whose property is to be extracted
218      * @param name {@code propertyname(index)} of the property value to be extracted
219      * @return The mapped property's value, converted to a String
220      * @throws IllegalAccessException    if the caller does not have access to the property accessor method
221      * @throws InvocationTargetException if the property accessor method throws an exception
222      * @throws NoSuchMethodException     if an accessor method for this property cannot be found
223      * @see BeanUtilsBean#getMappedProperty(Object, String)
224      */
225     public static String getMappedProperty(final Object bean, final String name)
226             throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
227         return BeanUtilsBean.getInstance().getMappedProperty(bean, name);
228 
229     }
230 
231     /**
232      * <p>
233      * Return the value of the specified mapped property of the specified bean, as a String.
234      * </p>
235      *
236      * <p>
237      * For more details see {@code BeanUtilsBean}.
238      * </p>
239      *
240      * @param bean Bean whose property is to be extracted
241      * @param name Simple property name of the property value to be extracted
242      * @param key  Lookup key of the property value to be extracted
243      * @return The mapped property's value, converted to a String
244      * @throws IllegalAccessException    if the caller does not have access to the property accessor method
245      * @throws InvocationTargetException if the property accessor method throws an exception
246      * @throws NoSuchMethodException     if an accessor method for this property cannot be found
247      * @see BeanUtilsBean#getMappedProperty(Object, String, String)
248      */
249     public static String getMappedProperty(final Object bean, final String name, final String key)
250             throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
251         return BeanUtilsBean.getInstance().getMappedProperty(bean, name, key);
252 
253     }
254 
255     /**
256      * <p>
257      * Return the value of the (possibly nested) property of the specified name, for the specified bean, as a String.
258      * </p>
259      *
260      * <p>
261      * For more details see {@code BeanUtilsBean}.
262      * </p>
263      *
264      * @param bean Bean whose property is to be extracted
265      * @param name Possibly nested name of the property to be extracted
266      * @return The nested property's value, converted to a String
267      * @throws IllegalAccessException    if the caller does not have access to the property accessor method
268      * @throws IllegalArgumentException  if a nested reference to a property returns null
269      * @throws InvocationTargetException if the property accessor method throws an exception
270      * @throws NoSuchMethodException     if an accessor method for this property cannot be found
271      * @see BeanUtilsBean#getNestedProperty
272      */
273     public static String getNestedProperty(final Object bean, final String name)
274             throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
275         return BeanUtilsBean.getInstance().getNestedProperty(bean, name);
276 
277     }
278 
279     /**
280      * <p>
281      * Return the value of the specified property of the specified bean, no matter which property reference format is used, as a String.
282      * </p>
283      *
284      * <p>
285      * For more details see {@code BeanUtilsBean}.
286      * </p>
287      *
288      * @param bean Bean whose property is to be extracted
289      * @param name Possibly indexed and/or nested name of the property to be extracted
290      * @return The property's value, converted to a String
291      * @throws IllegalAccessException    if the caller does not have access to the property accessor method
292      * @throws InvocationTargetException if the property accessor method throws an exception
293      * @throws NoSuchMethodException     if an accessor method for this property cannot be found
294      * @see BeanUtilsBean#getProperty
295      */
296     public static String getProperty(final Object bean, final String name) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
297         return BeanUtilsBean.getInstance().getProperty(bean, name);
298 
299     }
300 
301     /**
302      * <p>
303      * Return the value of the specified simple property of the specified bean, converted to a String.
304      * </p>
305      *
306      * <p>
307      * For more details see {@code BeanUtilsBean}.
308      * </p>
309      *
310      * @param bean Bean whose property is to be extracted
311      * @param name Name of the property to be extracted
312      * @return The property's value, converted to a String
313      * @throws IllegalAccessException    if the caller does not have access to the property accessor method
314      * @throws InvocationTargetException if the property accessor method throws an exception
315      * @throws NoSuchMethodException     if an accessor method for this property cannot be found
316      * @see BeanUtilsBean#getSimpleProperty
317      */
318     public static String getSimpleProperty(final Object bean, final String name)
319             throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
320         return BeanUtilsBean.getInstance().getSimpleProperty(bean, name);
321 
322     }
323 
324     /**
325      * <p>
326      * Populate the JavaBeans properties of the specified bean, based on the specified name/value pairs.
327      * </p>
328      *
329      * <p>
330      * For more details see {@code BeanUtilsBean}.
331      * </p>
332      *
333      * @param bean       JavaBean whose properties are being populated
334      * @param properties Map keyed by property name, with the corresponding (String or String[]) value(s) to be set
335      * @throws IllegalAccessException    if the caller does not have access to the property accessor method
336      * @throws InvocationTargetException if the property accessor method throws an exception
337      * @see BeanUtilsBean#populate
338      */
339     public static void populate(final Object bean, final Map<String, ? extends Object> properties) throws IllegalAccessException, InvocationTargetException {
340         BeanUtilsBean.getInstance().populate(bean, properties);
341     }
342 
343     /**
344      * <p>
345      * Set the specified property value, performing type conversions as required to conform to the type of the destination property.
346      * </p>
347      *
348      * <p>
349      * For more details see {@code BeanUtilsBean}.
350      * </p>
351      *
352      * @param bean  Bean on which setting is to be performed
353      * @param name  Property name (can be nested/indexed/mapped/combo)
354      * @param value Value to be set
355      * @throws IllegalAccessException    if the caller does not have access to the property accessor method
356      * @throws InvocationTargetException if the property accessor method throws an exception
357      * @see BeanUtilsBean#setProperty
358      */
359     public static void setProperty(final Object bean, final String name, final Object value) throws IllegalAccessException, InvocationTargetException {
360         BeanUtilsBean.getInstance().setProperty(bean, name, value);
361     }
362 
363     private BeanUtils() {
364         // empty
365     }
366 }