package cuke4duke.internal.java; import cuke4duke.annotation.After; import cuke4duke.annotation.Before; import cuke4duke.annotation.Order; import cuke4duke.annotation.Transform; import cuke4duke.internal.Utils; import cuke4duke.internal.java.annotation.StepDef; import cuke4duke.internal.jvmclass.ClassAnalyzer; import cuke4duke.internal.jvmclass.ClassLanguage; import cuke4duke.internal.jvmclass.ObjectFactory; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.*; import java.util.regex.Pattern; public class JavaAnalyzer implements ClassAnalyzer { private final MethodFormat methodFormat; private static final String[] NO_TAGS = new String[0]; public JavaAnalyzer() { this.methodFormat = new MethodFormat(System.getProperty("cuke4duke.methodFormat", "%c.%m(%a)")); } public void populateStepDefinitionsAndHooks(ObjectFactory objectFactory, ClassLanguage classLanguage) throws Throwable { for (Method method : getOrderedMethods(classLanguage)) { registerBeforeMaybe(method, classLanguage); registerAfterMaybe(method, classLanguage); registerStepDefinitionsFromAnnotations(method, classLanguage); registerTransformMaybe(method, classLanguage); } } private void registerTransformMaybe(Method method, ClassLanguage classLanguage) { if (method.isAnnotationPresent(Transform.class)) { classLanguage.addTransform(method.getReturnType(), new JavaTransform(classLanguage, method)); } } public Class<?>[] alwaysLoad() { return new Class<?>[0]; } private List<Method> getOrderedMethods(ClassLanguage classLanguage) { Set<Method> methods = new HashSet<Method>(); for (Class<?> clazz : classLanguage.getClasses()) { methods.addAll(Arrays.asList(clazz.getMethods())); } List<Method> sortedMethods = new ArrayList<Method>(methods); Collections.sort(sortedMethods, new Comparator<Method>() { public int compare(Method m1, Method m2) { return order(m1) - order(m2); } private int order(Method m) { Order order = m.getAnnotation(Order.class); return (order == null) ? Integer.MAX_VALUE : order.value(); } }); return sortedMethods; } private void registerBeforeMaybe(Method method, ClassLanguage classLanguage) { if (method.isAnnotationPresent(Before.class)) { String[] tagExpressions = method.getAnnotation(Before.class).value(); if ("".equals(tagExpressions[0])) { tagExpressions = NO_TAGS; } classLanguage.addBeforeHook(new JavaHook(classLanguage, method, Arrays.asList(tagExpressions))); } } private void registerAfterMaybe(Method method, ClassLanguage classLanguage) { if (method.isAnnotationPresent(After.class)) { String[] tagExpressions = method.getAnnotation(After.class).value(); if ("".equals(tagExpressions[0])) { tagExpressions = NO_TAGS; } classLanguage.addAfterHook(new JavaHook(classLanguage, method, Arrays.asList(tagExpressions))); } } private void registerStepDefinitionsFromAnnotations(Method method, ClassLanguage classLanguage) throws Throwable { for (Annotation annotation : method.getAnnotations()) { if (annotation.annotationType().isAnnotationPresent(StepDef.class)) { Locale locale = Utils.localeFor(annotation.annotationType().getAnnotation(StepDef.class).value()); Method regexpMethod = annotation.getClass().getMethod("value"); String regexpString = (String) regexpMethod.invoke(annotation); if (regexpString != null) { Pattern regexp = Pattern.compile(regexpString); classLanguage.addStepDefinition(new JavaStepDefinition(classLanguage, method, regexp, methodFormat, locale)); } } } } }