/** * */ package org.minnal.autopojo.util; import java.beans.PropertyDescriptor; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Field; 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.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.reflect.FieldUtils; import com.google.common.reflect.TypeToken; /** * @author ganeshs * */ public class PropertyUtil { /** * 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 ClassUtils.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); } 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; } public static boolean isCollectionProperty(Class<?> clazz, boolean includeMaps) { return Collection.class.isAssignableFrom(clazz) || (includeMaps && isMapProperty(clazz)); } 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; } public static boolean isMapProperty(Class<?> clazz) { return Map.class.isAssignableFrom(clazz); } public static Class<?> getRawType(Type genericType) { if (genericType instanceof ParameterizedType) { ParameterizedType ptype = (ParameterizedType) genericType; return (Class<?>) ptype.getRawType(); } return (Class<?>) genericType; } public static Type[] getTypeArguments(Type genericType) { if (genericType instanceof ParameterizedType) { ParameterizedType ptype = (ParameterizedType) genericType; return ptype.getActualTypeArguments(); } return null; } public static Class<?> getMapKeyType(Type type) { return TypeToken.of(type).resolveType(getMapGenericTypes(type)[0]).getRawType(); } public static Class<?> getMapValueType(Type type) { return TypeToken.of(type).resolveType(getMapGenericTypes(type)[1]).getRawType(); } private static Type[] getMapGenericTypes(Type type) { try { return Map.class.getMethod("put", Object.class, Object.class).getGenericParameterTypes(); } catch (Exception e) { // TODO logo exception and ignore } return new Type[]{Object.class, Object.class}; } public static Class<?> getCollectionElementType(Type type) { Class<?> rawType = getRawType(type); 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 getMapValueType(type); } } catch (Exception e) { // TODO logo exception and ignore } return Object.class; } public static List<Annotation> getAnnotations(PropertyDescriptor descriptor) { List<Annotation> annotations = new ArrayList<Annotation>(); annotations.addAll(getMethodAnnotations(descriptor)); annotations.addAll(getFieldAnnotations(descriptor)); return annotations; } public static List<Annotation> getMethodAnnotations(PropertyDescriptor descriptor) { List<Annotation> annotations = new ArrayList<Annotation>(); Method method = descriptor.getReadMethod(); if (method == null || method.getDeclaringClass().equals(Object.class)) { return annotations; } annotations.addAll(Arrays.asList(method.getAnnotations())); return annotations; } public static List<Annotation> getFieldAnnotations(PropertyDescriptor descriptor) { List<Annotation> annotations = new ArrayList<Annotation>(); Method method = descriptor.getReadMethod(); if (method == null || method.getDeclaringClass().equals(Object.class)) { return annotations; } Field field = FieldUtils.getField(method.getDeclaringClass(), descriptor.getName(), true); if (field == null) { return annotations; } annotations.addAll(Arrays.asList(field.getAnnotations())); return annotations; } public static <T extends Annotation> T getAnnotation(PropertyDescriptor descriptor, Class<T> clazz) { return getAnnotation(descriptor, clazz, false); } public static <T extends Annotation> T getAnnotation(PropertyDescriptor descriptor, Class<T> clazz, boolean ignoreObjectClass) { Method method = descriptor.getReadMethod(); if (method == null || ignoreObjectClass && method.getDeclaringClass().equals(Object.class)) { return null; } Field field = FieldUtils.getField(method.getDeclaringClass(), descriptor.getName(), true); if (field == null) { return null; } if (field.isAnnotationPresent(clazz)) { return field.getAnnotation(clazz); } return method.getAnnotation(clazz); } public static boolean hasAnnotation(PropertyDescriptor descriptor, Class<? extends Annotation> clazz) { return hasAnnotation(descriptor, clazz, false); } public static boolean hasAnnotation(PropertyDescriptor descriptor, Class<? extends Annotation> clazz, boolean ignoreObjectClass) { return getAnnotation(descriptor, clazz) != null; } public static List<String> getEnumValues(PropertyDescriptor descriptor) { List<String> values = new ArrayList<String>(); try { Enum<?>[] enums = (Enum[])descriptor.getPropertyType().getMethod("values").invoke(null); for (Enum<?> enm : enums) { values.add(enm.name()); } } catch (Exception e) { // TODO Log exception and ignore } return values; } public static Type getGenericType(PropertyDescriptor descriptor) { Method method = descriptor.getReadMethod(); if (method == null) { method = descriptor.getWriteMethod(); } if (method == null) { return null; } return method.getGenericReturnType(); } public static Class<?> getType(PropertyDescriptor descriptor) { Type type = getGenericType(descriptor); if (type instanceof ParameterizedType) { if (isCollectionProperty(type, true)) { return getCollectionElementType(type); } return (Class<?>)((ParameterizedType)type).getRawType(); } return (Class<?>) type; } public static List<PropertyDescriptor> getPopertiesWithAnnotation(Class<?> clazz, Class<? extends Annotation> annotation) { List<PropertyDescriptor> descriptors = new ArrayList<PropertyDescriptor>(); for (PropertyDescriptor descriptor : PropertyUtils.getPropertyDescriptors(clazz)) { if (hasAnnotation(descriptor, annotation)) { descriptors.add(descriptor); } } return descriptors; } public static PropertyDescriptor getDescriptor(Class<?> clazz, String property) { for (PropertyDescriptor descriptor : PropertyUtils.getPropertyDescriptors(clazz)) { if (descriptor.getName().equals(property)) { return descriptor; } } return null; } public static boolean isPrimitive(Class<?> type) { return type.equals(int.class) || type.equals(long.class) || type.equals(char.class) || type.equals(byte.class) || type.equals(boolean.class) || type.equals(short.class) || type.equals(double.class) || type.equals(float.class); } public static boolean isPrimitive(PropertyDescriptor descriptor) { return isPrimitive(descriptor.getPropertyType()); } }