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