Class AnnotationQuery<A extends Annotation>

  • Type Parameters:
    A - base annotation type
    All Implemented Interfaces:
    Iterable<A>

    public abstract class AnnotationQuery<A extends Annotation>
    extends Object
    Iterable-like container that finds annotations.

    Instances of this class are immutable, each filtering produces new, modified instance. To obtain query for specific class, use of(java.lang.reflect.AnnotatedElement).

    To obtain results either iterate this class with Iterable.iterator() (or in enhanced-for loop) or use one of stream(), unique(), option() or isPresent().

    This query handles repeatable annotations on elements as if they would be placed in a container annotation, exactly as it is written in bytecode. To get behavior that was introduced in Java 1.8 in AnnotatedElement.getDeclaredAnnotationsByType(java.lang.Class<T>), this query needs manual expansion of container annotations. See withRepeatableUnroll() for details.

    Example usage, which collects all annotations on singletonClass that are meta-annotated by Qualifier.

         AnnotationQuery.of(singletonClass)
                            .annotatedWith(javax.inject.Qualifier.class)
                            .stream()
                            .collect(ImmutableSet.toImmutableSet());
     
    • Method Detail

      • empty

        public static AnnotationQuery<Annotation> empty()
        This simple Null Object Pattern for this query.
        Returns:
        Query which will produce no results.
      • of

        public static AnnotationQuery<Annotation> of​(AnnotatedElement element)
        Creates a query from annotations declared on specified element.

        Only annotations with RetentionPolicy.RUNTIME will be returned.

        Parameters:
        element - element to extract annotations from
        Returns:
        annotation query that will list annotations
      • fromElements

        public static AnnotationQuery<Annotation> fromElements​(Set<Annotation> set)
        Converts set of annotations to query.

        Sets stream can be used to filter and does essentially the same, but this query allows more expressive filters used on specified set.

        Parameters:
        set - set to search on
        Returns:
        annotation query that will list exactly the set contents
      • fromElements

        public static AnnotationQuery<Annotation> fromElements​(Annotation... elements)
        Converts array of annotations to query.

        Stream of array contents can be used to filter and does essentially the same, but this query allows more expressive filters used.

        Parameters:
        elements - annotations to search from to search on
        Returns:
        annotation query that will list exactly the array contents
      • join

        public AnnotationQuery<Annotation> join​(AnnotationQuery<?> other)
        Creates query that contains results from both this and provided query.
        Parameters:
        other - annotation query to add
        Returns:
        annotation query that will list results of this and then the other query
      • filter

        public AnnotationQuery<A> filter​(Predicate<? super A> filter)
        Filter query elements by arbitrary predicate.

        Immutability warning: queries are assumed as immutable, but this method allows providing any Predicate, which will be held in resulting query. Therefore, if stateful predicate is provided, immutability of resulting query will be compromised. However, this is rarely the case, because most of the filters provided will be non-capturing lambdas or static method references.

        Parameters:
        filter - predicate that will determine if this query will contain element
        Returns:
        query returning the same elements as this one, but only if they match the predicate
      • annotatedWith

        public AnnotationQuery<A> annotatedWith​(Class<? extends Annotation> metaAnnotation)
        Creates query that filters resulting annotations that have meta-annotation placed on them.
        Parameters:
        metaAnnotation - annotation that must be placed on resulting annotation to be returned by query
        Returns:
        annotation query that will list results that have specific annotations placed on them
      • typed

        public <X extends AnnotationAnnotationQuery<X> typed​(Class<X> annotationClass)
        . Creates query that filters annotation that have specific type as a supertype.
        Type Parameters:
        X - new query result type
        Parameters:
        annotationClass - annotation type to filters
        Returns:
        annotation query that will list results that are of specific type
      • withRepeatableUnroll

        public AnnotationQuery<Annotation> withRepeatableUnroll()
        Expands repeatable annotations for the results of returned query.

        Normally, query handles repeatable annotations on elements as if they would be placed in a container annotation, exactly as it is written in bytecode. This method will add that repeatable annotations to the container.

        This method changes results, so that every annotation, that would be returned, if its a containing annotation, annotations that are embedded in it are also returned as a results. Containing annotation is also returned, if it matches other filters. See JLS 9.6.3.

        Unfortunately, repeatable annotation extraction in native Java is done with special care that is unavailable for public, for example in OpenJDK, the sun.reflect.annotation.AnnotationType is used, which is contained in a Class instance of an annotation type. Both field containing and the type is not public. Therefore this query tries to reconstruct relationship between containing and contained types. This has some initial performance penalty, as "value" method must be reflected. This class caches the information, so successive calls should be faster. *

        Returns:
        annotation query that will list repeatable annotations extracted from containers
      • contains

        public boolean contains​(@CompatibleWith("E")
                                Object candidate)
        Checks if provided object is in elements that would be returned by this query.

        This is often faster than checking by iteration, and most queries in library override this method, but this is not guaranteed, as it might not be possible.

        Parameters:
        candidate - object to check if it is contained in this query.
        Returns:
        if object would be returned by the query
      • stream

        public abstract Stream<E> stream()
        Adapts this query to a Stream.
        Returns:
        stream with elements of this query
      • unique

        public final E unique()
        Returns single element that this query contains.
        Returns:
        single element matches by this query
        Throws:
        NoSuchElementException - if this query didn't contain any element
        IllegalArgumentException - if the query contains multiple elements
      • isPresent

        public boolean isPresent()
        Checks if any element was contained in query.
        Returns:
        true if at least one element is present in this query
      • option

        public final Optional<E> option()
        Fetches only element present in this query, or empty optional.
        Returns:
        single element matched by this query, or empty optional.
        Throws:
        IllegalArgumentException - if the query contains multiple elements