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 }