001    package org.junit.experimental.categories;
002    
003    import static java.util.Arrays.asList;
004    import static java.util.Collections.unmodifiableList;
005    import static java.util.Collections.unmodifiableSet;
006    
007    import java.lang.annotation.Annotation;
008    import java.util.ArrayList;
009    import java.util.HashSet;
010    import java.util.List;
011    import java.util.Set;
012    
013    import org.junit.After;
014    import org.junit.AfterClass;
015    import org.junit.Before;
016    import org.junit.BeforeClass;
017    import org.junit.runners.model.FrameworkMethod;
018    import org.junit.validator.AnnotationValidator;
019    
020    /**
021     * Validates that there are no errors in the use of the {@code Category}
022     * annotation. If there is, a {@code Throwable} object will be added to the list
023     * of errors.
024     *
025     * @since 4.12
026     */
027    public final class CategoryValidator extends AnnotationValidator {
028    
029        @SuppressWarnings("unchecked")
030        private static final Set<Class<? extends Annotation>> INCOMPATIBLE_ANNOTATIONS = unmodifiableSet(new HashSet<Class<? extends Annotation>>(
031                asList(BeforeClass.class, AfterClass.class, Before.class, After.class)));
032    
033        /**
034         * Adds to {@code errors} a throwable for each problem detected. Looks for
035         * {@code BeforeClass}, {@code AfterClass}, {@code Before} and {@code After}
036         * annotations.
037         *
038         * @param method the method that is being validated
039         * @return A list of exceptions detected
040         *
041         * @since 4.12
042         */
043        @Override
044        public List<Exception> validateAnnotatedMethod(FrameworkMethod method) {
045            List<Exception> errors = new ArrayList<Exception>();
046            Annotation[] annotations = method.getAnnotations();
047            for (Annotation annotation : annotations) {
048                for (Class<?> clazz : INCOMPATIBLE_ANNOTATIONS) {
049                    if (annotation.annotationType().isAssignableFrom(clazz)) {
050                        addErrorMessage(errors, clazz);
051                    }
052                }
053            }
054            return unmodifiableList(errors);
055        }
056    
057        private void addErrorMessage(List<Exception> errors, Class<?> clazz) {
058            String message = String.format("@%s can not be combined with @Category",
059                    clazz.getSimpleName());
060            errors.add(new Exception(message));
061        }
062    }