AllStepCandidates.java
- package org.jbehave.core.embedder;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Comparator;
- import java.util.EnumMap;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Optional;
- import java.util.stream.Collector;
- import java.util.stream.Collector.Characteristics;
- import java.util.stream.Collectors;
- import org.jbehave.core.annotations.Conditional;
- import org.jbehave.core.annotations.ScenarioType;
- import org.jbehave.core.condition.StepConditionMatcher;
- import org.jbehave.core.steps.BeforeOrAfterStep;
- import org.jbehave.core.steps.CandidateSteps;
- import org.jbehave.core.steps.ConditionalStepCandidate;
- import org.jbehave.core.steps.StepCandidate;
- public class AllStepCandidates {
- private final List<BeforeOrAfterStep> beforeStoriesSteps = new ArrayList<>();
- private final List<BeforeOrAfterStep> afterStoriesSteps = new ArrayList<>();
- private final List<BeforeOrAfterStep> beforeGivenStorySteps = new ArrayList<>();
- private final List<BeforeOrAfterStep> afterGivenStorySteps = new ArrayList<>();
- private final List<BeforeOrAfterStep> beforeStorySteps = new ArrayList<>();
- private final List<BeforeOrAfterStep> afterStorySteps = new ArrayList<>();
- private final Map<ScenarioType, List<BeforeOrAfterStep>> beforeScenarioSteps = new EnumMap<>(ScenarioType.class);
- private final Map<ScenarioType, List<BeforeOrAfterStep>> afterScenarioSteps = new EnumMap<>(ScenarioType.class);
- private final List<StepCandidate> regularSteps;
- public AllStepCandidates(StepConditionMatcher stepConditionMatcher, List<CandidateSteps> candidateSteps) {
- for (ScenarioType type : ScenarioType.values()) {
- beforeScenarioSteps.put(type, new ArrayList<>());
- afterScenarioSteps.put(type, new ArrayList<>());
- }
- for (CandidateSteps candidateStep : candidateSteps) {
- beforeStoriesSteps.addAll(candidateStep.listBeforeStories());
- afterStoriesSteps.addAll(candidateStep.listAfterStories());
- beforeGivenStorySteps.addAll(candidateStep.listBeforeStory(true));
- afterGivenStorySteps.addAll(candidateStep.listAfterStory(true));
- beforeStorySteps.addAll(candidateStep.listBeforeStory(false));
- afterStorySteps.addAll(candidateStep.listAfterStory(false));
- candidateStep.listBeforeScenario().forEach(
- (scenarioType, steps) -> beforeScenarioSteps.get(scenarioType).addAll(steps));
- candidateStep.listAfterScenario().forEach(
- (scenarioType, steps) -> afterScenarioSteps.get(scenarioType).addAll(steps));
- }
- this.regularSteps = candidateSteps.stream()
- .map(CandidateSteps::listCandidates)
- .flatMap(List::stream)
- .collect(stepCandidateCollector())
- .entrySet()
- .stream()
- .map(e -> {
- List<StepCandidate> candidates = e.getValue();
- boolean allCandidatesConditional = areAllCandidatesConditional(candidates);
- if (allCandidatesConditional) {
- return ConditionalStepCandidate.from(stepConditionMatcher, candidates);
- }
- if (candidates.size() == 1) {
- return candidates.get(0);
- }
- throw new DuplicateCandidateFound(e.getKey());
- })
- .collect(Collectors.toList());
- sortBeforeSteps(beforeStoriesSteps);
- sortAfterSteps(afterStoriesSteps);
- sortBeforeSteps(beforeGivenStorySteps);
- sortAfterSteps(afterGivenStorySteps);
- sortBeforeSteps(beforeStorySteps);
- sortAfterSteps(afterStorySteps);
- beforeScenarioSteps.values().forEach(this::sortBeforeSteps);
- afterScenarioSteps.values().forEach(this::sortAfterSteps);
- }
- private void sortBeforeSteps(List<BeforeOrAfterStep> beforeSteps) {
- sortSteps(beforeSteps, Comparator.reverseOrder());
- }
- private void sortAfterSteps(List<BeforeOrAfterStep> afterSteps) {
- sortSteps(afterSteps, Comparator.naturalOrder());
- }
- private void sortSteps(List<BeforeOrAfterStep> steps, Comparator<Integer> comparator) {
- steps.sort(Comparator.comparing(BeforeOrAfterStep::getOrder, comparator));
- }
- public List<BeforeOrAfterStep> getBeforeStoriesSteps() {
- return beforeStoriesSteps;
- }
- public List<BeforeOrAfterStep> getAfterStoriesSteps() {
- return afterStoriesSteps;
- }
- public List<BeforeOrAfterStep> getBeforeStorySteps(boolean givenStory) {
- return givenStory ? beforeGivenStorySteps : beforeStorySteps;
- }
- public List<BeforeOrAfterStep> getAfterStorySteps(boolean givenStory) {
- return givenStory ? afterGivenStorySteps : afterStorySteps;
- }
- public List<BeforeOrAfterStep> getBeforeScenarioSteps(ScenarioType scenarioType) {
- return beforeScenarioSteps.get(scenarioType);
- }
- public List<BeforeOrAfterStep> getAfterScenarioSteps(ScenarioType scenarioType) {
- return afterScenarioSteps.get(scenarioType);
- }
- public List<StepCandidate> getRegularSteps() {
- return regularSteps;
- }
- private static Collector<StepCandidate, Map<String, List<StepCandidate>>, Map<String, List<StepCandidate>>>
- stepCandidateCollector() {
- return Collector.of(HashMap::new, (map, candidate) -> {
- String candidateWording = candidate.getStartingWord() + " " + candidate.getPatternAsString();
- Optional<String> candidateKey = map.keySet().stream()
- .filter(k -> candidate.matches(k) && map.get(k).stream().allMatch(c -> c.matches(candidateWording)))
- .findFirst();
- List<StepCandidate> candidates;
- if (candidateKey.isPresent()) {
- candidates = map.get(candidateKey.get());
- } else {
- candidates = new ArrayList<>();
- map.put(candidateWording, candidates);
- }
- candidates.add(candidate);
- }, (l, r) -> l, Characteristics.IDENTITY_FINISH);
- }
- private boolean areAllCandidatesConditional(Collection<StepCandidate> candidates) {
- return candidates.stream()
- .map(StepCandidate::getMethod)
- .allMatch(m -> m != null
- && (m.isAnnotationPresent(Conditional.class)
- || m.getDeclaringClass().isAnnotationPresent(Conditional.class)));
- }
- }