Skip to content

Commit

Permalink
Fixed disabled test in AnnotationUtilsTest.
Browse files Browse the repository at this point in the history
------------------------------------------------------------------------
On behalf of the community, the JUnit Lambda Team thanks
Samuraism, Inc. (http://samuraism.com/) for supporting the
JUnit crowdfunding campaign!
------------------------------------------------------------------------
  • Loading branch information
jlink committed Dec 29, 2015
1 parent dc2f86c commit d09f119
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 26 deletions.
Expand Up @@ -14,11 +14,13 @@


import java.io.Serializable; import java.io.Serializable;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
Expand All @@ -44,9 +46,9 @@ private AnnotationUtils() {
} }


/** /**
* Determine if an annotation of {@code annotationType} is either * Determine if an annotation of {@code annotationType} is either <em>present</em> or <em>meta-present</em> on the
* <em>present</em> or <em>meta-present</em> on the supplied optional * supplied optional {@code element}.
* {@code element}. *
* @see #findAnnotation(Optional, Class) * @see #findAnnotation(Optional, Class)
*/ */
public static boolean isAnnotated(Optional<? extends AnnotatedElement> element, public static boolean isAnnotated(Optional<? extends AnnotatedElement> element,
Expand All @@ -56,18 +58,19 @@ public static boolean isAnnotated(Optional<? extends AnnotatedElement> element,
} }


/** /**
* Determine if an annotation of {@code annotationType} is either * Determine if an annotation of {@code annotationType} is either <em>present</em> or <em>meta-present</em> on the
* <em>present</em> or <em>meta-present</em> on the supplied {@code element}. * supplied {@code element}.
*
* @see #findAnnotation(AnnotatedElement, Class) * @see #findAnnotation(AnnotatedElement, Class)
*/ */
public static boolean isAnnotated(AnnotatedElement element, Class<? extends Annotation> annotationType) { public static boolean isAnnotated(AnnotatedElement element, Class<? extends Annotation> annotationType) {
return findAnnotation(element, annotationType).isPresent(); return findAnnotation(element, annotationType).isPresent();
} }


/** /**
* Find the first annotation of {@code annotationType} that is either * Find the first annotation of {@code annotationType} that is either <em>present</em> or <em>meta-present</em> on
* <em>present</em> or <em>meta-present</em> on the supplied optional * the supplied optional {@code element}.
* {@code element}. *
* @see #findAnnotation(AnnotatedElement, Class) * @see #findAnnotation(AnnotatedElement, Class)
*/ */
public static <A extends Annotation> Optional<A> findAnnotation(Optional<? extends AnnotatedElement> element, public static <A extends Annotation> Optional<A> findAnnotation(Optional<? extends AnnotatedElement> element,
Expand All @@ -81,8 +84,9 @@ public static <A extends Annotation> Optional<A> findAnnotation(Optional<? exten
} }


/** /**
* Find the first annotation of {@code annotationType} that is either * Find the first annotation of {@code annotationType} that is either <em>present</em> or <em>meta-present</em> on
* <em>present</em> or <em>meta-present</em> on the supplied {@code element}. * the supplied {@code element}.
*
* @see #findAnnotation(Optional, Class) * @see #findAnnotation(Optional, Class)
*/ */
public static <A extends Annotation> Optional<A> findAnnotation(AnnotatedElement element, Class<A> annotationType) { public static <A extends Annotation> Optional<A> findAnnotation(AnnotatedElement element, Class<A> annotationType) {
Expand Down Expand Up @@ -148,14 +152,12 @@ private static <A extends Annotation> Optional<A> findAnnotation(AnnotatedElemen
} }


/** /**
* Find all <em>repeatable</em> {@linkplain Annotation annotations} of * Find all <em>repeatable</em> {@linkplain Annotation annotations} of {@code annotationType} that are either
* {@code annotationType} that are either <em>present</em>, * <em>present</em>, <em>indirectly present</em>, or <em>meta-present</em> on the supplied {@link AnnotatedElement}.
* <em>indirectly present</em>, or <em>meta-present</em> on the supplied
* {@link AnnotatedElement}.
* *
* <p>This method extends the functionality of * <p>This method extends the functionality of {@link java.lang.reflect.AnnotatedElement#getAnnotationsByType(Class)}
* {@link java.lang.reflect.AnnotatedElement#getAnnotationsByType(Class)}
* with additional support for meta-annotations. * with additional support for meta-annotations.
*
* @return the list of all such annotations found; never {@code null} * @return the list of all such annotations found; never {@code null}
*/ */
public static <A extends Annotation> List<A> findRepeatableAnnotations(AnnotatedElement element, public static <A extends Annotation> List<A> findRepeatableAnnotations(AnnotatedElement element,
Expand All @@ -168,22 +170,34 @@ private static <A extends Annotation> List<A> findRepeatableAnnotations(Annotate
Class<A> annotationType, Set<Annotation> visited) { Class<A> annotationType, Set<Annotation> visited) {


Preconditions.notNull(annotationType, "annotationType must not be null"); Preconditions.notNull(annotationType, "annotationType must not be null");
Class<? extends Annotation> containerTypeForRepeatable = annotationType.isAnnotationPresent(Repeatable.class)
? annotationType.getAnnotation(Repeatable.class).value() : null;
Preconditions.notNull(containerTypeForRepeatable, "annotationType must be @Repeatable");


if (element == null) { if (element == null) {
return Collections.emptyList(); return Collections.emptyList();
} }


List<A> collectedAnnotations = new ArrayList<>(); // Use set because there can be duplicates in loop below.

Set<A> collectedAnnotations = new LinkedHashSet<>();
// Directly present?
collectedAnnotations.addAll(asList(element.getDeclaredAnnotationsByType(annotationType)));


// Meta-present on directly present annotations? // Collect directly present annotations and meta-present on directly present annotations.
// Keep order of annotations.
for (Annotation candidateAnnotation : element.getDeclaredAnnotations()) { for (Annotation candidateAnnotation : element.getDeclaredAnnotations()) {
if (!isInJavaLangAnnotationPackage(candidateAnnotation) && visited.add(candidateAnnotation)) { if (!isInJavaLangAnnotationPackage(candidateAnnotation) && visited.add(candidateAnnotation)) {
List<A> metaAnnotations = findRepeatableAnnotations(candidateAnnotation.annotationType(), if (candidateAnnotation.annotationType().equals(annotationType)) {
annotationType, visited); collectedAnnotations.add((A) candidateAnnotation);
collectedAnnotations.addAll(metaAnnotations); }
else if (candidateAnnotation.annotationType().equals(containerTypeForRepeatable)) {
//TODO: Retrieve containedAnnotations from candidateAnnotation.value()
List<A> containedAnnotations = asList(element.getDeclaredAnnotationsByType(annotationType));
collectedAnnotations.addAll(containedAnnotations);
}
else {
List<A> metaAnnotations = findRepeatableAnnotations(candidateAnnotation.annotationType(),
annotationType, visited);
collectedAnnotations.addAll(metaAnnotations);
}
} }
} }


Expand All @@ -206,7 +220,7 @@ private static <A extends Annotation> List<A> findRepeatableAnnotations(Annotate
} }
} }


return collectedAnnotations; return new ArrayList<>(collectedAnnotations);
} }


public static List<Method> findAnnotatedMethods(Class<?> clazz, Class<? extends Annotation> annotationType, public static List<Method> findAnnotatedMethods(Class<?> clazz, Class<? extends Annotation> annotationType,
Expand Down
Expand Up @@ -109,7 +109,6 @@ public void findRepeatableAnnotationsWithContainer() throws Exception {
} }


@Test @Test
@Ignore("Disabled until findRepeatableAnnotations() algorithm is refined")
public void findRepeatableAnnotationsWithComposedTagBeforeContainer() throws Exception { public void findRepeatableAnnotationsWithComposedTagBeforeContainer() throws Exception {
assertTagsFound(ContainerAfterComposedTaggedClass.class, "fast", "a", "b", "c"); assertTagsFound(ContainerAfterComposedTaggedClass.class, "fast", "a", "b", "c");
} }
Expand Down

0 comments on commit d09f119

Please sign in to comment.