Configuration.java

  1. package org.jbehave.core.configuration;

  2. import java.util.Collections;
  3. import java.util.Comparator;
  4. import java.util.Optional;
  5. import java.util.Set;

  6. import com.thoughtworks.paranamer.NullParanamer;
  7. import com.thoughtworks.paranamer.Paranamer;

  8. import org.jbehave.core.Embeddable;
  9. import org.jbehave.core.condition.ReflectionBasedStepConditionMatcher;
  10. import org.jbehave.core.condition.StepConditionMatcher;
  11. import org.jbehave.core.embedder.Embedder;
  12. import org.jbehave.core.embedder.StoryControls;
  13. import org.jbehave.core.expressions.ExpressionResolver;
  14. import org.jbehave.core.expressions.NullExpressionResolverMonitor;
  15. import org.jbehave.core.failures.FailingUponPendingStep;
  16. import org.jbehave.core.failures.FailureStrategy;
  17. import org.jbehave.core.failures.PassingUponPendingStep;
  18. import org.jbehave.core.failures.PendingStepStrategy;
  19. import org.jbehave.core.failures.RethrowingFailure;
  20. import org.jbehave.core.failures.SilentlyAbsorbingFailure;
  21. import org.jbehave.core.i18n.LocalizedKeywords;
  22. import org.jbehave.core.io.AbsolutePathCalculator;
  23. import org.jbehave.core.io.LoadFromClasspath;
  24. import org.jbehave.core.io.PathCalculator;
  25. import org.jbehave.core.io.StoryLoader;
  26. import org.jbehave.core.io.StoryPathResolver;
  27. import org.jbehave.core.io.UnderscoredCamelCaseResolver;
  28. import org.jbehave.core.model.ExamplesTableFactory;
  29. import org.jbehave.core.model.NullTableTransformerMonitor;
  30. import org.jbehave.core.model.Story;
  31. import org.jbehave.core.model.TableParsers;
  32. import org.jbehave.core.model.TableTransformerMonitor;
  33. import org.jbehave.core.model.TableTransformers;
  34. import org.jbehave.core.parsers.AliasParser;
  35. import org.jbehave.core.parsers.CompositeParser;
  36. import org.jbehave.core.parsers.JsonAliasParser;
  37. import org.jbehave.core.parsers.RegexCompositeParser;
  38. import org.jbehave.core.parsers.RegexPrefixCapturingPatternParser;
  39. import org.jbehave.core.parsers.RegexStoryParser;
  40. import org.jbehave.core.parsers.StepPatternParser;
  41. import org.jbehave.core.parsers.StoryParser;
  42. import org.jbehave.core.reporters.ConsoleOutput;
  43. import org.jbehave.core.reporters.FreemarkerViewGenerator;
  44. import org.jbehave.core.reporters.PrintStreamStepdocReporter;
  45. import org.jbehave.core.reporters.StepdocReporter;
  46. import org.jbehave.core.reporters.StoryReporter;
  47. import org.jbehave.core.reporters.StoryReporterBuilder;
  48. import org.jbehave.core.reporters.ViewGenerator;
  49. import org.jbehave.core.steps.MarkUnmatchedStepsAsPending;
  50. import org.jbehave.core.steps.ParameterControls;
  51. import org.jbehave.core.steps.ParameterConverters;
  52. import org.jbehave.core.steps.PrintStreamStepMonitor;
  53. import org.jbehave.core.steps.SilentStepMonitor;
  54. import org.jbehave.core.steps.StepCollector;
  55. import org.jbehave.core.steps.StepFinder;
  56. import org.jbehave.core.steps.StepMonitor;
  57. import org.jbehave.core.steps.context.StepsContext;

  58. /**
  59.  * <p>
  60.  * Provides the configuration used by the {@link Embedder} and the in the
  61.  * {@link Embeddable} implementations to customise its runtime properties.
  62.  * </p>
  63.  * <p>
  64.  * Configuration implements a <a
  65.  * href="http://en.wikipedia.org/wiki/Builder_pattern">Builder</a> pattern so
  66.  * that each element of the configuration can be specified individually, and
  67.  * read well. All elements have default values, which can be overridden by the
  68.  * "use" methods. The "use" methods allow to override the dependencies one by
  69.  * one and play nicer with a Java hierarchical structure, in that does allow the
  70.  * use of non-static member variables.
  71.  * </p>
  72.  */
  73. public abstract class Configuration {

  74.     /**
  75.      * Use default story controls
  76.      */
  77.     protected StoryControls storyControls;

  78.     /**
  79.      * Use English language for keywords
  80.      */
  81.     protected Keywords keywords;

  82.     /**
  83.      * Provides pending steps where unmatched steps exist.
  84.      */
  85.     protected StepCollector stepCollector;

  86.     /**
  87.      * Parses the textual representation via pattern matching of keywords
  88.      */
  89.     protected StoryParser storyParser;

  90.     /**
  91.      * Parses composite steps from their textual representation
  92.      */
  93.     protected CompositeParser compositeParser;

  94.     /**
  95.      * Loads story content from classpath
  96.      */
  97.     protected StoryLoader storyLoader;

  98.     /**
  99.      * Parse aliases from resources
  100.      */
  101.     protected AliasParser aliasParser;

  102.     /**
  103.      * Resolves story paths from class names using underscored camel case with
  104.      * ".story" extension
  105.      */
  106.     protected StoryPathResolver storyPathResolver;

  107.     /**
  108.      * Handles errors by re-throwing them.
  109.      * <p/>
  110.      * If there are multiple scenarios in a single story, this could cause the
  111.      * story to stop after the first failing scenario.
  112.      * <p/>
  113.      * Users wanting a different behaviour may use
  114.      * {@link SilentlyAbsorbingFailure}.
  115.      */
  116.     protected FailureStrategy failureStrategy;

  117.     /**
  118.      * Allows pending steps to pass, so that steps that to do not match any
  119.      * method will not cause failure.
  120.      * <p/>
  121.      * Uses wanting a stricter behaviour for pending steps may use
  122.      * {@link FailingUponPendingStep}.
  123.      */
  124.     protected PendingStepStrategy pendingStepStrategy;

  125.     /**
  126.      * Reports stories to console output
  127.      */
  128.     protected StoryReporter defaultStoryReporter;

  129.     /**
  130.      * The story reporter builder
  131.      */
  132.     protected StoryReporterBuilder storyReporterBuilder;

  133.     /**
  134.      * The steps context
  135.      */
  136.     protected StepsContext stepsContext;

  137.     /**
  138.      * Finder of matching candidate steps
  139.      */
  140.     protected StepFinder stepFinder;

  141.     /**
  142.      * Report candidate steps found to a PrintStream
  143.      */
  144.     protected StepdocReporter stepdocReporter;

  145.     /**
  146.      * Pattern build that uses prefix for identifying parameters
  147.      */
  148.     protected StepPatternParser stepPatternParser;

  149.     /**
  150.      * Controls of step parameterization
  151.      */
  152.     protected ParameterControls parameterControls;

  153.     /**
  154.      * Silent monitoring that does not produce any noise of the step matching.
  155.      * </p> If needed, users can switch on verbose monitoring using
  156.      * {@link PrintStreamStepMonitor}
  157.      */
  158.     protected StepMonitor stepMonitor;

  159.     /**
  160.      * Paranamer is switched off by default
  161.      */
  162.     protected Paranamer paranamer;

  163.     /**
  164.      * Use default built-in parameter converters
  165.      */
  166.     protected ParameterConverters parameterConverters;

  167.     /**
  168.      * Use default built-in expression resolver
  169.      */
  170.     protected ExpressionResolver expressionResolver;

  171.     /**
  172.      * Use default built-in ExamplesTable parsers
  173.      */
  174.     protected TableParsers tableParsers;

  175.     /**
  176.      * Use default built-in ExamplesTable transformers
  177.      */
  178.     protected TableTransformers tableTransformers;

  179.     /**
  180.      * Use Freemarker-based view generator
  181.      */
  182.     protected ViewGenerator viewGenerator;

  183.     /**
  184.      * Use an absolute path calculator
  185.      */
  186.     protected PathCalculator pathCalculator;

  187.     /**
  188.      * Paths to resources containing composite steps definitions
  189.      */
  190.     protected Set<String> compositePaths;

  191.     /**
  192.      * Paths to resources containing ailas definitions
  193.      */
  194.     protected Set<String> aliasPaths;

  195.     /**
  196.      * The examples table factory
  197.      */
  198.     protected ExamplesTableFactory examplesTableFactory;

  199.     /**
  200.      * The story execution comparator
  201.      */
  202.     protected Comparator<Story> storyExecutionComparator;

  203.     /**
  204.      * Enables parallelization of story level examples
  205.      */
  206.     private boolean parallelStoryExamplesEnabled;

  207.     /**
  208.      * The step condition matcher to match conditional steps
  209.      */
  210.     protected StepConditionMatcher stepConditionMatcher;

  211.     /**
  212.      * Monitor events of example table transformers
  213.      */
  214.     protected TableTransformerMonitor tableTransformerMonitor;

  215.     public Configuration() {
  216.     }

  217.     public Keywords keywords() {
  218.         if (keywords == null) {
  219.             keywords = new LocalizedKeywords();
  220.         }
  221.         return keywords;
  222.     }

  223.     public boolean dryRun() {
  224.         return storyControls().dryRun();
  225.     }

  226.     public StoryControls storyControls() {
  227.         if (storyControls == null) {
  228.             storyControls = new StoryControls();
  229.         }
  230.         return storyControls;
  231.     }

  232.     public StoryParser storyParser() {
  233.         if (storyParser == null) {
  234.             storyParser = new RegexStoryParser(examplesTableFactory());
  235.         }
  236.         return storyParser;
  237.     }

  238.     public CompositeParser compositeParser() {
  239.         if (compositeParser == null) {
  240.             compositeParser = new RegexCompositeParser(keywords());
  241.         }
  242.         return compositeParser;
  243.     }

  244.     public StoryLoader storyLoader() {
  245.         if (storyLoader == null) {
  246.             storyLoader = new LoadFromClasspath();
  247.         }
  248.         return storyLoader;
  249.     }

  250.     public AliasParser aliasParser() {
  251.         if (aliasParser == null) {
  252.             aliasParser = new JsonAliasParser(keywords());
  253.         }
  254.         return aliasParser;
  255.     }

  256.     public Comparator<Story> storyExecutionComparator() {
  257.         if (storyExecutionComparator == null) {
  258.             storyExecutionComparator = Comparator.comparing(Story::getPath, Comparator.naturalOrder());
  259.         }
  260.         return storyExecutionComparator;
  261.     }

  262.     public ExamplesTableFactory examplesTableFactory() {
  263.         if (examplesTableFactory == null) {
  264.             examplesTableFactory = new ExamplesTableFactory(keywords(), storyLoader(), parameterConverters(),
  265.                     parameterControls(), tableParsers(), tableTransformers(), tableTransformerMonitor());
  266.         }
  267.         return examplesTableFactory;
  268.     }

  269.     public StoryPathResolver storyPathResolver() {
  270.         if (storyPathResolver == null) {
  271.             storyPathResolver = new UnderscoredCamelCaseResolver();
  272.         }
  273.         return storyPathResolver;
  274.     }

  275.     public FailureStrategy failureStrategy() {
  276.         if (failureStrategy == null) {
  277.             failureStrategy = new RethrowingFailure();
  278.         }
  279.         return failureStrategy;
  280.     }

  281.     public PendingStepStrategy pendingStepStrategy() {
  282.         if (pendingStepStrategy == null) {
  283.             pendingStepStrategy = new PassingUponPendingStep();
  284.         }
  285.         return pendingStepStrategy;
  286.     }

  287.     public StoryReporter defaultStoryReporter() {
  288.         if (defaultStoryReporter == null) {
  289.             defaultStoryReporter = new ConsoleOutput();
  290.         }
  291.         return defaultStoryReporter;
  292.     }

  293.     public StoryReporter storyReporter(String storyPath) {
  294.         return storyReporterBuilder().build(storyPath);
  295.     }

  296.     public StoryReporterBuilder storyReporterBuilder() {
  297.         if (storyReporterBuilder == null) {
  298.             storyReporterBuilder = new StoryReporterBuilder();
  299.         }
  300.         return storyReporterBuilder;
  301.     }

  302.     public StepsContext stepsContext() {
  303.         if (stepsContext == null) {
  304.             stepsContext = new StepsContext();
  305.         }
  306.         return stepsContext;
  307.     }

  308.     public StepCollector stepCollector() {
  309.         if (stepCollector == null) {
  310.             stepCollector = new MarkUnmatchedStepsAsPending(stepFinder(), keywords());
  311.         }
  312.         return stepCollector;
  313.     }

  314.     public StepFinder stepFinder() {
  315.         if (stepFinder == null) {
  316.             stepFinder = new StepFinder(stepConditionMatcher());
  317.         }
  318.         return stepFinder;
  319.     }

  320.     public StepdocReporter stepdocReporter() {
  321.         if (stepdocReporter == null) {
  322.             stepdocReporter = new PrintStreamStepdocReporter();
  323.         }
  324.         return stepdocReporter;
  325.     }

  326.     public StepPatternParser stepPatternParser() {
  327.         if (stepPatternParser == null) {
  328.             stepPatternParser = new RegexPrefixCapturingPatternParser();
  329.         }
  330.         return stepPatternParser;
  331.     }

  332.     public ParameterControls parameterControls() {
  333.         if (parameterControls == null) {
  334.             parameterControls = new ParameterControls();
  335.         }
  336.         return parameterControls;
  337.     }

  338.     public StepMonitor stepMonitor() {
  339.         if (stepMonitor == null) {
  340.             stepMonitor = new SilentStepMonitor();
  341.         }
  342.         return stepMonitor;
  343.     }

  344.     public Paranamer paranamer() {
  345.         if (paranamer == null) {
  346.             paranamer = new NullParanamer();
  347.         }
  348.         return paranamer;
  349.     }

  350.     public ParameterConverters parameterConverters() {
  351.         if (parameterConverters == null) {
  352.             parameterConverters = new ParameterConverters(stepMonitor(), keywords(), storyLoader(), parameterControls(),
  353.                     tableTransformers());
  354.         }
  355.         return parameterConverters;
  356.     }

  357.     public ExpressionResolver expressionResolver() {
  358.         if (expressionResolver == null) {
  359.             expressionResolver = new ExpressionResolver(Collections.emptySet(), new NullExpressionResolverMonitor());
  360.         }
  361.         return expressionResolver;
  362.     }

  363.     public TableParsers tableParsers() {
  364.         if (tableParsers == null) {
  365.             tableParsers = new TableParsers(keywords(), parameterConverters(), Optional.empty());
  366.         }
  367.         return tableParsers;
  368.     }

  369.     public TableTransformers tableTransformers() {
  370.         if (tableTransformers == null) {
  371.             tableTransformers = new TableTransformers();
  372.         }
  373.         return tableTransformers;
  374.     }

  375.     public ViewGenerator viewGenerator() {
  376.         if (viewGenerator == null) {
  377.             viewGenerator = new FreemarkerViewGenerator();
  378.         }
  379.         return viewGenerator;
  380.     }

  381.     public PathCalculator pathCalculator() {
  382.         if (pathCalculator == null) {
  383.             pathCalculator = new AbsolutePathCalculator();
  384.         }
  385.         return pathCalculator;
  386.     }

  387.     public Set<String> compositePaths() {
  388.         if (compositePaths == null) {
  389.             compositePaths = Collections.emptySet();
  390.         }
  391.         return compositePaths;
  392.     }

  393.     public Set<String> aliasPaths() {
  394.         if (aliasPaths == null) {
  395.             aliasPaths = Collections.emptySet();
  396.         }
  397.         return aliasPaths;
  398.     }

  399.     public StepConditionMatcher stepConditionMatcher() {
  400.         if (stepConditionMatcher == null) {
  401.             stepConditionMatcher = new ReflectionBasedStepConditionMatcher();
  402.         }
  403.         return stepConditionMatcher;
  404.     }

  405.     public TableTransformerMonitor tableTransformerMonitor() {
  406.         if (tableTransformerMonitor == null) {
  407.             tableTransformerMonitor = new NullTableTransformerMonitor();
  408.         }
  409.         return tableTransformerMonitor;
  410.     }

  411.     public Configuration useStepConditionMatcher(StepConditionMatcher stepConditionMatcher) {
  412.         this.stepConditionMatcher = stepConditionMatcher;
  413.         return this;
  414.     }

  415.     public Configuration useKeywords(Keywords keywords) {
  416.         this.keywords = keywords;
  417.         return this;
  418.     }

  419.     public Configuration doDryRun(Boolean dryRun) {
  420.         this.storyControls().doDryRun(dryRun);
  421.         return this;
  422.     }

  423.     public Configuration useStoryControls(StoryControls storyControls) {
  424.         this.storyControls = storyControls;
  425.         return this;
  426.     }

  427.     public Configuration usePendingStepStrategy(PendingStepStrategy pendingStepStrategy) {
  428.         this.pendingStepStrategy = pendingStepStrategy;
  429.         return this;
  430.     }

  431.     public Configuration useFailureStrategy(FailureStrategy failureStrategy) {
  432.         this.failureStrategy = failureStrategy;
  433.         return this;
  434.     }

  435.     public Configuration useStoryParser(StoryParser storyParser) {
  436.         this.storyParser = storyParser;
  437.         return this;
  438.     }

  439.     public Configuration useCompositeParser(CompositeParser compositeParser) {
  440.         this.compositeParser = compositeParser;
  441.         return this;
  442.     }

  443.     public Configuration useStoryLoader(StoryLoader storyLoader) {
  444.         this.storyLoader = storyLoader;
  445.         return this;
  446.     }

  447.     public Configuration useAliasParser(AliasParser aliasParser) {
  448.         this.aliasParser = aliasParser;
  449.         return this;
  450.     }

  451.     public Configuration useExamplesTableFactory(ExamplesTableFactory examplesTableFactory) {
  452.         this.examplesTableFactory = examplesTableFactory;
  453.         return this;
  454.     }

  455.     public Configuration useStoryExecutionComparator(Comparator<Story> storyExecutionComparator) {
  456.         this.storyExecutionComparator = storyExecutionComparator;
  457.         return this;
  458.     }

  459.     public Configuration useStoryPathResolver(StoryPathResolver storyPathResolver) {
  460.         this.storyPathResolver = storyPathResolver;
  461.         return this;
  462.     }

  463.     public Configuration useDefaultStoryReporter(StoryReporter storyReporter) {
  464.         this.defaultStoryReporter = storyReporter;
  465.         return this;
  466.     }

  467.     public Configuration useStoryReporterBuilder(StoryReporterBuilder storyReporterBuilder) {
  468.         this.storyReporterBuilder = storyReporterBuilder;
  469.         return this;
  470.     }

  471.     public Configuration useStepCollector(StepCollector stepCollector) {
  472.         this.stepCollector = stepCollector;
  473.         return this;
  474.     }

  475.     public Configuration useStepFinder(StepFinder stepFinder) {
  476.         this.stepFinder = stepFinder;
  477.         return this;
  478.     }

  479.     public Configuration useStepdocReporter(StepdocReporter stepdocReporter) {
  480.         this.stepdocReporter = stepdocReporter;
  481.         return this;
  482.     }

  483.     public Configuration useStepPatternParser(StepPatternParser stepPatternParser) {
  484.         this.stepPatternParser = stepPatternParser;
  485.         return this;
  486.     }

  487.     public Configuration useParameterControls(ParameterControls parameterControls) {
  488.         this.parameterControls = parameterControls;
  489.         return this;
  490.     }

  491.     public Configuration useStepMonitor(StepMonitor stepMonitor) {
  492.         this.stepMonitor = stepMonitor;
  493.         return this;
  494.     }

  495.     public Configuration useParanamer(Paranamer paranamer) {
  496.         this.paranamer = paranamer;
  497.         return this;
  498.     }

  499.     public Configuration useParameterConverters(ParameterConverters parameterConverters) {
  500.         this.parameterConverters = parameterConverters;
  501.         return this;
  502.     }

  503.     public Configuration useExpressionResolver(ExpressionResolver expressionResolver) {
  504.         this.expressionResolver = expressionResolver;
  505.         return this;
  506.     }

  507.     public Configuration useTableTransformers(TableTransformers tableTransformers) {
  508.         this.tableTransformers = tableTransformers;
  509.         return this;
  510.     }

  511.     public Configuration useViewGenerator(ViewGenerator viewGenerator) {
  512.         this.viewGenerator = viewGenerator;
  513.         return this;
  514.     }

  515.     public Configuration usePathCalculator(PathCalculator pathCalculator) {
  516.         this.pathCalculator = pathCalculator;
  517.         return this;
  518.     }

  519.     public Configuration useCompositePaths(Set<String> compositePaths) {
  520.         this.compositePaths = compositePaths;
  521.         return this;
  522.     }

  523.     public Configuration useAliasPaths(Set<String> aliasPaths) {
  524.         this.aliasPaths = aliasPaths;
  525.         return this;
  526.     }

  527.     public boolean isParallelStoryExamplesEnabled() {
  528.         return parallelStoryExamplesEnabled;
  529.     }

  530.     public void setParallelStoryExamplesEnabled(boolean parallelStoryExamplesEnabled) {
  531.         this.parallelStoryExamplesEnabled = parallelStoryExamplesEnabled;
  532.     }

  533.     public Configuration useStepsContext(StepsContext stepsContext) {
  534.         this.stepsContext = stepsContext;
  535.         return this;
  536.     }

  537.     public Configuration useTableTransformerMonitor(TableTransformerMonitor tableTransformerMonitor) {
  538.         this.tableTransformerMonitor = tableTransformerMonitor;
  539.         return this;
  540.     }
  541. }