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);
}
}