/**
*
*/
package org.activejpa.util;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.URL;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import org.activejpa.ActiveJpaException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.reflect.TypeToken;
/**
* @author ganeshs
*
*/
public class PropertyUtil {
private static final Logger logger = LoggerFactory.getLogger(PropertyUtil.class);
/**
* Check if the given type represents a "simple" property:
* a primitive, a String or other CharSequence, a Number, a Date,
* a URI, a URL, a Locale, a Class, or a corresponding array.
* <p>Used to determine properties to check for a "simple" dependency-check.
* @param clazz the type to check
* @return whether the given type represents a "simple" property
* @see org.springframework.beans.factory.support.RootBeanDefinition#DEPENDENCY_CHECK_SIMPLE
* @see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#checkDependencies
*/
public static boolean isSimpleProperty(Class<?> clazz) {
return isSimpleValueType(clazz) || (clazz.isArray() && isSimpleValueType(clazz.getComponentType()));
}
/**
* Check if the given type represents a "simple" value type:
* a primitive, a String or other CharSequence, a Number, a Date,
* a URI, a URL, a Locale or a Class.
*
* @param clazz the type to check
* @return whether the given type represents a "simple" value type
*/
public static boolean isSimpleValueType(Class<?> clazz) {
return isPrimitiveOrWrapper(clazz) || clazz.isEnum() ||
CharSequence.class.isAssignableFrom(clazz) ||
Number.class.isAssignableFrom(clazz) ||
Date.class.isAssignableFrom(clazz) ||
clazz.equals(URI.class) || clazz.equals(URL.class) ||
clazz.equals(Locale.class) || clazz.equals(Class.class) ||
clazz.equals(Serializable.class) || clazz.equals(Timestamp.class);
}
/**
* Checks if the given type is a collection. If includeMaps is set, maps will be treated as collections
*
* @param type
* @param includeMaps
* @return
*/
public static boolean isCollectionProperty(Type type, boolean includeMaps) {
if (type instanceof Class) {
return isCollectionProperty((Class<?>)type, includeMaps);
}
if (type instanceof ParameterizedType) {
return isCollectionProperty((Class<?>)((ParameterizedType) type).getRawType(), includeMaps);
}
return false;
}
/**
* Checks if the given clazz is a collection. If includeMaps is set, maps will be treated as collections
*
* @param clazz
* @param includeMaps
* @return
*/
public static boolean isCollectionProperty(Class<?> clazz, boolean includeMaps) {
return Collection.class.isAssignableFrom(clazz) || (includeMaps && isMapProperty(clazz));
}
/**
* Checks if the given type is a map
*
* @param type
* @return
*/
public static boolean isMapProperty(Type type) {
if (type instanceof Class) {
return isMapProperty((Class<?>)type);
}
if (type instanceof ParameterizedType) {
return isMapProperty((Class<?>)((ParameterizedType) type).getRawType());
}
return false;
}
/**
* Checks if the given class is a map
*
* @param clazz
* @return
*/
public static boolean isMapProperty(Class<?> clazz) {
return Map.class.isAssignableFrom(clazz);
}
/**
* Returns the element type of the collection
*
* @param type
* @return
*/
public static Class<?> getCollectionElementType(Type type) {
if (! (type instanceof ParameterizedType)) {
return Object.class;
}
ParameterizedType ptype = (ParameterizedType) type;
Class<?> rawType = (Class<?>) ptype.getRawType();
try {
if (Collection.class.isAssignableFrom(rawType)) {
return TypeToken.of(type).resolveType(Collection.class.getMethod("add", Object.class).getGenericParameterTypes()[0]).getRawType();
}
if (Map.class.isAssignableFrom(rawType)) {
return TypeToken.of(type).resolveType(Map.class.getMethod("put", Object.class, Object.class).getGenericParameterTypes()[1]).getRawType();
}
} catch (Exception e) {
logger.warn("Failed while getting the collection element type", e);
}
return Object.class;
}
/**
* Returns the property value for the given property name from the bean
*
* @param bean
* @param name
* @return
*/
public static Object getProperty(Object bean, String name) {
try {
Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass("org.apache.commons.beanutils.PropertyUtils");
Method method = clazz.getMethod("getProperty", Object.class, String.class);
return method.invoke(null, bean, name);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof NoSuchMethodException) {
logger.debug("Getter doesn't exist for the property {} in the class {}", name, bean.getClass());
return null;
}
throw new ActiveJpaException("Failed while invoking the getter for the property " + name + " in the class " + bean.getClass(), e);
} catch (Exception e) {
throw new ActiveJpaException("Failed while invoking the getter for the property " + name + " in the class " + bean.getClass(), e);
}
}
/**
* Sets the value to the property on the bean
*
* @param bean
* @param name
* @param value
*/
public static void setProperty(Object bean, String name, Object value) {
try {
Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass("org.apache.commons.beanutils.BeanUtils");
Method method = clazz.getMethod("setProperty", Object.class, String.class, Object.class);
method.invoke(null, bean, name, value);
} catch (Exception e) {
throw new ActiveJpaException("Failed while setting the property", e);
}
}
public static Method getReadMethod(Object bean, String name) {
try {
Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass("org.apache.commons.beanutils.PropertyUtils");
Method method = clazz.getMethod("getPropertyDescriptor", Object.class, String.class);
Object descriptor = method.invoke(null, bean, name);
if (descriptor == null) {
throw new ActiveJpaException("Property descriptor not found for the field - " + name);
}
method = clazz.getMethod("getReadMethod", PropertyDescriptor.class);
return (Method) method.invoke(null, descriptor);
} catch (Exception e) {
throw new ActiveJpaException("Failed while getting the property descriptor", e);
}
}
/**
* Checks if the given class is primitive type or wrapper
*
* @param clazz
* @return
*/
public static Boolean isPrimitiveOrWrapper(Class<?> clazz) {
try {
Class<?> utils = Thread.currentThread().getContextClassLoader().loadClass("org.apache.commons.lang3.ClassUtils");
Method method = utils.getMethod("isPrimitiveOrWrapper", Class.class);
return (Boolean) method.invoke(null, clazz);
} catch (Exception e) {
throw new ActiveJpaException("Failed while getting the property descriptor", e);
}
}
}