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 }