AnnotationFinder.java

package org.jbehave.core.configuration;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

/**
 * Helper class to find and retrieve annotated values
 * 
 * @author Cristiano GaviĆ£o
 * @author Brian Repko
 * @author Mauro Talevi
 */
public class AnnotationFinder {

    private final Class<?> annotatedClass;

    public AnnotationFinder(Class<?> annotatedClass) {
        this.annotatedClass = annotatedClass;
    }

    public <A extends Annotation> boolean isAnnotationPresent(Class<A> annotationClass) {
        return getAnnotation(annotationClass) != null;
    }

    public <A extends Annotation> boolean isAnnotationValuePresent(Class<A> annotationClass, String memberName) {
        Annotation annotation = getAnnotation(annotationClass);
        return annotation != null && getAnnotationValue(annotation, memberName) != null;
    }

    @SuppressWarnings("unchecked")
    public <T, A extends Annotation> T getAnnotatedValue(Class<A> annotationClass, Class<T> memberType,
            String memberName) {
        Annotation annotation = getAnnotation(annotationClass);
        if (annotation != null) {
            return (T) getAnnotationValue(annotation, memberName);
        }
        throw new AnnotationRequired(annotatedClass, annotationClass);
    }

    @SuppressWarnings("unchecked")
    public <T, A extends Annotation> List<T> getAnnotatedValues(Class<A> annotationClass, Class<T> type,
            String memberName) {
        Set<T> set = new LinkedHashSet<>();
        if (!isAnnotationPresent(annotationClass)) {
            return new ArrayList<>(set);
        }
        Object[] values = getAnnotatedValue(annotationClass, Object[].class, memberName);
        for (Object value : values) {
            set.add((T) value);
        }
        boolean inheritValues = true;
        String inheritMemberName = createInheritMemberName(memberName);
        if (isAnnotationValuePresent(annotationClass, inheritMemberName)) {
            inheritValues = getAnnotatedValue(annotationClass, boolean.class, inheritMemberName);
        }
        if (inheritValues) {
            Class<?> superClass = annotatedClass.getSuperclass();
            if (superClass != null && superClass != Object.class) {
                set.addAll(new AnnotationFinder(superClass).getAnnotatedValues(annotationClass, type, memberName));
            }
        }
        return new ArrayList<>(set);
    }

    /**
     * Creates the inherit member name by prefixing "inherit" to the capitalized member name.
     * 
     * @param memberName the initial member name
     * @return The inherit member name
     */
    protected String createInheritMemberName(String memberName) {
        return "inherit" + StringUtils.capitalize(memberName);
    }

    @SuppressWarnings("unchecked")
    public <T, A extends Annotation> List<Class<T>> getAnnotatedClasses(Class<A> annotationClass, Class<T> type,
            String memberName) {
        return (List<Class<T>>) getAnnotatedValues(annotationClass, type.getClass(), memberName);
    }

    protected <A extends Annotation> Annotation getAnnotation(Class<A> annotationClass) {
        return annotatedClass.getAnnotation(annotationClass);
    }

    protected Object getAnnotationValue(Annotation annotation, String attributeName) {
        try {
            Method method = annotation.annotationType().getDeclaredMethod(attributeName);
            return method.invoke(annotation);
        } catch (Exception e) {
            return null;
        }
    }
}