/*
* Copyright 2015-2017 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.junit.platform.commons.support;
import static org.junit.platform.commons.meta.API.Usage.Maintained;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Optional;
import org.junit.platform.commons.meta.API;
import org.junit.platform.commons.util.AnnotationUtils;
import org.junit.platform.commons.util.ReflectionUtils;
/**
* Common annotation support.
*
* @since 1.0
*/
@API(Maintained)
public final class AnnotationSupport {
///CLOVER:OFF
private AnnotationSupport() {
/* no-op */
}
///CLOVER:ON
/**
* Determine if an annotation of {@code annotationType} is either
* <em>present</em> or <em>meta-present</em> on the supplied
* {@code element}.
*
* @see #findAnnotation(AnnotatedElement, Class)
*/
public static boolean isAnnotated(AnnotatedElement element, Class<? extends Annotation> annotationType) {
return AnnotationUtils.isAnnotated(element, annotationType);
}
/**
* Find the first annotation of {@code annotationType} that is either
* <em>present</em> or <em>meta-present</em> on the supplied
* {@code element}.
*/
public static <A extends Annotation> Optional<A> findAnnotation(AnnotatedElement element, Class<A> annotationType) {
return AnnotationUtils.findAnnotation(element, annotationType);
}
/**
* Find all <em>repeatable</em> {@linkplain Annotation annotations} of
* {@code annotationType} that are either <em>present</em>, <em>indirectly
* present</em>, or <em>meta-present</em> on the supplied {@link AnnotatedElement}.
*
* <p>This method extends the functionality of
* {@link java.lang.reflect.AnnotatedElement#getAnnotationsByType(Class)}
* with additional support for meta-annotations.
*
* <p>In addition, if the element is a class and the repeatable annotation
* is {@link java.lang.annotation.Inherited @Inherited}, this method will
* search on superclasses first in order to support top-down semantics.
* The result is that this algorithm finds repeatable annotations that
* would be <em>shadowed</em> and therefore not visible according to Java's
* standard semantics for inherited, repeatable annotations, but most
* developers will naturally assume that all repeatable annotations in JUnit
* are discovered regardless of whether they are declared stand-alone, in a
* container, or as a meta-annotation (e.g., multiple declarations of
* {@code @ExtendWith} within a test class hierarchy).
*
* <p>If the supplied {@code element} is {@code null}, this method simply
* returns an empty list.
*
* @param element the element to search on, potentially {@code null}
* @param annotationType the repeatable annotation type to search for; never {@code null}
* @return the list of all such annotations found; neither {@code null} nor mutable
* @see java.lang.annotation.Repeatable
* @see java.lang.annotation.Inherited
*/
public static <A extends Annotation> List<A> findRepeatableAnnotations(AnnotatedElement element,
Class<A> annotationType) {
return AnnotationUtils.findRepeatableAnnotations(element, annotationType);
}
/**
* Find all {@code public} {@linkplain Field fields} of the supplied class
* or interface that are of the specified {@code fieldType} and annotated
* or <em>meta-annotated</em> with the specified {@code annotationType}.
*
* <p>Consult the Javadoc for {@link Class#getFields()} for details on
* inheritance and ordering.
*
* @param clazz the class or interface in which to find the fields; never {@code null}
* @param fieldType the type of field to find; never {@code null}
* @param annotationType the annotation type to search for; never {@code null}
* @return the list of all such fields found; neither {@code null} nor mutable
* @see Class#getFields()
*/
public static List<Field> findPublicAnnotatedFields(Class<?> clazz, Class<?> fieldType,
Class<? extends Annotation> annotationType) {
return AnnotationUtils.findPublicAnnotatedFields(clazz, fieldType, annotationType);
}
/**
* Find all {@linkplain Method methods} of the supplied class or interface
* that are annotated or <em>meta-annotated</em> with the specified
* {@code annotationType}.
*
* @param clazz the class or interface in which to find the methods; never {@code null}
* @param annotationType the annotation type to search for; never {@code null}
* @param traversalMode the hierarchy traversal mode; never {@code null}
* @return the list of all such methods found; neither {@code null} nor mutable
*/
public static List<Method> findAnnotatedMethods(Class<?> clazz, Class<? extends Annotation> annotationType,
HierarchyTraversalMode traversalMode) {
return AnnotationUtils.findAnnotatedMethods(clazz, annotationType,
ReflectionUtils.HierarchyTraversalMode.valueOf(traversalMode.name()));
}
}