001    /*
002     * To change this template, choose Tools | Templates
003     * and open the template in the editor.
004     */
005    package org.bridj.util;
006    
007    import java.lang.annotation.Annotation;
008    import java.lang.reflect.AnnotatedElement;
009    import java.lang.reflect.Member;
010    import java.lang.reflect.Proxy;
011    import org.bridj.ann.Forwardable;
012    
013    /**
014     * Util methods for annotations (inheritable annotations, forwarded annotations, annotations from AnnotatedElements and/or direct annotation arrays...)
015     * @author ochafik
016     */
017    public class AnnotationUtils {
018        
019        public static <A extends Annotation> A getInheritableAnnotation(Class<A> ac, AnnotatedElement m, Annotation... directAnnotations) {
020            return getAnnotation(ac, true, m, directAnnotations);
021        }
022        public static <A extends Annotation> A getAnnotation(Class<A> ac, AnnotatedElement m, Annotation... directAnnotations) {
023            return getAnnotation(ac, false, m, directAnnotations);
024        }
025        private static boolean isForwardable(Class<? extends Annotation> ac) {
026            return ac.isAnnotationPresent(Forwardable.class);
027        }
028        public static boolean isAnnotationPresent(Class<? extends Annotation> ac, Annotation... annotations) {
029            return isAnnotationPresent(ac, isForwardable(ac), annotations);
030        }
031        private static boolean isAnnotationPresent(Class<? extends Annotation> ac, boolean isForwardable, Annotation... annotations) {
032            for (Annotation ann : annotations) {
033                if (ac.isInstance(ann))
034                    return true;
035    
036                if (isForwardable) {
037                    if (ann.annotationType().isAnnotationPresent(ac))
038                        return true;
039                }
040            }
041            return false;
042        }
043        public static boolean isAnnotationPresent(Class<? extends Annotation> ac, AnnotatedElement m, Annotation... directAnnotations) {
044            boolean isForwardable = isForwardable(ac);
045            if (m != null) {
046                if (isForwardable) {
047                    if (isAnnotationPresent(ac, true, m.getAnnotations()))
048                        return true;
049                } else {
050                    if (m.isAnnotationPresent(ac))
051                        return true;
052                }
053            }
054            if (directAnnotations != null)
055                return isAnnotationPresent(ac, isForwardable, directAnnotations);
056            
057            return false;
058        }
059    
060        private static <A extends Annotation> A getAnnotation(Class<A> ac, boolean inherit, AnnotatedElement m, Annotation... directAnnotations) {
061            if (directAnnotations != null) {
062                for (Annotation ann : directAnnotations) {
063                    if (ac.isInstance(ann)) {
064                        return ac.cast(ann);
065                    }
066                }
067            }
068    
069            if (m == null) {
070                return null;
071            }
072            A a = m.getAnnotation(ac);
073            if (a != null) {
074                return a;
075            }
076    
077            if (inherit) {
078                if (m instanceof Member) {
079                    return getAnnotation(ac, inherit, ((Member) m).getDeclaringClass());
080                }
081                
082                if (m instanceof Class<?>) {
083                    Class<?> c = (Class<?>) m, dc = c.getDeclaringClass();
084                    Class p = c.getSuperclass();
085                                    while (p != null) {
086                                            a = getAnnotation(ac, true, p);
087                                            if (a != null)
088                                                    return a;
089                                            p = p.getSuperclass();
090                                    }
091    
092                    if (dc != null) {
093                            return getAnnotation(ac, inherit, dc);
094                    }
095            }
096            }
097            return null;
098        }
099    }