NeedleAnnotationBuilder.java
package org.jbehave.core.configuration.needle;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.jbehave.core.annotations.UsingSteps;
import org.jbehave.core.annotations.needle.UsingNeedle;
import org.jbehave.core.configuration.AnnotationBuilder;
import org.jbehave.core.configuration.AnnotationFinder;
import org.jbehave.core.configuration.AnnotationMonitor;
import org.jbehave.core.configuration.AnnotationRequired;
import org.jbehave.core.configuration.Configuration;
import org.jbehave.core.configuration.PrintStreamAnnotationMonitor;
import org.jbehave.core.steps.InjectableStepsFactory;
import org.jbehave.core.steps.needle.NeedleStepsFactory;
import org.jbehave.core.steps.needle.configuration.CreateInstanceByDefaultConstructor;
import org.needle4j.injection.InjectionProvider;
import org.needle4j.injection.InjectionProviderInstancesSupplier;
/**
* Extends {@link AnnotationBuilder} to provide Needle-based dependency injection if {@link UsingNeedle} annotation is
* present.
*
* @author Simon Zambrovski (simon.zambrovski@holisticon.de)
* @author Jan Galinski (jan.galinski@holisticon.de)
*
*/
public class NeedleAnnotationBuilder extends AnnotationBuilder {
private final Set<InjectionProvider<?>> provider = new HashSet<>();
private final Set<Class<?>> stepsClasses = new HashSet<>();
private NeedleStepsFactory factory;
public NeedleAnnotationBuilder(Class<?> annotatedClass, AnnotationMonitor annotationMonitor) {
super(annotatedClass, annotationMonitor);
}
public NeedleAnnotationBuilder(Class<?> annotatedClass) {
this(annotatedClass, new PrintStreamAnnotationMonitor());
}
@Override
public Configuration buildConfiguration() throws AnnotationRequired {
final AnnotationFinder finder = annotationFinder();
if (finder.isAnnotationPresent(UsingSteps.class)) {
stepsClasses.addAll(finder.getAnnotatedClasses(UsingSteps.class, Object.class, "instances"));
}
if (finder.isAnnotationPresent(UsingNeedle.class)) {
@SuppressWarnings("rawtypes")
final List<Class> supplierClasses = finder.getAnnotatedValues(UsingNeedle.class, Class.class, "supplier");
for (Class<InjectionProviderInstancesSupplier> supplierClass : supplierClasses) {
provider.addAll(CreateInstanceByDefaultConstructor.INSTANCE.apply(supplierClass).get());
}
@SuppressWarnings("rawtypes")
final List<Class> providerClasses = finder.getAnnotatedValues(UsingNeedle.class, Class.class, "provider");
for (Class<InjectionProvider<?>> providerClass : providerClasses) {
provider.add(CreateInstanceByDefaultConstructor.INSTANCE.apply(providerClass));
}
} else {
annotationMonitor().annotationNotFound(UsingNeedle.class, annotatedClass());
}
return super.buildConfiguration();
}
@Override
public InjectableStepsFactory buildStepsFactory(Configuration configuration) {
this.factory = new NeedleStepsFactory(configuration, provider, stepsClasses.toArray(new Class<?>[stepsClasses
.size()]));
return factory;
}
@Override
@SuppressWarnings("unchecked")
protected <T, V extends T> T instanceOf(Class<T> type, Class<V> ofClass) {
/*
* This allow usage of the factory only after step factory is constructed. Current implementation only supports
* creation injection into steps. Further improvement will be to provide a needle factory capable of creating
* configuration parts.
*/
if (factory != null) {
return (T) factory.createInstanceOfType(ofClass);
}
return super.instanceOf(type, ofClass);
}
/**
* Retrieves the set of injection providers.
*
* @return set of providers.
*/
public Set<InjectionProvider<?>> getProvider() {
return provider;
}
/**
* Retrieve step classes.
*
* @return set of step classes.
*/
public Set<Class<?>> getStepsClasses() {
return stepsClasses;
}
}