AbstractStepsFactory.java
package org.jbehave.core.steps;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.jbehave.core.annotations.AsParameterConverter;
import org.jbehave.core.configuration.Configuration;
import org.jbehave.core.steps.ParameterConverters.MethodReturningConverter;
import org.jbehave.core.steps.ParameterConverters.ParameterConverter;
/**
* <p>
* An abstract implementation of {@link InjectableStepsFactory} that is provided
* by concrete subclasses Object instances which contain the candidate steps
* methods. The Object instances are wrapped by {@link Steps}.
* </p>
* <p>
* The object instances are also inspected for methods annotated by {@link AsParameterConverter}
* and the {@link ParameterConverter} is configured accordingly.
* </p>
*/
public abstract class AbstractStepsFactory implements InjectableStepsFactory {
private final Configuration configuration;
public AbstractStepsFactory(Configuration configuration) {
this.configuration = configuration;
}
@Override
public List<CandidateSteps> createCandidateSteps() {
List<Class<?>> types = stepsTypes();
List<CandidateSteps> steps = new ArrayList<>();
for (Class<?> type : types) {
configuration.parameterConverters().addConverters(
methodReturningConverters(type));
steps.add(new Steps(configuration, type, this));
}
Set<String> compositePaths = configuration.compositePaths();
if (!compositePaths.isEmpty()) {
steps.add(new CompositeCandidateSteps(configuration, compositePaths));
}
return steps;
}
protected abstract List<Class<?>> stepsTypes();
/**
* Create parameter converters from methods annotated with @AsParameterConverter
*/
private List<ParameterConverter> methodReturningConverters(Class<?> type) {
List<ParameterConverter> converters = new ArrayList<>();
for (Method method : type.getMethods()) {
if (method.isAnnotationPresent(AsParameterConverter.class)) {
converters.add(new MethodReturningConverter(method, type, this));
}
}
return converters;
}
/**
* Determines if the given type is a {@link Class} containing at least one method
* annotated with annotations from package "org.jbehave.core.annotations".
*
* @param type the Type of the steps instance
* @return A boolean, <code>true</code> if at least one annotated method is found.
*/
protected boolean hasAnnotatedMethods(Type type) {
if (type instanceof Class<?>) {
for (Method method : ((Class<?>) type).getMethods()) {
for (Annotation annotation : method.getAnnotations()) {
if (annotation.annotationType().getName().startsWith(
"org.jbehave.core.annotations")) {
return true;
}
}
}
}
return false;
}
@SuppressWarnings("serial")
public static class StepsInstanceNotFound extends RuntimeException {
public StepsInstanceNotFound(Class<?> type, InjectableStepsFactory stepsFactory) {
super("Steps instance not found for type " + type + " in factory " + stepsFactory);
}
}
}