/** * Copyright 2004-2016 Riccardo Solmi. All rights reserved. * This file is part of the Whole Platform. * * The Whole Platform is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Whole Platform is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>. */ package org.whole.lang.util; import java.beans.BeanInfo; import java.beans.IndexedPropertyDescriptor; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.Method; import java.lang.reflect.TypeVariable; import java.util.Collection; import java.util.HashMap; import java.util.Map; /** * @author Riccardo Solmi, Enrico Persiani */ public class ReflectiveUtils { @SuppressWarnings("unchecked") public static final <T> T reflectiveClone(T object) { try { Method cloneMethod = object.getClass().getMethod("clone", new Class<?>[] {}); return (T) cloneMethod.invoke(object, new Object[] {}); } catch (Exception e) { throw new IllegalArgumentException("Clone not supported in bean", e); } } public static final Map<String, PropertyDescriptor> getBeanPropertyMap(Class<?> bean) { Map<String, PropertyDescriptor> propertyMap = new HashMap<String, PropertyDescriptor>(); try { BeanInfo beanInfo = Introspector.getBeanInfo(bean); for (PropertyDescriptor property : beanInfo.getPropertyDescriptors()) { propertyMap.put(property.getName(), property); } return propertyMap; } catch (IntrospectionException e) { throw new RuntimeException(e); } } public static final Class<?> propertyType(Map<String, PropertyDescriptor> propertyMap, String name) { return propertyMap.get(name).getPropertyType(); } public static final Class<?> propertyIndexedType(Map<String, PropertyDescriptor> propertyMap, String name) { return ((IndexedPropertyDescriptor)propertyMap.get(name)).getIndexedPropertyType(); } public static final boolean hasProperty( Map<String, PropertyDescriptor> propertyMap, String name) { PropertyDescriptor property = propertyMap.get(name); return property != null; } public static final boolean hasPrimitiveProperty(Map<String, PropertyDescriptor> propertyMap, String name) { PropertyDescriptor property = propertyMap.get(name); return property != null && property.getPropertyType().isPrimitive(); } public static final boolean hasReferenceProperty(Map<String, PropertyDescriptor> propertyMap, String name) { PropertyDescriptor property = propertyMap.get(name); return property != null && !property.getPropertyType().isPrimitive(); } public static final boolean hasIndexedProperty(Map<String, PropertyDescriptor> propertyMap, String name) { PropertyDescriptor property = propertyMap.get(name); return property != null && property instanceof IndexedPropertyDescriptor; } public static final <T> boolean hasCollectionProperty(Map<String, PropertyDescriptor> propertyMap, String name) { PropertyDescriptor property = propertyMap.get(name); return property != null && Collection.class.isAssignableFrom(property.getPropertyType()); } public static final TypeVariable<?>[] collectionPropertyTypeVariables(Map<String, PropertyDescriptor> propertyMap, String name) { PropertyDescriptor property = propertyMap.get(name); return property.getPropertyType().getTypeParameters(); } public static final Object getProperty(Map<String, PropertyDescriptor> propertyMap, Object bean, String name) { PropertyDescriptor property = propertyMap.get(name); try { Method readMethod = property.getReadMethod(); return readMethod.invoke(bean, new Object[] {}); } catch (Exception e) { throw new IllegalArgumentException("No such property: \"" + name + "\"", e); } } public static final void setProperty(Map<String, PropertyDescriptor> propertyMap, Object bean, String name, Object value) { PropertyDescriptor property = propertyMap.get(name); try { Method writeMethod = property.getWriteMethod(); writeMethod.invoke(bean, new Object[] {value}); } catch (Exception e) { throw new IllegalArgumentException("No such property: \"" + name + "\"", e); } } public static final <T> void addIndexedProperty(Map<String, PropertyDescriptor> propertyMap, Object bean, String name, T value) { Object array = getProperty(propertyMap, bean, name); if (array == null) throw new IllegalArgumentException("No such property: \"" + name + "\""); int length = Array.getLength(array); Object newArray = Array.newInstance(array.getClass().getComponentType(), length + 1); System.arraycopy(array, 0, newArray, 0, length); Array.set(newArray, length, value); setProperty(propertyMap, bean, name, newArray); } @SuppressWarnings("unchecked") public static final boolean addCollectionProperty(Map<String, PropertyDescriptor> propertyMap, Object bean, String name, Object value) { Collection<Object> collection = (Collection<Object>) getProperty(propertyMap, bean, name); return collection != null ? collection.add(value) : false; } }