View Javadoc

1   /*
2    * Copyright (C) 2013 Martin Cerny
3    *
4    * This program is free software: you can redistribute it and/or modify
5    * it under the terms of the GNU General Public License as published by
6    * the Free Software Foundation, either version 3 of the License, or
7    * (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16   */
17  
18  package cz.cuni.amis.utils;
19  
20  import java.lang.reflect.Field;
21  import java.lang.reflect.Method;
22  import java.lang.reflect.Modifier;
23  import org.apache.commons.beanutils.PropertyUtils;
24  
25  /**
26   * Utility methods for reading and processing annotations of objects and their members.
27   * @author Martin Cerny
28   */
29  public class ReflectionUtils {
30  
31      public ReflectionUtils() {
32          throw new RuntimeException("Cannot instantiate static class");
33      }
34  
35      public static interface ProcessAnnotatedMethodCallback<T extends java.lang.annotation.Annotation> {
36          void processMethod(Method m, T annotation);
37      }
38      
39      public static interface ProcessAnnotatedFieldCallback<T extends java.lang.annotation.Annotation, E extends Throwable> {
40          void processField(Field f,Object fieldValue, T annotation) throws E;
41      }
42  
43      public static interface ProcessFieldCallback<E extends Throwable> {
44          void processField(Field f) throws E;
45      }
46  
47      public static <E extends Throwable>  void processEachDeclaredNonStaticField(Object targetObject, ProcessFieldCallback<E> callBack) throws E{
48          processEachDeclaredNonStaticField(targetObject,Object.class, callBack);
49      }
50      
51      public static <E extends Throwable>  void processEachDeclaredNonStaticField(Object targetObject, Class rootClass,ProcessFieldCallback<E> callBack) throws E{
52          if(!rootClass.isAssignableFrom(targetObject.getClass())){
53              throw new IllegalArgumentException("TargetObject must be instance of rootClass");
54          }
55          Class inspectedClass = targetObject.getClass();
56          while(inspectedClass != null && rootClass.isAssignableFrom(inspectedClass)){
57              for(Field f : inspectedClass.getDeclaredFields()){
58                  if(Modifier.isStatic(f.getModifiers())){
59                      continue;
60                  }
61                  callBack.processField(f);
62              }
63              inspectedClass = inspectedClass.getSuperclass();
64          }
65  
66      }
67  
68      public static <E extends Throwable>  void processEachDeclaredFieldOfClass(Class targetClass, ProcessFieldCallback<E> callBack) throws E{
69          processEachDeclaredFieldOfClass(targetClass,Object.class, callBack);
70      }
71      
72      public static <E extends Throwable>  void processEachDeclaredFieldOfClass(Class targetClass, Class rootClass,ProcessFieldCallback<E> callBack) throws E{
73          if(!rootClass.isAssignableFrom(targetClass)){
74              throw new IllegalArgumentException("TargetClass must be descendant of rootClass");
75          }
76          Class inspectedClass = targetClass;
77          while(inspectedClass != null && rootClass.isAssignableFrom(inspectedClass)){
78              for(Field f : inspectedClass.getDeclaredFields()){
79                  callBack.processField(f);
80              }
81              inspectedClass = inspectedClass.getSuperclass();
82          }
83  
84      }
85      
86  
87      public static <T extends java.lang.annotation.Annotation, E extends Throwable>  void processEachAnnotatedDeclaredField(final Object targetObject, final Class<T> annotationClass, final ProcessAnnotatedFieldCallback<T, E> callBack) throws E{
88          processEachAnnotatedDeclaredField(targetObject, Object.class, annotationClass, callBack);
89      }
90  
91      public static <T extends java.lang.annotation.Annotation, E extends Throwable>  void processEachAnnotatedDeclaredField(final Object targetObject, final Class rootClass, final Class<T> annotationClass, final ProcessAnnotatedFieldCallback<T, E> callBack) throws E{
92  
93          processEachDeclaredNonStaticField(targetObject, rootClass, new ProcessFieldCallback<E>() {
94  
95              @Override
96              public void processField(Field f) throws E {
97                  if(f.isAnnotationPresent(annotationClass)){
98                      Object fieldValue;
99                      try {
100                          fieldValue = PropertyUtils.getProperty(targetObject, f.getName());
101                     } catch (Exception ex) {
102                         throw new IllegalStateException("Could not read property value for annotated property '" + f.getName() + "' in class" + f.getDeclaringClass().getName() + "\nThe property should have public getter.", ex);
103                     }
104                     callBack.processField(f, fieldValue, f.getAnnotation(annotationClass));
105                 }
106             }
107         });
108 
109         
110     }
111 
112     
113     public static <T extends java.lang.annotation.Annotation>  void processEachAnnotatedDeclaredMethod(final Object targetObject, final Class<T> annotationClass, final ProcessAnnotatedMethodCallback<T> callBack){
114         processEachAnnotatedDeclaredMethod(targetObject, Object.class, annotationClass, callBack);
115     }
116     
117     public static <T extends java.lang.annotation.Annotation>  void processEachAnnotatedDeclaredMethod(final Object targetObject, final Class rootClass, final Class<T> annotationClass, final ProcessAnnotatedMethodCallback<T> callBack){
118 
119         if(!rootClass.isAssignableFrom(targetObject.getClass())){
120             throw new IllegalArgumentException("TargetObject must be instance of rootClass");
121         }
122         Class inspectedClass = targetObject.getClass();
123         while(inspectedClass != null && rootClass.isAssignableFrom(inspectedClass)){
124             for(Method f : inspectedClass.getDeclaredMethods()){
125                 if(f.isAnnotationPresent(annotationClass)){
126                     callBack.processMethod(f,f.getAnnotation(annotationClass));
127                 }
128             }
129             inspectedClass = inspectedClass.getSuperclass();
130         }
131         
132     }
133     
134 }