package com.github.vbauer.jconditions.core;
import com.github.vbauer.jconditions.util.ReflexUtils;
import org.junit.runners.model.FrameworkMethod;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collection;
/**
* @author Vladislav Bauer
*/
public final class ConditionCheckerEngine {
private ConditionCheckerEngine() {
throw new UnsupportedOperationException();
}
public static ConditionChecker<?> detectFailedChecker(
final Object instance, final FrameworkMethod method
) {
final Collection<Annotation> annotations = findAllAnnotations(instance, method);
return findCheckerByAnnotations(instance, null, annotations);
}
private static ConditionChecker<?> findCheckerByAnnotations(
final Object instance, final Annotation parent, final Collection<Annotation> annotations
) {
for (final Annotation annotation : annotations) {
final ConditionChecker<?> checker =
getConditionChecker(instance, parent, annotation);
if (checker != null) {
return checker;
}
}
return null;
}
private static ConditionChecker<?> getConditionChecker(
final Object instance, final Annotation parent, final Annotation annotation
) {
if (!ReflexUtils.isInJavaLangAnnotationPackage(annotation)) {
final Class<? extends Annotation> annotationType = annotation.annotationType();
if (annotationType == Condition.class) {
final Condition condition = (Condition) annotation;
final ConditionChecker<?> checker =
findCheckerByCondition(instance, parent, condition);
if (checker != null) {
return checker;
}
}
final Collection<Annotation> extra =
Arrays.asList(annotationType.getAnnotations());
final ConditionChecker<?> checker =
findCheckerByAnnotations(instance, annotation, extra);
if (checker != null) {
return checker;
}
}
return null;
}
@SuppressWarnings({"unchecked", "rawtypes"})
private static <T> ConditionChecker<T> findCheckerByCondition(
final T instance, final Annotation parent, final Condition condition
) {
final Class<? extends ConditionChecker> checkerClass = condition.value();
final ConditionChecker<T> checker = ReflexUtils.instantiate(instance, checkerClass);
final CheckerContext<T> context = new CheckerContext(instance, parent);
if (!ConditionCheckerExecutor.isSatisfied(context, checker)) {
return checker;
}
return null;
}
private static Collection<Annotation> findAllAnnotations(
final Object instance, final FrameworkMethod method
) {
final Collection<Annotation> result = ReflexUtils.findAllAnnotations(instance.getClass());
result.addAll(Arrays.asList(method.getAnnotations()));
return result;
}
}