r2058 - in trunk/nuiton-utils/src: main/java/org/nuiton/util test/java/org/nuiton/util
Author: tchemit Date: 2011-01-26 11:38:34 +0100 (Wed, 26 Jan 2011) New Revision: 2058 Url: http://nuiton.org/repositories/revision/nuiton-utils/2058 Log: Evolution #1235: Add new convinient methods in ReflectUtil Added: trunk/nuiton-utils/src/test/java/org/nuiton/util/ReflectUtilTest.java Modified: trunk/nuiton-utils/src/main/java/org/nuiton/util/ReflectUtil.java Modified: trunk/nuiton-utils/src/main/java/org/nuiton/util/ReflectUtil.java =================================================================== --- trunk/nuiton-utils/src/main/java/org/nuiton/util/ReflectUtil.java 2011-01-25 16:56:18 UTC (rev 2057) +++ trunk/nuiton-utils/src/main/java/org/nuiton/util/ReflectUtil.java 2011-01-26 10:38:34 UTC (rev 2058) @@ -275,7 +275,54 @@ } /** + * Obtain all the declared fields of the given {@code objectClass} with a + * deep scan inside super classes and interfaces. + * <p/> + * <strong>Note:</strong> The type {@link Object} will not be scanned. + * + * @param objectClass the object class to scan + * @return the set of all declared fields found + * @since 2.0 + */ + public static Set<Field> getAllDeclaredFields(Class<?> objectClass) { + Set<Field> result = new HashSet<Field>(); + Set<Class<?>> visitedClasses = new HashSet<Class<?>>(); + + try { + getAllDeclaredFields(objectClass, visitedClasses, result); + } finally { + visitedClasses.clear(); + } + return result; + } + + /** + * Obtain all the declared methods of the given {@code objectClass} with a + * deep scan inside super classes and interfaces. + * <p/> + * <strong>Note:</strong> The type {@link Object} will not be scanned. + * + * @param objectClass the object class to scan + * @return the set of all declared methods found + * @since 2.0 + */ + public static Set<Method> getAllDeclaredMethods(Class<?> objectClass) { + Set<Method> result = new HashSet<Method>(); + Set<Class<?>> visitedClasses = new HashSet<Class<?>>(); + + try { + getAllDeclaredMethods(objectClass, visitedClasses, result); + } finally { + visitedClasses.clear(); + } + return result; + } + + /** * Obtain all the fields with the given annotation type. + * <p/> + * <strong>Note:</strong> This method will not scan deeply the given type + * (no scan of super-classes nor interfaces). * * @param objectClass the type to scan * @param annotationClass the type of annotation to scan @@ -285,16 +332,108 @@ */ public static <A extends Annotation> Map<Field, A> getFieldAnnotation(Class<?> objectClass, Class<A> annotationClass) { + Map<Field, A> result = getFieldAnnotation(objectClass, + annotationClass, + false + ); + return result; + } + + /** + * Obtain all the fields with the given annotation type. + * <p/> + * <strong>Note:</strong> This method will scan deeply the given type + * if parameter {@code deepVisit} is setted to {@code true}. + * <p/> + * <strong>Note:</strong> The type {@link Object} will not be scanned. + * + * @param objectClass the type to scan + * @param annotationClass the type of annotation to scan + * @param deepVisit flag to visit deeply the class (if set to + * {@code true}, will also scan super classes + * and interfaces) + * @param <A> type of annotation to scan + * @return the dictionnary of fields with the given annotation + * @since 2.0 + */ + public static <A extends Annotation> Map<Field, A> getFieldAnnotation(Class<?> objectClass, + Class<A> annotationClass, + boolean deepVisit) { + Map<Field, A> result = new HashMap<Field, A>(); - for (Field field : objectClass.getDeclaredFields()) { - A annotation = field.getAnnotation(annotationClass); - if (annotation != null) { - result.put(field, annotation); - } + Set<Class<?>> visitedClasses = new HashSet<Class<?>>(); + + try { + getFieldAnnotation(objectClass, + annotationClass, + deepVisit, + visitedClasses, + result + ); + } finally { + visitedClasses.clear(); } + return result; } + /** + * Obtain all the methods with the given annotation type. + * <p/> + * <strong>Note:</strong> This method will not scan deeply the given type + * (no scan of super-classes nor interfaces). + * + * @param objectClass the type to scan + * @param annotationClass the type of annotation to scan + * @param <A> type of annotation to scan + * @return the dictionnary of methods with the given annotation + * @since 2.0 + */ + public static <A extends Annotation> Map<Method, A> getMethodAnnotation(Class<?> objectClass, + Class<A> annotationClass) { + Map<Method, A> result = getMethodAnnotation(objectClass, + annotationClass, + false + ); + return result; + } + + /** + * Obtain all the methods with the given annotation type. + * <p/> + * <strong>Note:</strong> This method will scan deeply the given type + * if parameter {@code deepVisit} is setted to {@code true}. + * <p/> + * <strong>Note:</strong> The type {@link Object} will not be scanned. + * + * @param objectClass the type to scan + * @param annotationClass the type of annotation to scan + * @param <A> type of annotation to scan + * @param deepVisit flag to visit deeply the class (if set to + * {@code true}, will also scan super classes + * and interfaces) + * @return the dictionnary of methods with the given annotation + * @since 2.0 + */ + public static <A extends Annotation> Map<Method, A> getMethodAnnotation(Class<?> objectClass, + Class<A> annotationClass, + boolean deepVisit) { + Map<Method, A> result = new HashMap<Method, A>(); + Set<Class<?>> visitedClasses = new HashSet<Class<?>>(); + + try { + getMethodAnnotation(objectClass, + annotationClass, + deepVisit, + visitedClasses, + result + ); + } finally { + visitedClasses.clear(); + } + return result; + } + protected static Method getDeclaredMethod(Class<?> klass, String methodName, Set<Class<?>> visitedClasses, @@ -391,4 +530,192 @@ return method; } + + protected static void getAllDeclaredFields(Class<?> objectClass, + Set<Class<?>> visitedClasses, + Set<Field> result) { + + if (visitedClasses.contains(objectClass) || + Object.class.equals(objectClass)) { + + // already scanned + // or arrives to Object.class + return; + } + + // mark as scanned + visitedClasses.add(objectClass); + + Field[] declaredFields = objectClass.getDeclaredFields(); + result.addAll(Arrays.asList(declaredFields)); + + Class<?> superclass = objectClass.getSuperclass(); + if (superclass != null) { + + // scan also the superclass + getAllDeclaredFields(superclass, + visitedClasses, + result + ); + } + + Class<?>[] interfaces = objectClass.getInterfaces(); + + for (Class<?> anInterface : interfaces) { + + // scan also the interface + getAllDeclaredFields(anInterface, + visitedClasses, + result + ); + } + + } + + protected static void getAllDeclaredMethods(Class<?> objectClass, + Set<Class<?>> visitedClasses, + Set<Method> result) { + + if (visitedClasses.contains(objectClass) || + Object.class.equals(objectClass)) { + + // already scanned + // or arrives to Object.class + return; + } + + // mark as scanned + visitedClasses.add(objectClass); + + Method[] declaredFields = objectClass.getDeclaredMethods(); + result.addAll(Arrays.asList(declaredFields)); + + Class<?> superclass = objectClass.getSuperclass(); + if (superclass != null) { + + // scan also the superclass + getAllDeclaredMethods(superclass, + visitedClasses, + result + ); + } + + Class<?>[] interfaces = objectClass.getInterfaces(); + + for (Class<?> anInterface : interfaces) { + + // scan also the interface + getAllDeclaredMethods(anInterface, + visitedClasses, + result + ); + } + + } + + protected static <A extends Annotation> void getFieldAnnotation(Class<?> objectClass, + Class<A> annotationClass, + boolean deepVisit, + Set<Class<?>> visitedClasses, + Map<Field, A> result) { + + if (visitedClasses.contains(objectClass) || + Object.class.equals(objectClass)) { + + // already scanned + // or arrives to Object.class + return; + } + + // mark as scanned + visitedClasses.add(objectClass); + + for (Field field : objectClass.getDeclaredFields()) { + A annotation = field.getAnnotation(annotationClass); + if (annotation != null) { + result.put(field, annotation); + } + } + + if (deepVisit) { + + Class<?> superclass = objectClass.getSuperclass(); + if (superclass != null) { + + // scan also the superclass + getFieldAnnotation(superclass, + annotationClass, + deepVisit, + visitedClasses, + result + ); + } + + Class<?>[] interfaces = objectClass.getInterfaces(); + + for (Class<?> anInterface : interfaces) { + + // scan also the interface + getFieldAnnotation(anInterface, + annotationClass, + deepVisit, + visitedClasses, + result + ); + } + } + } + + protected static <A extends Annotation> void getMethodAnnotation(Class<?> objectClass, + Class<A> annotationClass, + boolean deepVisit, + Set<Class<?>> visitedClasses, + Map<Method, A> result) { + + if (visitedClasses.contains(objectClass) || + Object.class.equals(objectClass)) { + + // already scanned + // or arrives to Object.class + return; + } + + // mark as scanned + visitedClasses.add(objectClass); + + for (Method method : objectClass.getDeclaredMethods()) { + A annotation = method.getAnnotation(annotationClass); + if (annotation != null) { + result.put(method, annotation); + } + } + + if (deepVisit) { + + Class<?> superclass = objectClass.getSuperclass(); + if (superclass != null) { + + // scan also the superclass + getMethodAnnotation(superclass, + annotationClass, + deepVisit, + visitedClasses, + result + ); + } + + Class<?>[] interfaces = objectClass.getInterfaces(); + + for (Class<?> anInterface : interfaces) { + + // scan also the interface + getMethodAnnotation(anInterface, + annotationClass, + deepVisit, + visitedClasses, + result + ); + } + } + } } Added: trunk/nuiton-utils/src/test/java/org/nuiton/util/ReflectUtilTest.java =================================================================== --- trunk/nuiton-utils/src/test/java/org/nuiton/util/ReflectUtilTest.java (rev 0) +++ trunk/nuiton-utils/src/test/java/org/nuiton/util/ReflectUtilTest.java 2011-01-26 10:38:34 UTC (rev 2058) @@ -0,0 +1,394 @@ +/* + * #%L + * Nuiton Utils :: Nuiton Utils + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2004 - 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.util; + +import org.junit.Assert; +import org.junit.Test; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.Set; + +/** + * To test the class {@link ReflectUtil}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class ReflectUtilTest { + + public static class MyClass { + + @SuppressWarnings("") + @Deprecated + public String publicField; + + @SuppressWarnings("") + @Deprecated + protected String protectedField; + + @SuppressWarnings("") + @Deprecated + private String privateField; + + @SuppressWarnings("") + @Deprecated + String field; + + @SuppressWarnings("") + String fieldSkipped; + + @SuppressWarnings("") + @Deprecated + public void publicMethod() { + + } + + @SuppressWarnings("") + @Deprecated + protected void protectedMethod() { + + } + + @SuppressWarnings("") + @Deprecated + private void privateMethod() { + + } + + @SuppressWarnings("") + @Deprecated + void method() { + + } + + @SuppressWarnings("") + void methodSkipped() { + + } + } + + public static class MySubClass extends MyClass { + + @SuppressWarnings("") + @Deprecated + String field2; + + @SuppressWarnings("") + @Deprecated + void method2() { + + } + } + + @Test + public void getAllDeclaredFields() throws NoSuchFieldException { + + Set<Field> fields; + + fields = ReflectUtil.getAllDeclaredFields(MyClass.class); + + assertGetAllDeclaredFields(fields, + "publicField", + "protectedField", + "privateField", + "field", + "fieldSkipped" + ); + + fields = ReflectUtil.getAllDeclaredFields(MySubClass.class); + + assertGetAllDeclaredFields(fields, + "publicField", + "protectedField", + "privateField", + "field", + "fieldSkipped", + "field2" + ); + + } + + @Test + public void getAllDeclaredMethods() throws NoSuchFieldException { + + Set<Method> methods; + + methods = ReflectUtil.getAllDeclaredMethods(MyClass.class); + + assertGetAllDeclaredMethods(methods, + "publicMethod", + "protectedMethod", + "privateMethod", + "method", + "methodSkipped" + ); + + methods = ReflectUtil.getAllDeclaredMethods(MySubClass.class); + + assertGetAllDeclaredMethods(methods, + "publicMethod", + "protectedMethod", + "privateMethod", + "method", + "methodSkipped", + "method2" + ); + + } + + @Test + public void getFieldAnnotation() throws NoSuchFieldException { + + Map<Field, ? extends Annotation> fieldAnnotation; + + // SuppressWarning is source scope so will disappear at compilation :) + fieldAnnotation = ReflectUtil.getFieldAnnotation(MyClass.class, + SuppressWarnings.class); + + assertFieldAnnotation(MyClass.class, fieldAnnotation); + + // SuppressWarning is source scope so will disappear at compilation :) + fieldAnnotation = ReflectUtil.getFieldAnnotation(MyClass.class, + SuppressWarnings.class, + true); + + assertFieldAnnotation(MyClass.class, fieldAnnotation); + + // SuppressWarning is source scope so will disappear at compilation :) + fieldAnnotation = ReflectUtil.getFieldAnnotation(MySubClass.class, + SuppressWarnings.class); + + assertFieldAnnotation(MySubClass.class, fieldAnnotation); + + // SuppressWarning is source scope so will disappear at compilation :) + fieldAnnotation = ReflectUtil.getFieldAnnotation(MySubClass.class, + SuppressWarnings.class, + true); + + assertFieldAnnotation(MySubClass.class, fieldAnnotation); + + fieldAnnotation = ReflectUtil.getFieldAnnotation(MyClass.class, + Deprecated.class); + + assertFieldAnnotation(MyClass.class, + fieldAnnotation, + "publicField", + "protectedField", + "privateField", + "field" + ); + + + fieldAnnotation = ReflectUtil.getFieldAnnotation(MyClass.class, + Deprecated.class, + true); + + assertFieldAnnotation(MyClass.class, + fieldAnnotation, + "publicField", + "protectedField", + "privateField", + "field" + ); + + fieldAnnotation = ReflectUtil.getFieldAnnotation(MySubClass.class, + Deprecated.class); + + assertFieldAnnotation(MySubClass.class, + fieldAnnotation, + "field2" + ); + + fieldAnnotation = ReflectUtil.getFieldAnnotation(MySubClass.class, + Deprecated.class, + true); + + assertFieldAnnotation(MySubClass.class, + fieldAnnotation, + "publicField", + "protectedField", + "privateField", + "field", + "field2" + ); + + } + + @Test + public void getMethodAnnotation() throws NoSuchMethodException { + + Map<Method, ? extends Annotation> methodAnnotation; + + // SuppressWarning is source scope so will disappear at compilation :) + methodAnnotation = ReflectUtil.getMethodAnnotation(MyClass.class, + SuppressWarnings.class); + + assertMethodAnnotation(MyClass.class, methodAnnotation); + + // SuppressWarning is source scope so will disappear at compilation :) + methodAnnotation = ReflectUtil.getMethodAnnotation(MyClass.class, + SuppressWarnings.class, + true); + + assertMethodAnnotation(MyClass.class, methodAnnotation); + + // SuppressWarning is source scope so will disappear at compilation :) + methodAnnotation = ReflectUtil.getMethodAnnotation(MySubClass.class, + SuppressWarnings.class); + + assertMethodAnnotation(MySubClass.class, methodAnnotation); + + // SuppressWarning is source scope so will disappear at compilation :) + methodAnnotation = ReflectUtil.getMethodAnnotation(MySubClass.class, + SuppressWarnings.class, + true); + + assertMethodAnnotation(MySubClass.class, methodAnnotation); + + methodAnnotation = ReflectUtil.getMethodAnnotation(MyClass.class, + Deprecated.class); + + assertMethodAnnotation(MyClass.class, + methodAnnotation, + "publicMethod", + "protectedMethod", + "privateMethod", + "method" + ); + + methodAnnotation = ReflectUtil.getMethodAnnotation(MyClass.class, + Deprecated.class, + true); + + assertMethodAnnotation(MyClass.class, + methodAnnotation, + "publicMethod", + "protectedMethod", + "privateMethod", + "method" + ); + + methodAnnotation = ReflectUtil.getMethodAnnotation(MySubClass.class, + Deprecated.class); + + assertMethodAnnotation(MySubClass.class, + methodAnnotation, + "method2" + ); + + methodAnnotation = ReflectUtil.getMethodAnnotation(MySubClass.class, + Deprecated.class, + true); + + assertMethodAnnotation(MySubClass.class, + methodAnnotation, + "publicMethod", + "protectedMethod", + "privateMethod", + "method", + "method2" + ); + + } + + protected void assertGetAllDeclaredFields(Set<Field> fields, + String... fieldNames) throws NoSuchFieldException { + + Assert.assertNotNull(fields); + Assert.assertEquals(fieldNames.length, fields.size()); + for (String fieldName : fieldNames) { + + Field field = getField(fieldName, fields); + + Assert.assertNotNull("Could not found field named " + fieldName, field); + } + } + + protected void assertGetAllDeclaredMethods(Set<Method> methods, + String... methodNames) throws NoSuchFieldException { + + Assert.assertNotNull(methods); + Assert.assertEquals(methodNames.length, methods.size()); + for (String methodName : methodNames) { + + Method method = getMethod(methodName, methods); + Assert.assertNotNull("Could not found method named " + methodName, method); + } + + } + + protected void assertFieldAnnotation(Class<?> type, + Map<Field, ? extends Annotation> fieldAnnotation, + String... fieldNames) throws NoSuchFieldException { + + Set<Field> allDeclaredFields = ReflectUtil.getAllDeclaredFields(type); + + Assert.assertNotNull(fieldAnnotation); + Assert.assertEquals(fieldNames.length, fieldAnnotation.size()); + for (String fieldName : fieldNames) { + Field field = getField(fieldName, allDeclaredFields); + Assert.assertNotNull(field); + Annotation annotation = fieldAnnotation.get(field); + Assert.assertNotNull("Could not found annotation for field " + fieldName, annotation); + } + } + + protected void assertMethodAnnotation(Class<?> type, + Map<Method, ? extends Annotation> fieldAnnotation, + String... methodNames) throws NoSuchMethodException { + + Set<Method> allDeclaredMethods = ReflectUtil.getAllDeclaredMethods(type); + + Assert.assertNotNull(fieldAnnotation); + Assert.assertEquals(methodNames.length, fieldAnnotation.size()); + for (String methodName : methodNames) { + Method method = getMethod(methodName, allDeclaredMethods); + Assert.assertNotNull(method); + Annotation annotation = fieldAnnotation.get(method); + Assert.assertNotNull("Could not found annotation for method " + methodName, annotation); + } + } + + protected Field getField(String fieldName, Set<Field> fields) { + for (Field field : fields) { + if (fieldName.equals(field.getName())) { + return field; + } + } + return null; + } + + protected Method getMethod(String methodName, Set<Method> methods) { + for (Method method : methods) { + if (methodName.equals(method.getName())) { + return method; + } + } + return null; + } +} Property changes on: trunk/nuiton-utils/src/test/java/org/nuiton/util/ReflectUtilTest.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native
participants (1)
-
tchemit@users.nuiton.org