Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
mpkorstanje committed May 26, 2024
1 parent e0906b3 commit d23d5d5
Show file tree
Hide file tree
Showing 10 changed files with 518 additions and 292 deletions.
33 changes: 27 additions & 6 deletions java/src/main/java/io/cucumber/query/Lineage.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,49 @@
* structure is simple enough to hard code.
*/
class Lineage {

private final GherkinDocument document;
private final Feature feature;
private final Rule rule;
private final Scenario scenario;
private final Examples examples;
private final TableRow example;
private final Integer examplesIndex;
private final TableRow example;
private final Integer exampleIndex;

Lineage(GherkinDocument document, Feature feature, Rule rule, Scenario scenario) {
this(document, feature, rule, scenario, null, null, null, null);
Lineage(GherkinDocument document) {
this(document, null, null, null, null, null, null, null);
}

Lineage(Lineage parent, Feature feature) {
this(parent.document, feature, null, null, null, null, null, null);
}

Lineage(Lineage parent, Rule rule) {
this(parent.document, parent.feature, rule, null, null, null, null, null);
}

Lineage(Lineage parent, Scenario scenario) {
this(parent.document, parent.feature, parent.rule, scenario, null, null, null, null);
}

Lineage(GherkinDocument document, Feature feature, Rule rule, Scenario scenario, Integer examplesIndex, Examples examples, Integer exampleIndex, TableRow example) {
Lineage(Lineage parent, Examples examples, int examplesIndex) {
this(parent.document, parent.feature, parent.rule, parent.scenario, examples, examplesIndex, null, null);
}

Lineage(Lineage parent, TableRow example, int exampleIndex) {
this(parent.document, parent.feature, parent.rule, parent.scenario, parent.examples, parent.examplesIndex, example, exampleIndex);
}

private Lineage(GherkinDocument document, Feature feature, Rule rule, Scenario scenario, Examples examples, Integer examplesIndex, TableRow example, Integer exampleIndex) {
this.document = requireNonNull(document);
this.feature = feature;
this.rule = rule;
this.scenario = scenario;
this.examplesIndex = examplesIndex;
this.examples = examples;
this.exampleIndex = exampleIndex;
this.examplesIndex = examplesIndex;
this.example = example;
this.exampleIndex = exampleIndex;
}

GherkinDocument document() {
Expand Down
37 changes: 37 additions & 0 deletions java/src/main/java/io/cucumber/query/LineageReducer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.cucumber.query;

import io.cucumber.messages.types.Examples;
import io.cucumber.messages.types.Feature;
import io.cucumber.messages.types.GherkinDocument;
import io.cucumber.messages.types.Pickle;
import io.cucumber.messages.types.Rule;
import io.cucumber.messages.types.Scenario;
import io.cucumber.messages.types.TableRow;

interface LineageReducer<T> {
default void add(GherkinDocument document) {

}
default void add(Feature feature) {

}

default void add(Rule rule) {

}

default void add(Scenario scenario) {

}

default void add(Examples examples, int index) {
}

default void add(TableRow example, int index) {
}

default void add(Pickle pickle) {
}

T finish();
}
51 changes: 51 additions & 0 deletions java/src/main/java/io/cucumber/query/LineageReducerStrategy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package io.cucumber.query;

import io.cucumber.messages.types.Pickle;

import java.util.function.Supplier;

import static java.util.Objects.requireNonNull;

/**
* TODO: Explain how this solves the lack of an AST that has nodes.
*
* @param <T>
*/
interface LineageReducerStrategy<T> {

T reduce(Lineage lineage);

T reduce(Lineage lineage, Pickle pickle);

class Descending<T> implements LineageReducerStrategy<T> {

private final Supplier<LineageReducer<T>> reducerSupplier;

Descending(Supplier<LineageReducer<T>> reducerSupplier) {
this.reducerSupplier = requireNonNull(reducerSupplier);
}

@Override
public T reduce(Lineage lineage) {
LineageReducer<T> reducer = reducerSupplier.get();
reduceAddLineage(reducer, lineage);
return reducer.finish();
}

@Override
public T reduce(Lineage lineage, Pickle pickle) {
LineageReducer<T> reducer = reducerSupplier.get();
reduceAddLineage(reducer, lineage);
reducer.add(pickle);
return reducer.finish();
}

private static <T> void reduceAddLineage(LineageReducer<T> reducer, Lineage lineage) {
lineage.feature().ifPresent(reducer::add);
lineage.rule().ifPresent(reducer::add);
lineage.scenario().ifPresent(reducer::add);
lineage.examples().ifPresent(examples -> reducer.add(examples, lineage.examplesIndex().orElse(0)));
lineage.example().ifPresent(example -> reducer.add(example, lineage.exampleIndex().orElse(0)));
}
}
}
100 changes: 0 additions & 100 deletions java/src/main/java/io/cucumber/query/LineageVisitingStrategy.java

This file was deleted.

82 changes: 82 additions & 0 deletions java/src/main/java/io/cucumber/query/Lineages.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package io.cucumber.query;

import io.cucumber.messages.types.Examples;
import io.cucumber.messages.types.Feature;
import io.cucumber.messages.types.FeatureChild;
import io.cucumber.messages.types.GherkinDocument;
import io.cucumber.messages.types.Rule;
import io.cucumber.messages.types.RuleChild;
import io.cucumber.messages.types.Scenario;
import io.cucumber.messages.types.TableRow;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

class Lineages {

static Map<Object, Lineage> of(GherkinDocument document) {
Map<Object, Lineage> elements = new HashMap<>();
Lineage lineage = new Lineage(document);
elements.put(document, lineage);
document.getFeature().ifPresent(ofFeature(lineage, elements));
return elements;
}

private static Consumer<Feature> ofFeature(Lineage parent, Map<Object, Lineage> elements) {
return feature -> {
Lineage lineage = new Lineage(parent, feature);
feature.getChildren().forEach(ofFeatureChild(lineage, elements));
};
}

private static Consumer<FeatureChild> ofFeatureChild(Lineage parent, Map<Object, Lineage> elements) {
return featureChild -> {
featureChild.getScenario().ifPresent(ofScenario(parent, elements));
featureChild.getRule().ifPresent(ofRule(parent, elements));
};
}

private static Consumer<Rule> ofRule(Lineage parent, Map<Object, Lineage> elements) {
return rule -> {
Lineage lineage = new Lineage(parent, rule);
elements.put(rule.getId(), lineage);
rule.getChildren().forEach(ofRuleChild(lineage, elements));
};
}

private static Consumer<RuleChild> ofRuleChild(Lineage parent, Map<Object, Lineage> elements) {
return ruleChild -> ruleChild.getScenario().ifPresent(ofScenario(parent, elements));
}

private static Consumer<Scenario> ofScenario(Lineage parent, Map<Object, Lineage> elements) {
return scenario -> {
Lineage lineage = new Lineage(parent, scenario);
elements.put(scenario.getId(), lineage);
forEachIndexed(scenario.getExamples(), ofExamples(lineage, elements));
};
}

private static BiConsumer<Examples, Integer> ofExamples(Lineage parent, Map<Object, Lineage> elements) {
return (examples, examplesIndex) -> {
Lineage lineage = new Lineage(parent, examples, examplesIndex);
elements.put(examples.getId(), lineage);
forEachIndexed(examples.getTableBody(), ofExample(lineage, elements));
};
}

private static BiConsumer<TableRow, Integer> ofExample(Lineage parent, Map<Object, Lineage> elements) {
return (example, exampleIndex) -> {
Lineage lineage = new Lineage(parent, example, exampleIndex);
elements.put(example.getId(), lineage);
};
}

private static <T> void forEachIndexed(List<T> items, BiConsumer<T, Integer> consumer) {
for (int i = 0; i < items.size(); i++) {
consumer.accept(items.get(i), i);
}
}
}
Loading

0 comments on commit d23d5d5

Please sign in to comment.