/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.test.runner.utils;
import static org.apache.commons.lang.ClassUtils.getAllInterfaces;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* Utility for annotations related stuff.
*
* @since 4.0
*/
public class AnnotationUtils {
private AnnotationUtils() {}
/**
* Looks for the {@link Annotation} in the {@link Class} and invokes the {@link Method}. It will return the result of the
* invocation. If there {@link Class} is not annotated it will return the default value from the {@link Annotation}.
*
* @param klass the {@link Class} where to look for the annotation
* @param annotationClass the {@link Annotation} class to look for
* @param methodName the method name of the annotation to be called
* @param <T> the result of the invocation
* @throws IllegalStateException if the method is not defined in the annotation
* @return the attribute from the annotation for the given class
*/
public static <T> T getAnnotationAttributeFrom(Class<?> klass, Class<? extends Annotation> annotationClass, String methodName) {
T extensions;
Annotation annotation = klass.getAnnotation(annotationClass);
Method method;
try {
method = annotationClass.getMethod(methodName);
if (annotation != null) {
extensions = (T) method.invoke(annotation);
} else {
extensions = (T) method.getDefaultValue();
}
} catch (Exception e) {
throw new IllegalStateException("Cannot read default " + methodName + " from " + annotationClass);
}
return extensions;
}
/**
* Looks for the {@link Annotation} in the {@link Class} and invokes the {@link Method} in the whole hierarhcy until it reaches
* {@link Object}. It will return a {@link List<T>} with the results of each invocation. If there {@link Class} is not annotated
* it will return the default value from the {@link Annotation}.
*
* @param klass the {@link Class} where to look for the annotation
* @param annotationClass the {@link Annotation} class to look for
* @param methodName the method name of the annotation to be called
* @param <T> the result of the invocation
* @throws IllegalStateException if the method is not defined in the annotation
* @return a (@link List} of T for the attributes annotated in all the object hierarchy until it reaches {@link Object} class.
*/
public static <T> List<T> getAnnotationAttributeFromHierarchy(Class<?> klass, Class<? extends Annotation> annotationClass,
String methodName) {
List<T> list = new ArrayList<>();
Class<?> currentClass = klass;
while (currentClass != Object.class) {
T attributeFrom = getAnnotationAttributeFrom(currentClass, annotationClass, methodName);
if (attributeFrom != null) {
list.add(attributeFrom);
}
currentClass = currentClass.getSuperclass();
}
getAllInterfaces(klass).forEach(currentInterfaceClass -> {
T attributeFrom = getAnnotationAttributeFrom((Class<?>) currentInterfaceClass, annotationClass, methodName);
if (attributeFrom != null) {
list.add(attributeFrom);
}
});
return list;
}
}