Skip to content

Commit 58aad0b

Browse files
committed
WIP
1 parent b53ba40 commit 58aad0b

File tree

9 files changed

+161
-112
lines changed

9 files changed

+161
-112
lines changed

java/src/main/java/io/cucumber/query/Lineage.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import java.util.Objects;
1111
import java.util.Optional;
12+
import java.util.function.Supplier;
1213

1314
import static java.util.Objects.requireNonNull;
1415

@@ -17,6 +18,8 @@
1718
* <p>
1819
* This works without any ordering because Gherkins document
1920
* structure is simple enough to hard code.
21+
*
22+
* @see LineageCollector
2023
*/
2124
class Lineage {
2225

@@ -96,6 +99,10 @@ Optional<Integer> exampleIndex() {
9699
return Optional.ofNullable(exampleIndex);
97100
}
98101

102+
<T> LineageReducer reduce(Supplier<LineageCollector<T>> collector) {
103+
return new LineageReducerDescending(collector);
104+
}
105+
99106
@Override
100107
public boolean equals(Object o) {
101108
if (this == o) return true;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package io.cucumber.query;
2+
3+
import io.cucumber.messages.types.Examples;
4+
import io.cucumber.messages.types.Feature;
5+
import io.cucumber.messages.types.GherkinDocument;
6+
import io.cucumber.messages.types.Pickle;
7+
import io.cucumber.messages.types.Rule;
8+
import io.cucumber.messages.types.Scenario;
9+
import io.cucumber.messages.types.TableRow;
10+
11+
/**
12+
* Visit the members of {@link Lineage} of a gherkin document element or
13+
* {@link Pickle} and collect these into a single result.
14+
* <p>
15+
* Because we are using messages we can not express the hierarchy of elements in
16+
* a {@link GherkinDocument} programmatically as a tree of nodes. But we can
17+
* still express the operations that would be typically done with a tree as
18+
* operations on that elements lineage.
19+
*
20+
* @param <T> the type reduced to.
21+
*/
22+
interface LineageCollector<T> {
23+
default void add(GherkinDocument document) {
24+
25+
}
26+
27+
default void add(Feature feature) {
28+
29+
}
30+
31+
default void add(Rule rule) {
32+
33+
}
34+
35+
default void add(Scenario scenario) {
36+
37+
}
38+
39+
default void add(Examples examples, int index) {
40+
}
41+
42+
default void add(TableRow example, int index) {
43+
}
44+
45+
default void add(Pickle pickle) {
46+
}
47+
48+
T finish();
49+
}
Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,24 @@
11
package io.cucumber.query;
22

3-
import io.cucumber.messages.types.Examples;
4-
import io.cucumber.messages.types.Feature;
5-
import io.cucumber.messages.types.GherkinDocument;
63
import io.cucumber.messages.types.Pickle;
7-
import io.cucumber.messages.types.Rule;
8-
import io.cucumber.messages.types.Scenario;
9-
import io.cucumber.messages.types.TableRow;
104

11-
interface LineageReducer<T> {
12-
default void add(GherkinDocument document) {
13-
14-
}
15-
default void add(Feature feature) {
16-
17-
}
18-
19-
default void add(Rule rule) {
5+
import java.util.function.Supplier;
206

21-
}
22-
23-
default void add(Scenario scenario) {
7+
import static java.util.Objects.requireNonNull;
248

25-
}
9+
/**
10+
* S
11+
*
12+
* @param <T>
13+
*/
14+
interface LineageReducer<T> {
2615

27-
default void add(Examples examples, int index) {
16+
static <T> LineageReducer<T> descending(Supplier<? extends LineageCollector<T>> collector){
17+
return new LineageReducerDescending<>(collector);
2818
}
2919

30-
default void add(TableRow example, int index) {
31-
}
20+
T reduce(Lineage lineage);
3221

33-
default void add(Pickle pickle) {
34-
}
22+
T reduce(Lineage lineage, Pickle pickle);
3523

36-
T finish();
3724
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package io.cucumber.query;
2+
3+
import io.cucumber.messages.types.Pickle;
4+
5+
import java.util.function.Supplier;
6+
7+
import static java.util.Objects.requireNonNull;
8+
9+
/**
10+
* Reduces the lineage of a Gherkin document element in descending order.
11+
*
12+
* @param <T> type to which the lineage is reduced.
13+
*/
14+
class LineageReducerDescending<T> implements LineageReducer<T> {
15+
16+
private final Supplier<? extends LineageCollector<T>> reducerSupplier;
17+
18+
LineageReducerDescending(Supplier<? extends LineageCollector<T>> reducerSupplier) {
19+
this.reducerSupplier = requireNonNull(reducerSupplier);
20+
}
21+
22+
@Override
23+
public T reduce(Lineage lineage) {
24+
LineageCollector<T> reducer = reducerSupplier.get();
25+
reduceAddLineage(reducer, lineage);
26+
return reducer.finish();
27+
}
28+
29+
@Override
30+
public T reduce(Lineage lineage, Pickle pickle) {
31+
LineageCollector<T> reducer = reducerSupplier.get();
32+
reduceAddLineage(reducer, lineage);
33+
reducer.add(pickle);
34+
return reducer.finish();
35+
}
36+
37+
private static <T> void reduceAddLineage(LineageCollector<T> reducer, Lineage lineage) {
38+
reducer.add(lineage.document());
39+
lineage.feature().ifPresent(reducer::add);
40+
lineage.rule().ifPresent(reducer::add);
41+
lineage.scenario().ifPresent(reducer::add);
42+
lineage.examples().ifPresent(examples -> reducer.add(examples, lineage.examplesIndex().orElse(0)));
43+
lineage.example().ifPresent(example -> reducer.add(example, lineage.exampleIndex().orElse(0)));
44+
}
45+
}

java/src/main/java/io/cucumber/query/LineageReducerStrategy.java

Lines changed: 0 additions & 51 deletions
This file was deleted.

java/src/main/java/io/cucumber/query/Lineages.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,62 +12,72 @@
1212
import java.util.HashMap;
1313
import java.util.List;
1414
import java.util.Map;
15+
import java.util.Optional;
1516
import java.util.function.BiConsumer;
1617
import java.util.function.Consumer;
18+
import java.util.function.Supplier;
1719

1820
class Lineages {
1921

20-
static Map<Object, Lineage> of(GherkinDocument document) {
21-
Map<Object, Lineage> elements = new HashMap<>();
22+
/**
23+
* Create map of a {@link GherkinDocument} element to its {@link Lineage} in that document.
24+
* <p>
25+
* @param document to create the lineage of
26+
* @return a map of the document elements to their lineage.
27+
*/
28+
static Map<String, Lineage> of(GherkinDocument document) {
29+
Map<String, Lineage> elements = new HashMap<>();
2230
Lineage lineage = new Lineage(document);
23-
elements.put(document, lineage);
31+
String uri = document.getUri()
32+
.orElseThrow(() -> new IllegalArgumentException("document.uri must not be null"));
33+
elements.put(uri, lineage);
2434
document.getFeature().ifPresent(ofFeature(lineage, elements));
2535
return elements;
2636
}
2737

28-
private static Consumer<Feature> ofFeature(Lineage parent, Map<Object, Lineage> elements) {
38+
private static Consumer<Feature> ofFeature(Lineage parent, Map<String, Lineage> elements) {
2939
return feature -> {
3040
Lineage lineage = new Lineage(parent, feature);
3141
feature.getChildren().forEach(ofFeatureChild(lineage, elements));
3242
};
3343
}
3444

35-
private static Consumer<FeatureChild> ofFeatureChild(Lineage parent, Map<Object, Lineage> elements) {
45+
private static Consumer<FeatureChild> ofFeatureChild(Lineage parent, Map<String, Lineage> elements) {
3646
return featureChild -> {
3747
featureChild.getScenario().ifPresent(ofScenario(parent, elements));
3848
featureChild.getRule().ifPresent(ofRule(parent, elements));
3949
};
4050
}
4151

42-
private static Consumer<Rule> ofRule(Lineage parent, Map<Object, Lineage> elements) {
52+
private static Consumer<Rule> ofRule(Lineage parent, Map<String, Lineage> elements) {
4353
return rule -> {
4454
Lineage lineage = new Lineage(parent, rule);
4555
elements.put(rule.getId(), lineage);
4656
rule.getChildren().forEach(ofRuleChild(lineage, elements));
4757
};
4858
}
4959

50-
private static Consumer<RuleChild> ofRuleChild(Lineage parent, Map<Object, Lineage> elements) {
60+
private static Consumer<RuleChild> ofRuleChild(Lineage parent, Map<String, Lineage> elements) {
5161
return ruleChild -> ruleChild.getScenario().ifPresent(ofScenario(parent, elements));
5262
}
5363

54-
private static Consumer<Scenario> ofScenario(Lineage parent, Map<Object, Lineage> elements) {
64+
private static Consumer<Scenario> ofScenario(Lineage parent, Map<String, Lineage> elements) {
5565
return scenario -> {
5666
Lineage lineage = new Lineage(parent, scenario);
5767
elements.put(scenario.getId(), lineage);
5868
forEachIndexed(scenario.getExamples(), ofExamples(lineage, elements));
5969
};
6070
}
6171

62-
private static BiConsumer<Examples, Integer> ofExamples(Lineage parent, Map<Object, Lineage> elements) {
72+
private static BiConsumer<Examples, Integer> ofExamples(Lineage parent, Map<String, Lineage> elements) {
6373
return (examples, examplesIndex) -> {
6474
Lineage lineage = new Lineage(parent, examples, examplesIndex);
6575
elements.put(examples.getId(), lineage);
6676
forEachIndexed(examples.getTableBody(), ofExample(lineage, elements));
6777
};
6878
}
6979

70-
private static BiConsumer<TableRow, Integer> ofExample(Lineage parent, Map<Object, Lineage> elements) {
80+
private static BiConsumer<TableRow, Integer> ofExample(Lineage parent, Map<String, Lineage> elements) {
7181
return (example, exampleIndex) -> {
7282
Lineage lineage = new Lineage(parent, example, exampleIndex);
7383
elements.put(example.getId(), lineage);

java/src/main/java/io/cucumber/query/NamingReducer.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212

1313
import java.util.ArrayDeque;
1414
import java.util.Deque;
15+
import java.util.function.Supplier;
1516
import java.util.stream.Collectors;
1617

1718
import static io.cucumber.query.NamingStrategy.FeatureName.INCLUDE;
1819
import static io.cucumber.query.NamingStrategy.Strategy.SHORT;
1920

20-
class NamingReducer implements LineageReducer<String> {
21+
class NamingReducer implements LineageCollector<String> {
2122

2223
private final Deque<String> parts = new ArrayDeque<>();
2324
private final CharSequence delimiter = " - ";
@@ -29,7 +30,11 @@ class NamingReducer implements LineageReducer<String> {
2930
private boolean isExample;
3031
private int examplesIndex;
3132

32-
NamingReducer(Strategy strategy, FeatureName featureName, ExampleName exampleName) {
33+
static Supplier<NamingReducer> of(Strategy strategy, FeatureName featureName, ExampleName exampleName) {
34+
return () -> new NamingReducer(strategy, featureName, exampleName);
35+
}
36+
37+
private NamingReducer(Strategy strategy, FeatureName featureName, ExampleName exampleName) {
3338
this.strategy = strategy;
3439
this.featureName = featureName;
3540
this.exampleName = exampleName;

java/src/main/java/io/cucumber/query/NamingStrategy.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
* <li>Eating 1 cucumbers
6060
* </ul>
6161
*/
62-
public abstract class NamingStrategy implements LineageReducerStrategy<String> {
62+
public abstract class NamingStrategy implements LineageReducer<String> {
6363

6464
public enum Strategy {
6565
/**
@@ -134,16 +134,15 @@ public Builder featureName(FeatureName featureName) {
134134
}
135135

136136
public NamingStrategy build() {
137-
Supplier<LineageReducer<String>> reducer = () -> new NamingReducer(strategy, featureName, exampleName);
138-
LineageReducerStrategy<String> strategy = new Descending<>(reducer);
139-
return new Adaptor(strategy);
137+
LineageReducer<String> reducer = LineageReducer.descending(NamingReducer.of(strategy, featureName, exampleName));
138+
return new Adaptor(reducer);
140139
}
141140
}
142141

143142
private static class Adaptor extends NamingStrategy {
144-
private final LineageReducerStrategy<String> delegate;
143+
private final LineageReducer<String> delegate;
145144

146-
Adaptor(LineageReducerStrategy<String> delegate) {
145+
Adaptor(LineageReducer<String> delegate) {
147146
this.delegate = delegate;
148147
}
149148

0 commit comments

Comments
 (0)