    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 static abstract 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    }