Skip to content

Commit

Permalink
Moved findMethod methods from AnnotationUtils to ReflectionUtils
Browse files Browse the repository at this point in the history
  • Loading branch information
jlink committed Nov 5, 2015
1 parent ac758bc commit e9e5932
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 76 deletions.
Expand Up @@ -10,19 +10,13 @@


package org.junit.gen5.commons.util; package org.junit.gen5.commons.util;


import static java.util.stream.Collectors.toList;

import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
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.Arrays;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.Predicate;


/** /**
* Collection of utilities for working with {@linkplain Annotation annotations}. * Collection of utilities for working with {@linkplain Annotation annotations}.
Expand Down Expand Up @@ -99,74 +93,8 @@ public static List<Method> findAnnotatedMethods(Class<?> clazz, Class<? extends
Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(clazz, "Class must not be null");
Preconditions.notNull(annotationType, "annotationType must not be null"); Preconditions.notNull(annotationType, "annotationType must not be null");


return findMethods(clazz, method -> findAnnotation(method, annotationType).isPresent(), sortOrder); return ReflectionUtils.findMethods(clazz, method -> findAnnotation(method, annotationType).isPresent(),
} sortOrder);

public static List<Method> findMethods(Class<?> clazz, Predicate<Method> predicate, MethodSortOrder sortOrder) {
Preconditions.notNull(clazz, "Class must not be null");
Preconditions.notNull(predicate, "predicate must not be null");

// @formatter:off
return findAllMethodsInHierarchy(clazz, sortOrder).stream()
.filter(predicate)
.collect(toList());
// @formatter:on
}

/**
* Return all methods in superclass hierarchy except from Object.
*/
public static List<Method> findAllMethodsInHierarchy(Class<?> clazz, MethodSortOrder sortOrder) {
// TODO Support interface default methods.
// TODO Determine if we need to support bridged methods.

List<Method> localMethods = Arrays.asList(clazz.getDeclaredMethods());

// @formatter:off
List<Method> superclassMethods = getSuperclassMethods(clazz, sortOrder).stream()
.filter(method -> !isMethodShadowedByLocalMethods(method, localMethods))
.collect(toList());
// @formatter:on

List<Method> methods = new ArrayList<>();
if (sortOrder == MethodSortOrder.HierarchyDown) {
methods.addAll(superclassMethods);
}
methods.addAll(localMethods);
if (sortOrder == MethodSortOrder.HierarchyUp) {
methods.addAll(superclassMethods);
}
return methods;
}

private static List<Method> getSuperclassMethods(Class<?> clazz, MethodSortOrder sortOrder) {
if (clazz.getSuperclass() != Object.class) {
return findAllMethodsInHierarchy(clazz.getSuperclass(), sortOrder);
}
else {
return Collections.emptyList();
}
}

private static boolean isMethodShadowedByLocalMethods(Method method, List<Method> localMethods) {
return localMethods.stream().anyMatch(local -> isMethodShadowedBy(method, local));
}

private static boolean isMethodShadowedBy(Method upper, Method lower) {
if (!lower.getName().equals(upper.getName())) {
return false;
}
Class<?>[] lowerParameterTypes = lower.getParameterTypes();
Class<?>[] upperParameterTypes = upper.getParameterTypes();
if (lowerParameterTypes.length != upperParameterTypes.length) {
return false;
}
for (int i = 0; i < lowerParameterTypes.length; i++) {
if (!lowerParameterTypes[i].equals(upperParameterTypes[i])) {
return false;
}
}
return true;
} }


public static boolean isInJavaLangAnnotationPackage(Annotation annotation) { public static boolean isInJavaLangAnnotationPackage(Annotation annotation) {
Expand Down
Expand Up @@ -10,9 +10,16 @@


package org.junit.gen5.commons.util; package org.junit.gen5.commons.util;


import static java.util.stream.Collectors.toList;

import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;


/** /**
* @author Stefan Bechtold * @author Stefan Bechtold
Expand Down Expand Up @@ -53,4 +60,71 @@ public static Class<?> loadClass(String name) {
} }
} }


public static List<Method> findMethods(Class<?> clazz, Predicate<Method> predicate,
AnnotationUtils.MethodSortOrder sortOrder) {
Preconditions.notNull(clazz, "Class must not be null");
Preconditions.notNull(predicate, "predicate must not be null");

// @formatter:off
return findAllMethodsInHierarchy(clazz, sortOrder).stream()
.filter(predicate)
.collect(toList());
// @formatter:on
}

/**
* Return all methods in superclass hierarchy except from Object.
*/
public static List<Method> findAllMethodsInHierarchy(Class<?> clazz, AnnotationUtils.MethodSortOrder sortOrder) {
// TODO Support interface default methods.
// TODO Determine if we need to support bridged methods.

List<Method> localMethods = Arrays.asList(clazz.getDeclaredMethods());

// @formatter:off
List<Method> superclassMethods = getSuperclassMethods(clazz, sortOrder).stream()
.filter(method -> !isMethodShadowedByLocalMethods(method, localMethods))
.collect(toList());
// @formatter:on

List<Method> methods = new ArrayList<>();
if (sortOrder == AnnotationUtils.MethodSortOrder.HierarchyDown) {
methods.addAll(superclassMethods);
}
methods.addAll(localMethods);
if (sortOrder == AnnotationUtils.MethodSortOrder.HierarchyUp) {
methods.addAll(superclassMethods);
}
return methods;
}

private static List<Method> getSuperclassMethods(Class<?> clazz, AnnotationUtils.MethodSortOrder sortOrder) {
if (clazz.getSuperclass() != Object.class) {
return findAllMethodsInHierarchy(clazz.getSuperclass(), sortOrder);
}
else {
return Collections.emptyList();
}
}

private static boolean isMethodShadowedByLocalMethods(Method method, List<Method> localMethods) {
return localMethods.stream().anyMatch(local -> isMethodShadowedBy(method, local));
}

private static boolean isMethodShadowedBy(Method upper, Method lower) {
if (!lower.getName().equals(upper.getName())) {
return false;
}
Class<?>[] lowerParameterTypes = lower.getParameterTypes();
Class<?>[] upperParameterTypes = upper.getParameterTypes();
if (lowerParameterTypes.length != upperParameterTypes.length) {
return false;
}
for (int i = 0; i < lowerParameterTypes.length; i++) {
if (!lowerParameterTypes[i].equals(upperParameterTypes[i])) {
return false;
}
}
return true;
}
} }
Expand Up @@ -18,6 +18,7 @@
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;


import org.junit.gen5.commons.util.ReflectionUtils;
import org.junit.gen5.engine.ClassNameSpecification; import org.junit.gen5.engine.ClassNameSpecification;
import org.junit.gen5.engine.TestDescriptor; import org.junit.gen5.engine.TestDescriptor;


Expand Down Expand Up @@ -49,7 +50,7 @@ public List<TestDescriptor> resolveChildren(ClassTestDescriptor parent, ClassNam
// TODO Retrieve children resolvers according to type // TODO Retrieve children resolvers according to type
List<TestDescriptor> children = new LinkedList<>(); List<TestDescriptor> children = new LinkedList<>();


List<Method> testMethodCandidates = findMethods(parent.getTestClass(), methodTester::accept, List<Method> testMethodCandidates = ReflectionUtils.findMethods(parent.getTestClass(), methodTester::accept,
MethodSortOrder.HierarchyDown); MethodSortOrder.HierarchyDown);


// @formatter:off // @formatter:off
Expand Down
Expand Up @@ -11,6 +11,7 @@
package org.junit.gen5.engine.junit5.descriptor; package org.junit.gen5.engine.junit5.descriptor;


import org.junit.gen5.commons.util.AnnotationUtils; import org.junit.gen5.commons.util.AnnotationUtils;
import org.junit.gen5.commons.util.ReflectionUtils;


/** /**
* @since 5.0 * @since 5.0
Expand All @@ -28,7 +29,7 @@ boolean accept(Class<?> testClassCandidate) {
} }


private boolean hasTestMethods(Class<?> testClassCandidate) { private boolean hasTestMethods(Class<?> testClassCandidate) {
return !AnnotationUtils.findMethods(testClassCandidate, methodTester::accept, return !ReflectionUtils.findMethods(testClassCandidate, methodTester::accept,
AnnotationUtils.MethodSortOrder.HierarchyDown).isEmpty(); AnnotationUtils.MethodSortOrder.HierarchyDown).isEmpty();
} }


Expand Down

1 comment on commit e9e5932

@sbrannen
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I was gonna do that anyway. ;)

Please sign in to comment.