NeedleAnnotationBuilder.java

  1. package org.jbehave.core.configuration.needle;

  2. import java.util.HashSet;
  3. import java.util.List;
  4. import java.util.Set;

  5. import org.jbehave.core.annotations.UsingSteps;
  6. import org.jbehave.core.annotations.needle.UsingNeedle;
  7. import org.jbehave.core.configuration.AnnotationBuilder;
  8. import org.jbehave.core.configuration.AnnotationFinder;
  9. import org.jbehave.core.configuration.AnnotationMonitor;
  10. import org.jbehave.core.configuration.AnnotationRequired;
  11. import org.jbehave.core.configuration.Configuration;
  12. import org.jbehave.core.configuration.PrintStreamAnnotationMonitor;
  13. import org.jbehave.core.steps.InjectableStepsFactory;
  14. import org.jbehave.core.steps.needle.NeedleStepsFactory;
  15. import org.jbehave.core.steps.needle.configuration.CreateInstanceByDefaultConstructor;
  16. import org.needle4j.injection.InjectionProvider;
  17. import org.needle4j.injection.InjectionProviderInstancesSupplier;

  18. /**
  19.  * Extends {@link AnnotationBuilder} to provide Needle-based dependency injection if {@link UsingNeedle} annotation is
  20.  * present.
  21.  *
  22.  * @author Simon Zambrovski (simon.zambrovski@holisticon.de)
  23.  * @author Jan Galinski (jan.galinski@holisticon.de)
  24.  *
  25.  */
  26. public class NeedleAnnotationBuilder extends AnnotationBuilder {

  27.     private final Set<InjectionProvider<?>> provider = new HashSet<>();
  28.     private final Set<Class<?>> stepsClasses = new HashSet<>();
  29.     private NeedleStepsFactory factory;

  30.     public NeedleAnnotationBuilder(Class<?> annotatedClass, AnnotationMonitor annotationMonitor) {
  31.         super(annotatedClass, annotationMonitor);
  32.     }

  33.     public NeedleAnnotationBuilder(Class<?> annotatedClass) {
  34.         this(annotatedClass, new PrintStreamAnnotationMonitor());
  35.     }

  36.     @Override
  37.     public Configuration buildConfiguration() throws AnnotationRequired {

  38.         final AnnotationFinder finder = annotationFinder();

  39.         if (finder.isAnnotationPresent(UsingSteps.class)) {
  40.             stepsClasses.addAll(finder.getAnnotatedClasses(UsingSteps.class, Object.class, "instances"));
  41.         }

  42.         if (finder.isAnnotationPresent(UsingNeedle.class)) {

  43.             @SuppressWarnings("rawtypes")
  44.             final List<Class> supplierClasses = finder.getAnnotatedValues(UsingNeedle.class, Class.class, "supplier");
  45.             for (Class<InjectionProviderInstancesSupplier> supplierClass : supplierClasses) {
  46.                 provider.addAll(CreateInstanceByDefaultConstructor.INSTANCE.apply(supplierClass).get());
  47.             }

  48.             @SuppressWarnings("rawtypes")
  49.             final List<Class> providerClasses = finder.getAnnotatedValues(UsingNeedle.class, Class.class, "provider");
  50.             for (Class<InjectionProvider<?>> providerClass : providerClasses) {
  51.                 provider.add(CreateInstanceByDefaultConstructor.INSTANCE.apply(providerClass));
  52.             }

  53.         } else {
  54.             annotationMonitor().annotationNotFound(UsingNeedle.class, annotatedClass());
  55.         }
  56.         return super.buildConfiguration();
  57.     }

  58.     @Override
  59.     public InjectableStepsFactory buildStepsFactory(Configuration configuration) {
  60.         this.factory = new NeedleStepsFactory(configuration, provider, stepsClasses.toArray(new Class<?>[stepsClasses
  61.                 .size()]));
  62.         return factory;
  63.     }

  64.     @Override
  65.     @SuppressWarnings("unchecked")
  66.     protected <T, V extends T> T instanceOf(Class<T> type, Class<V> ofClass) {
  67.         /*
  68.          * This allow usage of the factory only after step factory is constructed. Current implementation only supports
  69.          * creation injection into steps. Further improvement will be to provide a needle factory capable of creating
  70.          * configuration parts.
  71.          */
  72.         if (factory != null) {
  73.             return (T) factory.createInstanceOfType(ofClass);
  74.         }
  75.         return super.instanceOf(type, ofClass);
  76.     }

  77.     /**
  78.      * Retrieves the set of injection providers.
  79.      *
  80.      * @return set of providers.
  81.      */
  82.     public Set<InjectionProvider<?>> getProvider() {
  83.         return provider;
  84.     }

  85.     /**
  86.      * Retrieve step classes.
  87.      *
  88.      * @return set of step classes.
  89.      */
  90.     public Set<Class<?>> getStepsClasses() {
  91.         return stepsClasses;
  92.     }
  93. }