package br.com.geraldoferraz.testyourquery.util.reflection; import static java.lang.reflect.Modifier.isStatic; import static java.util.Arrays.asList; import java.lang.annotation.Annotation; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import net.vidageek.mirror.dsl.Mirror; import net.vidageek.mirror.list.dsl.Matcher; import net.vidageek.mirror.list.dsl.MirrorList; import br.com.geraldoferraz.testyourquery.annotations.Configurator; public class ClassReflector { private Mirror mirror = new Mirror(); private Class<?> clazz; public ClassReflector(Class<?> clazz) { this.clazz = clazz; } public Class<?> getJavaClass(){ return this.clazz; } public List<Field> getAnnotatedInstanceFields(Class<? extends Annotation> annotation) { List<Field> annotatedFields = getAnnotatedFields(annotation); annotatedFields = filterStaticFields(annotatedFields); return annotatedFields; } private List<Field> filterStaticFields(List<Field> annotatedFields) { return remove(annotatedFields,true); } public List<Field> getAnnotatedStaticFields(Class<? extends Annotation> annotation) { List<Field> annotatedFields = getAnnotatedFields(annotation); annotatedFields = filterNonStaticFields(annotatedFields); return annotatedFields; } private List<Field> filterNonStaticFields(List<Field> annotatedFields) { return remove(annotatedFields,false); } private List<Field> getAnnotatedFields(Class<? extends Annotation> annotation) { List<Field> annotatedFields = mirror.on(clazz).reflectAll().fields().matching((ClassReflector.<Field>annotedWith(annotation))); return annotatedFields; } public MirrorList<Method> getMethodsMatching(Matcher<Method> matcher) { return mirror.on(clazz).reflectAll().methods().matching(matcher); } public Object invokeStatic(Method method) { return mirror.on(clazz).invoke().method(method).withoutArgs(); } public MirrorList<Method> getMethodsAnnotedWith(Class<Configurator> annotation) { return mirror.on(clazz).reflectAll().methods().matching(ClassReflector.<Method>annotedWith(annotation)); } private static <T extends AccessibleObject> Matcher<T> annotedWith(final Class<? extends Annotation> annotation) { return new Matcher<T>() { public boolean accepts(T element) { return element.isAnnotationPresent(annotation); } }; } public Method getConfiguratorMethod() { MirrorList<Method> methodsList = getMethodsAnnotedWith(Configurator.class); verificaQueNaoExisteMaisDeUmConfigurator(methodsList); if(!methodsList.isEmpty()){ Method method = methodsList.get(0); verificaQueConfiguratorEhStatic(method); return method; } return null; } private void verificaQueConfiguratorEhStatic(Method method) { if(!isStatic(method.getModifiers())){ throw new RuntimeException("Configurator method must be static"); } } private void verificaQueNaoExisteMaisDeUmConfigurator(MirrorList<Method> methdoList) { if (methdoList.size() > 1) { throw new RuntimeException("There can be only one configurator method"); } } public static List<Field> getFieldsByType(Class<?> clazz, Object daoObject) throws IllegalAccessException { List<Field> tmp = new ArrayList<Field>(); tmp.addAll(asList(daoObject.getClass().getDeclaredFields())); Class<?> currerntSuper = daoObject.getClass().getSuperclass(); while (currerntSuper != null) { tmp.addAll(asList(currerntSuper.getDeclaredFields())); currerntSuper = currerntSuper.getSuperclass(); } List<Field> retorno = new ArrayList<Field>(); for (Field field : tmp) { if (field.getType().isAssignableFrom(clazz)) { retorno.add(field); } } return retorno; } public static void injectOn(Field field, Object instance, Object value) throws IllegalArgumentException, IllegalAccessException { field.setAccessible(true); field.set(instance, value); } public static Object newInstanceOf(Field field) throws InstantiationException, IllegalAccessException { return field.getType().newInstance(); } public static void injectStaticOn(Field field, Class<?> clazz, Object value) { new Mirror().on(clazz).set().field(field).withValue(value); } private List<Field> remove(List<Field> annotatedFields, boolean b) { List<Field> retorno = new ArrayList<Field>(); for (Field field : annotatedFields) { if(b){ if(!isStatic(field.getModifiers())){ retorno.add(field); } }else{ if(isStatic(field.getModifiers())){ retorno.add(field); } } } return retorno; } public Object createInstance() throws InstantiationException, IllegalAccessException { return clazz.newInstance(); } }