package org.raidenjpa.reflection; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.raidenjpa.util.FixMe; public class ReflectionUtil { public static void setBeanField(Object entidade, String key, Object value) { try { String methodName = toMethodName("set", key); Method method = null; if (value != null) { method = ReflectionUtil.getMethod(entidade, methodName, value.getClass()); } if (method == null) { Class<?> type = ReflectionUtil.getBeanFieldType(entidade, key); method = ReflectionUtil.getMethod(entidade, methodName, type); } if (method == null && value == null) { throw new RuntimeException("impossible to guess type for field: " + key); } Class<?> paramType = method.getParameterTypes()[0]; if (value != null && !paramType.isAssignableFrom(value.getClass())) { throw new RuntimeException("this method " + method + " can not be invoked with: " + value.getClass().getName()); } method.invoke(entidade, new Object[] { value }); } catch (SecurityException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } } public static String toMethodName(String pre, String key) { char c = Character.toUpperCase(key.charAt(0)); return "" + pre + c + key.substring(1); } public static List<String> getBeanFields(Object obj) { Class<?> clazz = obj.getClass(); return getBeanFieldsOfClass(clazz); } public static List<String> getBeanFieldsOfClass(Class<?> clazz) { List<String> ret = new ArrayList<String>(); Method[] methods = clazz.getMethods(); for (Method method : methods) { if (method.getParameterTypes().length != 0) { continue; } String name = method.getName(); if (!name.startsWith("get") || name.equals("getClass")) { continue; } Class<?> type = method.getReturnType(); String fieldName = toBeanFieldName(name); if (getMethodOfClass(clazz, toMethodName("set", fieldName), new Class[] { type }) != null) { ret.add(fieldName); } } return ret; } private static String toBeanFieldName(String name) { char c = Character.toLowerCase(name.charAt(3)); return "" + c + name.substring(4); } @FixMe("Find element with @Id") public static Object getBeanId(Object obj) { return getBeanField(obj, "id"); } public static Object getBeanField(Object obj, List<String> path) { for (int i = 1; i < path.size(); i++) { obj = ReflectionUtil.getBeanField(obj, path.get(i)); } return obj; } public static Object getBeanField(Object obj, String fieldName) { try { String methodName = toMethodName("get", fieldName); Method method = getMethod(obj, methodName); if (method == null) { throw new RuntimeException("Class " + obj.getClass().getName() + " doesnt has field " + fieldName); } return method.invoke(obj); } catch (SecurityException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } } public static Method getMethod(Object obj, String methodName, Class<?>... types) { Class<?> clazz = obj.getClass(); return getMethodOfClass(clazz, methodName, types); } public static Method getMethodOfClass(Class<?> clazz, String methodName, Class<?>... types) { try { return clazz.getMethod(methodName, types); } catch (NoSuchMethodException e) { return null; } catch (SecurityException e) { throw new RuntimeException(e); } } public static boolean isBeanFieldAnnotated(Object obj, String fieldName, Class<? extends Annotation> annotation) { Class<?> clazz = obj.getClass(); return isBeanFieldAnnotated(clazz, fieldName, annotation); } public static boolean isBeanFieldAnnotated(Class<?> clazz, String fieldName, Class<? extends Annotation> annotation) { Method method = getMethodOfClass(clazz, toMethodName("get", fieldName)); if (method == null) { return false; } return method.isAnnotationPresent(annotation); } public static Class<?> getBeanFieldType(Object obj, String fieldName) { return getBeanFieldTypeOfClass(obj.getClass(), fieldName); } public static Class<?> getBeanFieldTypeOfClass(Class<?> clazz, String fieldName) { Method method = getMethodOfClass(clazz, toMethodName("get", fieldName)); if (method == null) { throw new RuntimeException("Bean field '" + fieldName + "' not found in " + clazz); } return method.getReturnType(); } public static void checkBeanFieldAnnotated(Class<?> clazz, String fieldName, Class<? extends Annotation> annotation) { if (!ReflectionUtil.isBeanFieldAnnotated(clazz, fieldName, annotation)) { throw new IllegalStateException("Requires " + annotation + " on " + clazz.getName() + "." + fieldName); } } public static List<Method> getMethods(Class<?> clazz, int modifier) { Method[] methods = clazz.getMethods(); List<Method> ret = new ArrayList<Method>(); for (Method method : methods) { int result = method.getModifiers() & modifier; if (result > 0) { ret.add(method); } } return ret; } public static List<Method> getMethods(Class<?> clazz) { return getMethods(clazz, 0xFFFFFFFF); } public static List<Annotation> getAnnotation(Method method) { Annotation[] annotations = method.getAnnotations(); if (annotations == null || annotations.length == 0) { return Collections.emptyList(); } return Arrays.asList(annotations); } public static List<Field> getFields(Class<?> clazz) { Field[] fields = clazz.getDeclaredFields(); List<Field> ret = new ArrayList<Field>(Arrays.asList(fields)); Class<?> superclass = clazz.getSuperclass(); if (superclass != null) { ret.addAll(getFields(superclass)); } return ret; } public static Field getField(Class<?> clazz, String fieldName) { for(Field field : getFields(clazz)) { if (field.getName().equals(fieldName)) { return field; } } throw new RuntimeException("There is no field called '" + fieldName + "' in the class " + clazz.getName()); } public static List<Method> getDeclaringMethods(Class<?> clazz) { return getDeclaringMethods(clazz, 0xFFFFFFFF); } public static List<Method> getDeclaringMethods(Class<?> clazz, int modifier) { Method[] methods = clazz.getDeclaredMethods(); List<Method> ret = new ArrayList<Method>(); for (Method method : methods) { int result = method.getModifiers() & modifier; if (result > 0) { ret.add(method); } } return ret; } public static Object invoke(Object o, Method m, Object... args) { try { return m.invoke(o, args); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } } @SuppressWarnings("unchecked") public static Method getMethodByName(Class<?> clazz, String methodName) { Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { boolean equals = method.getName().equals(methodName); if (equals) { return method; } } Class<Object> superclass = (Class<Object>) clazz.getSuperclass(); if (superclass == null) { return null; } return getMethodByName(superclass, methodName); } public static boolean hasBeanField(Object obj, String fieldName) { try { String methodName = toMethodName("get", fieldName); Method method = getMethod(obj, methodName); return method != null; } catch (SecurityException e) { throw new RuntimeException(e); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } } public static Object newInstance(String className) { Class<?> clazz = clazz(className); return newInstance(clazz); } public static Class<?> clazz(String className) { try { return Class.forName(className); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public static String debug(Class<?> clazz) { if (clazz == null) { return "null"; } StringBuilder ret = new StringBuilder(); ret.append("[").append(clazz.getName()); String url = debugLocation(clazz); if (url != null) { ret.append(" ").append(url); } ret.append(']'); return ret.toString(); } private static String debugLocation(Class<?> clazz) { try { return clazz.getProtectionDomain().getCodeSource().getLocation().toString(); } catch (Exception e) { return "null"; } } public static Object invokeStatic(Class<?> clazz, String methodName, Class<?>[] types, Object[] args) { try { Method method = ReflectionUtil.getMethodOfClass(clazz, methodName, types); return method.invoke(null, args[0]); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } } public static <T> T newInstance(Class<T> clazz) { try { return clazz.newInstance(); } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } public static List<Annotation> getBeanFieldsAnnotations(Class<?> clazz, String fieldName) { Method method = getMethodOfClass(clazz, toMethodName("get", fieldName)); return getAnnotation(method); } public static Class<?> forName(String className) { try { return Class.forName(className); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public static Class<?> getBeanFieldCollectionType(Object object, String field) { return getBeanFieldCollectionTypeOfClass(object.getClass(), field); } public static Class<?> getBeanFieldCollectionTypeOfClass(Class<?> clazz, String fieldName) { try { String methodName = toMethodName("get", fieldName); Method method = getMethodOfClass(clazz, methodName); Type listType = method.getGenericReturnType(); ParameterizedType parameterizedType = (ParameterizedType) listType; return (Class<?>) parameterizedType.getActualTypeArguments()[0]; } catch (SecurityException e) { throw new RuntimeException(e); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } } public static boolean checkClassAnnotated(Class<?> clazz, Class<? extends Annotation> annotation) { return clazz.isAnnotationPresent(annotation); } }