001 package org.junit.validator;
002
003 import static java.util.Collections.singletonList;
004
005 import java.lang.annotation.Annotation;
006 import java.util.ArrayList;
007 import java.util.Arrays;
008 import java.util.List;
009
010 import org.junit.runners.model.Annotatable;
011 import org.junit.runners.model.FrameworkField;
012 import org.junit.runners.model.FrameworkMethod;
013 import org.junit.runners.model.TestClass;
014
015 /**
016 * An {@code AnnotationsValidator} validates all annotations of a test class,
017 * including its annotated fields and methods.
018 *
019 * @since 4.12
020 */
021 public final class AnnotationsValidator implements TestClassValidator {
022 private static final List<AnnotatableValidator<?>> VALIDATORS = Arrays.<AnnotatableValidator<?>>asList(
023 new ClassValidator(), new MethodValidator(), new FieldValidator());
024
025 /**
026 * Validate all annotations of the specified test class that are be
027 * annotated with {@link ValidateWith}.
028 *
029 * @param testClass
030 * the {@link TestClass} that is validated.
031 * @return the errors found by the validator.
032 */
033 public List<Exception> validateTestClass(TestClass testClass) {
034 List<Exception> validationErrors= new ArrayList<Exception>();
035 for (AnnotatableValidator<?> validator : VALIDATORS) {
036 List<Exception> additionalErrors= validator
037 .validateTestClass(testClass);
038 validationErrors.addAll(additionalErrors);
039 }
040 return validationErrors;
041 }
042
043 private abstract static class AnnotatableValidator<T extends Annotatable> {
044 private static final AnnotationValidatorFactory ANNOTATION_VALIDATOR_FACTORY = new AnnotationValidatorFactory();
045
046 abstract Iterable<T> getAnnotatablesForTestClass(TestClass testClass);
047
048 abstract List<Exception> validateAnnotatable(
049 AnnotationValidator validator, T annotatable);
050
051 public List<Exception> validateTestClass(TestClass testClass) {
052 List<Exception> validationErrors= new ArrayList<Exception>();
053 for (T annotatable : getAnnotatablesForTestClass(testClass)) {
054 List<Exception> additionalErrors= validateAnnotatable(annotatable);
055 validationErrors.addAll(additionalErrors);
056 }
057 return validationErrors;
058 }
059
060 private List<Exception> validateAnnotatable(T annotatable) {
061 List<Exception> validationErrors= new ArrayList<Exception>();
062 for (Annotation annotation : annotatable.getAnnotations()) {
063 Class<? extends Annotation> annotationType = annotation
064 .annotationType();
065 ValidateWith validateWith = annotationType
066 .getAnnotation(ValidateWith.class);
067 if (validateWith != null) {
068 AnnotationValidator annotationValidator = ANNOTATION_VALIDATOR_FACTORY
069 .createAnnotationValidator(validateWith);
070 List<Exception> errors= validateAnnotatable(
071 annotationValidator, annotatable);
072 validationErrors.addAll(errors);
073 }
074 }
075 return validationErrors;
076 }
077 }
078
079 private static class ClassValidator extends AnnotatableValidator<TestClass> {
080 @Override
081 Iterable<TestClass> getAnnotatablesForTestClass(TestClass testClass) {
082 return singletonList(testClass);
083 }
084
085 @Override
086 List<Exception> validateAnnotatable(
087 AnnotationValidator validator, TestClass testClass) {
088 return validator.validateAnnotatedClass(testClass);
089 }
090 }
091
092 private static class MethodValidator extends
093 AnnotatableValidator<FrameworkMethod> {
094 @Override
095 Iterable<FrameworkMethod> getAnnotatablesForTestClass(
096 TestClass testClass) {
097 return testClass.getAnnotatedMethods();
098 }
099
100 @Override
101 List<Exception> validateAnnotatable(
102 AnnotationValidator validator, FrameworkMethod method) {
103 return validator.validateAnnotatedMethod(method);
104 }
105 }
106
107 private static class FieldValidator extends
108 AnnotatableValidator<FrameworkField> {
109 @Override
110 Iterable<FrameworkField> getAnnotatablesForTestClass(TestClass testClass) {
111 return testClass.getAnnotatedFields();
112 }
113
114 @Override
115 List<Exception> validateAnnotatable(
116 AnnotationValidator validator, FrameworkField field) {
117 return validator.validateAnnotatedField(field);
118 }
119 }
120 }