001package org.junit.experimental.categories;
002
003import static java.util.Arrays.asList;
004import static java.util.Collections.unmodifiableList;
005import static java.util.Collections.unmodifiableSet;
006
007import java.lang.annotation.Annotation;
008import java.util.ArrayList;
009import java.util.HashSet;
010import java.util.List;
011import java.util.Set;
012
013import org.junit.After;
014import org.junit.AfterClass;
015import org.junit.Before;
016import org.junit.BeforeClass;
017import org.junit.runners.model.FrameworkMethod;
018import 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 */
027public 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}