package org.test4j.module.core.utility;
import static ext.test4j.apache.commons.lang.ClassUtils.getShortClassName;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.test4j.module.Test4JException;
import org.test4j.module.core.Module;
import org.test4j.tools.commons.ClazzHelper;
import org.test4j.tools.commons.ConfigHelper;
@SuppressWarnings("rawtypes")
public class ModuleHelper {
/**
* The default name of the default enum value.
*/
public static final String DEFAULT_ENUM_VALUE_NAME = "DEFAULT";
/**
* Returns an object that represents the default values for the properties
* of the given annotations and the given module.
*
* @param moduleClass The class of the module for which we want the default
* annotation property values
* @param configuration The test4j configuration
* @param annotationClasses The annotations for which we want the default
* values
* @return An object that returns the annotation property default values
*/
public static Map<Class<? extends Annotation>, Map<String, String>> getAnnotationPropertyDefaults(Class<? extends Module> moduleClass,
Class<? extends Annotation>... annotationClasses) {
Map<Class<? extends Annotation>, Map<String, String>> result = new HashMap<Class<? extends Annotation>, Map<String, String>>();
for (Class<? extends Annotation> annotationClass : annotationClasses) {
Method[] methods = annotationClass.getDeclaredMethods();
for (Method method : methods) {
String defaultValue = getAnnotationPropertyDefault(moduleClass, annotationClass, method.getName());
Map<String, String> defaultValueMap = result.get(annotationClass);
if (defaultValueMap == null) {
defaultValueMap = new HashMap<String, String>();
result.put(annotationClass, defaultValueMap);
}
defaultValueMap.put(method.getName(), defaultValue);
}
}
return result;
}
/**
* Returns the default for annotation property of the given annotation with
* the given name for the given moduleclass.
*
* @param moduleClass The module class, not null
* @param annotationClass The annotation class, not null
* @param name The property suffix, not null
* @param configuration The test4j config, not null
* @return the default value
*/
private static String getAnnotationPropertyDefault(Class<? extends Module> moduleClass,
Class<? extends Annotation> annotationClass, String name) {
String propertyName = getShortClassName(moduleClass) + "." + getShortClassName(annotationClass) + "." + name
+ ".default";
if (!ConfigHelper.hasProperty(propertyName)) {
return null;
}
return ConfigHelper.getString(propertyName);
}
/**
* Replaces default enum value with the given default enum value. If
* enumValue contains the value {@link #DEFAULT_ENUM_VALUE_NAME} the
* defaultValue will be returned otherwise the enumValue itself will be
* returned.
*
* @param annotation the annotation, not null
* @param annotationPropertyName the name of the annotation property
* @param enumValue the value to check, not null
* @param allDefaultValues the map with values to return in case of a
* default, not null
* @return the enumValue or the defaultValue in case of a default
*/
public static <T extends Enum<?>> T getEnumValueReplaceDefault(Class<? extends Annotation> annotation,
String annotationPropertyName,
T enumValue,
Map<Class<? extends Annotation>, Map<String, String>> allDefaultValues) {
return getEnumValueReplaceDefault(annotation, annotationPropertyName, enumValue, allDefaultValues,
DEFAULT_ENUM_VALUE_NAME);
}
/**
* Replaces default enum value with the given default enum value. If
* enumValue contains the value {@link #DEFAULT_ENUM_VALUE_NAME} the
* defaultValue will be returned otherwise the enumValue itself will be
* returned.
*
* @param annotation the annotation, not null
* @param annotationPropertyName the name of the annotation property
* @param enumValue the value to check, not null
* @param allDefaultValues the map with values to return in case of a
* default, not null
* @param defaultValueName the name of the default value
* @return the enumValue or the defaultValue in case of a default
*/
@SuppressWarnings({ "unchecked" })
private static <T extends Enum<?>> T getEnumValueReplaceDefault(Class<? extends Annotation> annotation,
String annotationPropertyName,
T enumValue,
Map<Class<? extends Annotation>, Map<String, String>> allDefaultValues,
String defaultValueName) {
String valueAsString = getValueAsStringReplaceDefault(annotation, annotationPropertyName, enumValue.name(),
allDefaultValues, defaultValueName);
return (T) ClazzHelper.getEnumValue(enumValue.getClass(), valueAsString);
}
/**
* Replaces default enum value with the given default enum value. If
* enumValue contains the value {@link #DEFAULT_ENUM_VALUE_NAME} the
* defaultValue will be returned otherwise the enumValue itself will be
* returned.
*
* @param annotation the annotation, not null
* @param annotationPropertyName the name of the annotation property
* @param value the value to check, not null
* @param allDefaultValues the map with values to return in case of a
* default, not null
* @param defaultValueClass the name of the default value
* @return the enumValue or the defaultValue in case of a default
*/
public static Class getClassValueReplaceDefault(Class<? extends Annotation> annotation,
String annotationPropertyName,
Class value,
Map<Class<? extends Annotation>, Map<String, String>> allDefaultValues,
Class defaultValueClass) {
String valueAsString = getValueAsStringReplaceDefault(annotation, annotationPropertyName, value.getName(),
allDefaultValues, defaultValueClass.getName());
return ClazzHelper.getClazz(valueAsString);
}
/**
* Replaces default enum values with the given default enum value. If
* enumValue contains the value defaultValueName, the defaultValue will be
* returned otherwise the enumValue itself will be returned.
*
* @param annotation the annotation, not null
* @param annotationProperty the annotation property for which the value
* must be replaced, not null
* @param valueAsString the value to check, not null
* @param allDefaultValues the map with values to return in case of a
* default, not null
* @param defaultValueName the name of the default value, eg DEFAULT, not
* null @return the enumValue or the defaultValue in case of a
* default
* @return The default value as a string
*/
private static String getValueAsStringReplaceDefault(Class<? extends Annotation> annotation,
String annotationProperty,
String valueAsString,
Map<Class<? extends Annotation>, Map<String, String>> allDefaultValues,
String defaultValueName) {
if (!defaultValueName.equalsIgnoreCase(valueAsString)) {
// no replace needed
return valueAsString;
}
Map<String, String> defaultValues = allDefaultValues.get(annotation);
if (defaultValues != null) {
String defaultValueAsString = defaultValues.get(annotationProperty);
if (defaultValueAsString != null) {
return defaultValueAsString;
}
}
// nothing found, raise exception
throw new Test4JException("Could not replace default value. No default value found for annotation: "
+ annotation + ", property " + annotationProperty + ", defaultValues: " + allDefaultValues);
}
}