Как избавиться от кучи If (swich-case - тоже не подойдет) П.С. Аннотации написаны по аналогии с аннотациями JUnit4, просто с припиской "Сat"
Методы сортируются в ArrayList-ы, в зависимости от аннотации над методом.
public class CatTestMainClass {
public Class inputTestClass;
ArrayList<Method> methodsWithCatBeforeClassAnnotation = new ArrayList<>();
ArrayList<Method> methodsWithCatBeforeAnnotation = new ArrayList<>();
ArrayList<Method> methodsWithTheOnlyCatTestAnnotation = new ArrayList<>();
ArrayList<Method> methodsWithCatAfterAnnotation = new ArrayList<>();
ArrayList<Method> methodsWithCatAfterClassAnnotation = new ArrayList<>();
ArrayList<Method> methodsWithCatIgnoreAnnotation = new ArrayList<>();
ArrayList<Method> methodsWithCatTimeAnnotation = new ArrayList<>();
public CatTestMainClass(Class catTestClass) {
inputTestClass = catTestClass;
}
public void methodSortingByAnnotations() {
Method[] declaredMethods = inputTestClass.getDeclaredMethods();
for (Method method : declaredMethods) {
if (!method.isAnnotationPresent(CatIgnore.class)) {
if (method.isAnnotationPresent(CatBeforeClass.class))
methodsWithCatBeforeClassAnnotation.add(method);
if (method.isAnnotationPresent(CatBefore.class))
methodsWithCatBeforeAnnotation.add(method);
if (method.isAnnotationPresent(CatTest.class)
&& !method.isAnnotationPresent(CatBeforeClass.class)
&& !method.isAnnotationPresent(CatBefore.class)
&& !method.isAnnotationPresent(CatAfter.class)
&& !method.isAnnotationPresent(CatAfterClass.class))
methodsWithTheOnlyCatTestAnnotation.add(method);
if (method.isAnnotationPresent(CatAfter.class))
methodsWithCatAfterAnnotation.add(method);
if (method.isAnnotationPresent(CatAfterClass.class))
methodsWithCatAfterClassAnnotation.add(method);
if (method.isAnnotationPresent(CatTime.class)) {
methodsWithCatTimeAnnotation.add(method);
}
} else {
methodsWithCatIgnoreAnnotation.add(method);
}
}
}
}
Ответы (2 шт):
Можно так: создаем мапу где ключ - это аннотация, а значение - обработчик метода. Каждый обработчик записывает метод в определенный список. Далее бежим по мапе и проверяем аннотирован ли какой-либо метод аннотацией. Если да, вызываем соответствующий обработчик для этого метода.
package click.webelement.sandbox;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
interface MySorter{
void doSort(Method method);
}
public class MethodSorting {
List<Method> list1 = new ArrayList<>();
List<Method> list2 = new ArrayList<>();
public static void main(String[] args) {
new MethodSorting().sorting(MethodSorting.class);
}
private void sorting(Class testClass){
Map<Class, MySorter> classSorterMap = new HashMap<>();
classSorterMap.put(Annotation1.class, method -> {list1.add(method);});
classSorterMap.put(Annotation2.class, method -> {list2.add(method);});
classSorterMap.forEach((aClass, mySorter) -> {
for(Method method: testClass.getDeclaredMethods()){
if(method.isAnnotationPresent(aClass)){
mySorter.doSort(method);
}
}
});
System.out.println("Stop here to debug");
}
@Annotation1
void test1(){}
@Annotation2
void test2(){}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Annotation1 {}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Annotation2 {}
Это в целом прототип подхода, но не полное решение, т.к. в Вашем случае есть корнер-кейс с несколькими аннотациям. Думаю, в таком случае, его лучше обработать отдельно первым делом.
Если это кастомные аннотации, то соотвественно их можно расширить, например, добавив какие-нибудь аннотации, которые предоставят дополнительную информацию для построения структуры хранения методов и порядка их выполнения.
package com.somepackage;
import java.lang.annotation.*;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;
public class Main {
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE})
public @interface Ordered {
int value() default 0;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Ordered
public @interface SomeAnnotationA {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Ordered(value = 1)
public @interface SomeAnnotationB {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Ordered(value = 2)
public @interface SomeAnnotationC {
}
static class SomeClass {
@SomeAnnotationB
public void someMethodB() {
}
@SomeAnnotationC
public void someMethodC() {
}
@SomeAnnotationA
public void someMethodA() {
}
}
public static void main(String[] args) {
Map<Integer, List<Method>> map =
Arrays.stream(SomeClass.class.getDeclaredMethods())
.collect(
Collectors.groupingBy(
(Method m) -> Arrays.stream(m.getAnnotations())
.map(a -> a.annotationType().getAnnotation(Ordered.class))
.filter(Objects::nonNull)
.map(Ordered::value)
.max(Comparator.naturalOrder())
.orElse(Integer.MAX_VALUE)));
System.out.println(
map.entrySet().stream()
.map(e -> e.getKey() + " -> " + e.getValue())
.collect(Collectors.joining(", ")));
}
}