001package io.ebean.util; 002 003import java.lang.annotation.Annotation; 004import java.lang.reflect.AnnotatedElement; 005import java.util.Collections; 006import java.util.HashSet; 007import java.util.LinkedHashSet; 008import java.util.Set; 009 010/** 011 * Annotation utility methods to find annotations. 012 */ 013public class AnnotationUtil { 014 015 /** 016 * Determine if the supplied {@link Annotation} is defined in the core JDK {@code java.lang.annotation} package. 017 */ 018 public static boolean notJavaLang(Annotation annotation) { 019 return !annotation.annotationType().getName().startsWith("java.lang.annotation"); 020 } 021 022 /** 023 * Simple get on field or method with no meta-annotations or platform filtering. 024 */ 025 public static <A extends Annotation> A get(AnnotatedElement element, Class<A> annotation) { 026 return element.getAnnotation(annotation); 027 } 028 029 /** 030 * Simple has with no meta-annotations or platform filtering. 031 */ 032 public static <A extends Annotation> boolean has(AnnotatedElement element, Class<A> annotation) { 033 return get(element, annotation) != null; 034 } 035 036 /** 037 * On class get the annotation - includes inheritance. 038 */ 039 public static <A extends Annotation> A typeGet(Class<?> clazz, Class<A> annotationType) { 040 while (clazz != null && clazz != Object.class) { 041 final A val = clazz.getAnnotation(annotationType); 042 if (val != null) { 043 return val; 044 } 045 clazz = clazz.getSuperclass(); 046 } 047 return null; 048 } 049 050 /** 051 * On class get all the annotations - includes inheritance. 052 */ 053 public static <A extends Annotation> Set<A> typeGetAll(Class<?> clazz, Class<A> annotationType) { 054 Set<A> result = new LinkedHashSet<>(); 055 typeGetAllCollect(clazz, annotationType, result); 056 return result; 057 } 058 059 private static <A extends Annotation> void typeGetAllCollect(Class<?> clazz, Class<A> annotationType, Set<A> result) { 060 while (clazz != null && clazz != Object.class) { 061 final A[] annotations = clazz.getAnnotationsByType(annotationType); 062 Collections.addAll(result, annotations); 063 clazz = clazz.getSuperclass(); 064 } 065 } 066 067 /** 068 * On class simple check for annotation - includes inheritance. 069 */ 070 public static <A extends Annotation> boolean typeHas(Class<?> clazz, Class<A> annotation) { 071 return typeGet(clazz, annotation) != null; 072 } 073 074 /** 075 * Check if an element is annotated with an annotation of given type searching meta-annotations. 076 */ 077 public static boolean metaHas(AnnotatedElement element, Class<?> annotationType) { 078 return !metaFindAll(element, annotationType).isEmpty(); 079 } 080 081 /** 082 * Find all the annotations of a given type searching meta-annotations. 083 */ 084 public static Set<Annotation> metaFindAll(AnnotatedElement element, Class<?> annotationType) { 085 return metaFindAllFor(element, Collections.singleton(annotationType)); 086 } 087 088 /** 089 * Find all the annotations for the filter searching meta-annotations. 090 */ 091 public static Set<Annotation> metaFindAllFor(AnnotatedElement element, Set<Class<?>> filter) { 092 Set<Annotation> visited = new HashSet<>(); 093 Set<Annotation> result = new LinkedHashSet<>(); 094 for (Annotation ann : element.getAnnotations()) { 095 metaAdd(ann, filter, visited, result); 096 } 097 return result; 098 } 099 100 private static void metaAdd(Annotation ann, Set<Class<?>> filter, Set<Annotation> visited, Set<Annotation> result) { 101 if (notJavaLang(ann) && visited.add(ann)) { 102 if (filter.contains(ann.annotationType())) { 103 result.add(ann); 104 } else { 105 for (Annotation metaAnn : ann.annotationType().getAnnotations()) { 106 metaAdd(metaAnn, filter, visited, result); 107 } 108 } 109 } 110 } 111}