All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cucumber.runtime.RuntimeGlue Maven / Gradle / Ivy

There is a newer version: 7.18.1
Show newest version
package cucumber.runtime;

import io.cucumber.stepexpression.Argument;
import cucumber.api.StepDefinitionReporter;
import gherkin.pickles.PickleStep;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class RuntimeGlue implements Glue {
    final Map stepDefinitionsByPattern = new TreeMap();
    final List beforeHooks = new ArrayList();
    final List beforeStepHooks = new ArrayList();
    final List afterHooks = new ArrayList();
    final List afterStepHooks = new ArrayList();
    final Map matchedStepDefinitionsCache = new HashMap();

    @Override
    public void addStepDefinition(StepDefinition stepDefinition) {
        StepDefinition previous = stepDefinitionsByPattern.get(stepDefinition.getPattern());
        if (previous != null) {
            throw new DuplicateStepDefinitionException(previous, stepDefinition);
        }
        stepDefinitionsByPattern.put(stepDefinition.getPattern(), stepDefinition);
    }

    @Override
    public void addBeforeHook(HookDefinition hookDefinition) {
        beforeHooks.add(hookDefinition);
        Collections.sort(beforeHooks, new HookComparator(true));
    }

    @Override
    public void addBeforeStepHook(HookDefinition hookDefinition) {
        beforeStepHooks.add(hookDefinition);
        Collections.sort(beforeStepHooks, new HookComparator(true));
    }
    @Override
    public void addAfterHook(HookDefinition hookDefinition) {
        afterHooks.add(hookDefinition);
        Collections.sort(afterHooks, new HookComparator(false));
    }

    @Override
    public void addAfterStepHook(HookDefinition hookDefinition) {
        afterStepHooks.add(hookDefinition);
        Collections.sort(afterStepHooks, new HookComparator(false));
    }

    @Override
    public List getBeforeHooks() {
        return beforeHooks;
    }

    @Override
    public List getBeforeStepHooks() {
        return beforeStepHooks;
    }

    @Override
    public List getAfterHooks() {
        return afterHooks;
    }

    @Override
    public List getAfterStepHooks() {
        return afterStepHooks;
    }

    @Override
    public PickleStepDefinitionMatch stepDefinitionMatch(String featurePath, PickleStep step) {
        String stepText = step.getText();

        CacheEntry cacheEntry = matchedStepDefinitionsCache.get(stepText);
        if (cacheEntry != null) {
            return new PickleStepDefinitionMatch(Collections.emptyList(), cacheEntry.stepDefinition, featurePath, step);
        }

        List matches = stepDefinitionMatches(featurePath, step);
        if (matches.isEmpty()) {
            return null;
        }
        if (matches.size() > 1) {
            throw new AmbiguousStepDefinitionsException(step, matches);
        }

        PickleStepDefinitionMatch match = matches.get(0);

        // We can only cache step definitions without arguments.
        // DocString and TableArguments are not included in the stepText used as the cache key.
        if(match.getArguments().isEmpty()) {
            matchedStepDefinitionsCache.put(stepText, new CacheEntry(match.getStepDefinition()));
        }

        return match;
    }

    private List stepDefinitionMatches(String featurePath, PickleStep step) {
        List result = new ArrayList();
        for (StepDefinition stepDefinition : stepDefinitionsByPattern.values()) {
            List arguments = stepDefinition.matchedArguments(step);
            if (arguments != null) {
                result.add(new PickleStepDefinitionMatch(arguments, stepDefinition, featurePath, step));
            }
        }
        return result;
    }

    @Override
    public void reportStepDefinitions(StepDefinitionReporter stepDefinitionReporter) {
        for (StepDefinition stepDefinition : stepDefinitionsByPattern.values()) {
            stepDefinitionReporter.stepDefinition(stepDefinition);
        }
    }

    @Override
    public void removeScenarioScopedGlue() {
        removeScenarioScopedHooks(beforeHooks);
        removeScenarioScopedHooks(beforeStepHooks);
        removeScenarioScopedHooks(afterHooks);
        removeScenarioScopedHooks(afterStepHooks);
        removeScenarioScopedStepdefs();
    }

    private void removeScenarioScopedHooks(List beforeHooks1) {
        Iterator hookIterator = beforeHooks1.iterator();
        while (hookIterator.hasNext()) {
            HookDefinition hook = hookIterator.next();
            if (hook.isScenarioScoped()) {
                hookIterator.remove();
            }
        }
    }

    private void removeScenarioScopedStepdefs() {
        Iterator> stepdefs = stepDefinitionsByPattern.entrySet().iterator();
        while (stepdefs.hasNext()) {
            StepDefinition stepDefinition = stepdefs.next().getValue();
            if (stepDefinition.isScenarioScoped()) {
                stepdefs.remove();
            }
        }

        Iterator> cachedStepDefs = matchedStepDefinitionsCache.entrySet().iterator();
        while(cachedStepDefs.hasNext()){
            StepDefinition stepDefinition = cachedStepDefs.next().getValue().stepDefinition;
            if(stepDefinition.isScenarioScoped()){
                cachedStepDefs.remove();
            }
        }
    }

    static final class CacheEntry {

        StepDefinition stepDefinition;

        private CacheEntry(StepDefinition stepDefinition) {
            this.stepDefinition = stepDefinition;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy