Skip to content

Commit 647e2d0

Browse files
authored
Merge pull request #342 from KristianKarl/master
First fix to issue 341
2 parents 758658d + 0fd2214 commit 647e2d0

9 files changed

Lines changed: 176 additions & 37 deletions

File tree

graphwalker-core/src/main/java/org/graphwalker/core/condition/AlternativeCondition.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,14 @@ public double getFulfilment() {
9090

9191
@Override
9292
public StringBuilder toString(StringBuilder builder) {
93-
return builder.append(conditions.stream().map(StopCondition::toString)
93+
if (conditions.size()>1) {
94+
builder.append("(");
95+
}
96+
builder.append(conditions.stream().map(StopCondition::toString)
9497
.collect(Collectors.joining(" OR ")));
98+
if (conditions.size()>1) {
99+
builder.append(")");
100+
}
101+
return builder;
95102
}
96103
}

graphwalker-core/src/main/java/org/graphwalker/core/condition/CombinedCondition.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,14 @@ public double getFulfilment() {
8989

9090
@Override
9191
public StringBuilder toString(StringBuilder builder) {
92-
return builder.append(conditions.stream().map(StopCondition::toString)
92+
if (conditions.size()>1) {
93+
builder.append("(");
94+
}
95+
builder.append(conditions.stream().map(StopCondition::toString)
9396
.collect(Collectors.joining(" AND ")));
97+
if (conditions.size()>1) {
98+
builder.append(")");
99+
}
100+
return builder;
94101
}
95102
}

graphwalker-core/src/test/java/org/graphwalker/core/condition/AlternativeConditionTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public void testFulfilment() throws Exception {
6969
assertThat(condition.getFulfilment(), is(0.0));
7070
machine.getNextStep();
7171
assertThat(condition.getFulfilment(), is(1.0));
72-
assertThat(condition.toString(), is("VertexCoverage(100) OR ReachedEdge(e1)"));
72+
assertThat(condition.toString(), is("(VertexCoverage(100) OR ReachedEdge(e1))"));
7373
}
7474

7575
@Test
@@ -87,7 +87,7 @@ public void testIsFulfilled() throws Exception {
8787
assertThat(condition.getFulfilment(), is(0.0));
8888
machine.getNextStep();
8989
assertTrue(condition.isFulfilled());
90-
assertThat(condition.toString(), is("VertexCoverage(100) OR ReachedEdge(e1)"));
90+
assertThat(condition.toString(), is("(VertexCoverage(100) OR ReachedEdge(e1))"));
9191
}
9292

9393
@Test
@@ -99,10 +99,10 @@ public void testMultipleCondition() throws Exception {
9999
assertThat("Should be false", condition.isFulfilled(), is(false));
100100
condition.addStopCondition(new Never());
101101
assertThat("Should be false", condition.isFulfilled(), is(false));
102-
assertThat(condition.toString(), is("Never() OR Never() OR Never()"));
102+
assertThat(condition.toString(), is("(Never() OR Never() OR Never())"));
103103
condition.addStopCondition(new Always());
104104
assertThat("Should be true", condition.isFulfilled(), is(true));
105-
assertThat(condition.toString(), is("Never() OR Never() OR Never() OR Always()"));
105+
assertThat(condition.toString(), is("(Never() OR Never() OR Never() OR Always())"));
106106
}
107107

108108
private class Always extends StopConditionBase {

graphwalker-core/src/test/java/org/graphwalker/core/condition/CombinedConditionTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,6 @@ public void testIsFulfilled() throws Exception {
6262
assertThat("Should be false", condition.isFulfilled(), is(false));
6363
condition.addStopCondition(new Never());
6464
assertThat("Should be false", condition.isFulfilled(), is(false));
65-
assertThat(condition.toString(), is("Never() AND Never() AND Never()"));
65+
assertThat(condition.toString(), is("(Never() AND Never() AND Never())"));
6666
}
6767
}

graphwalker-core/src/test/java/org/graphwalker/core/condition/ComplexConditionsTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import org.graphwalker.core.model.*;
3535
import org.junit.Test;
3636

37+
import java.util.concurrent.TimeUnit;
38+
3739
/**
3840
* @author Nils Olsson
3941
*/
@@ -150,4 +152,25 @@ public void alternativeCondition_vertex_edge() throws Exception {
150152
}
151153
}
152154

155+
// random((reached_vertex(v_Browse) AND edge_coverage(100)) OR time(10))
156+
@Test
157+
public void and_plus_or() throws Exception {
158+
Context context = new TestExecutionContext();
159+
160+
CombinedCondition c1 = new CombinedCondition();
161+
c1.addStopCondition(new ReachedVertex("v_Browse"));
162+
c1.addStopCondition(new EdgeCoverage(100));
163+
164+
AlternativeCondition c2 = new AlternativeCondition();
165+
c2.addStopCondition(new TimeDuration(10, TimeUnit.SECONDS));
166+
c2.addStopCondition(c1);
167+
168+
context.setModel(model.build()).setPathGenerator(new RandomPath(c2));
169+
context.setNextElement(context.getModel().findElements("e_Init").get(0));
170+
171+
Machine machine = new SimpleMachine(context);
172+
while (machine.hasNextStep()) {
173+
machine.getNextStep();
174+
}
175+
}
153176
}

graphwalker-dsl/src/main/antlr4/org/graphwalker/dsl/generator/GeneratorParser.g4

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,19 @@ generator
1616
;
1717

1818
logicalExpression
19-
: booleanAndExpression ( OR booleanAndExpression )*
19+
: primaryExpression
20+
| andExpression
21+
| orExpression
2022
;
2123

22-
booleanAndExpression
24+
andExpression
2325
: primaryExpression ( AND primaryExpression )*
2426
;
2527

28+
orExpression
29+
: primaryExpression ( OR primaryExpression )*
30+
;
31+
2632
primaryExpression
2733
: stopCondition
2834
| '(' logicalExpression ')'

graphwalker-dsl/src/main/java/org/graphwalker/dsl/antlr/generator/GeneratorLoader.java

Lines changed: 88 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -46,59 +46,121 @@ public class GeneratorLoader extends GeneratorParserBaseListener {
4646

4747
private StopCondition stopCondition = null;
4848
private final List<PathGenerator> pathGenerators = new ArrayList<>();
49-
private final List<StopCondition> stopConditions = new ArrayList<>();
49+
50+
static public class Node<T>{
51+
private T data = null;
52+
private List<Node> children = new ArrayList<>();
53+
private Node parent = null;
54+
55+
public Node(T data) {
56+
this.data = data;
57+
}
58+
public void addChild(Node child) {
59+
child.setParent(this);
60+
this.children.add(child);
61+
}
62+
63+
public void addChild(T data) {
64+
Node<T> newChild = new Node<>(data);
65+
this.addChild(newChild);
66+
}
67+
68+
public List<Node> getChildren() {
69+
return children;
70+
}
71+
72+
public T getData() {
73+
return data;
74+
}
75+
76+
private void setParent(Node parent) {
77+
this.parent = parent;
78+
}
79+
}
80+
81+
Node root = null;
82+
Node currentNode = null;
83+
84+
@Override
85+
public void enterAndExpression(GeneratorParser.AndExpressionContext ctx) {
86+
Node node = new Node(new CombinedCondition());
87+
currentNode.addChild(node);
88+
currentNode = node;
89+
}
5090

5191
@Override
52-
public void exitBooleanAndExpression(GeneratorParser.BooleanAndExpressionContext ctx) {
53-
if (!ctx.AND().isEmpty()) {
54-
CombinedCondition combinedCondition = new CombinedCondition();
55-
stopConditions.forEach(combinedCondition::addStopCondition);
56-
stopCondition = combinedCondition;
92+
public void exitAndExpression(GeneratorParser.AndExpressionContext ctx) {
93+
CombinedCondition combinedCondition = (CombinedCondition) currentNode.getData();
94+
for ( Object child: currentNode.getChildren() ) {
95+
combinedCondition.addStopCondition((StopCondition) ((Node)child).getData());
5796
}
97+
currentNode = currentNode.parent;
98+
}
99+
100+
@Override
101+
public void enterOrExpression(GeneratorParser.OrExpressionContext ctx) {
102+
Node node = new Node(new AlternativeCondition());
103+
currentNode.addChild(node);
104+
currentNode = node;
105+
}
106+
107+
@Override
108+
public void exitOrExpression(GeneratorParser.OrExpressionContext ctx) {
109+
AlternativeCondition alternativeCondition = (AlternativeCondition) currentNode.getData();
110+
for ( Object child: currentNode.getChildren() ) {
111+
alternativeCondition.addStopCondition((StopCondition) ((Node)child).getData());
112+
}
113+
currentNode = currentNode.parent;
58114
}
59115

60116
@Override
61117
public void exitStopCondition(GeneratorParser.StopConditionContext ctx) {
62118
String conditionName = ctx.getChild(0).getText().toLowerCase();
63119
if ("never".equals(conditionName)) {
64-
stopConditions.add(new Never());
120+
currentNode.addChild(new Never());
65121
} else if ("edge_coverage".equals(conditionName) || "edgecoverage".equals(conditionName)) {
66-
stopConditions.add(new EdgeCoverage(Integer.parseInt(ctx.getChild(2).getText())));
122+
currentNode.addChild(new EdgeCoverage(Integer.parseInt(ctx.getChild(2).getText())));
67123
} else if ("vertex_coverage".equals(conditionName) || "vertexcoverage".equals(conditionName)) {
68-
stopConditions.add(new VertexCoverage(Integer.parseInt(ctx.getChild(2).getText())));
124+
currentNode.addChild(new VertexCoverage(Integer.parseInt(ctx.getChild(2).getText())));
69125
} else if ("reached_vertex".equals(conditionName) || "reachedvertex".equals(conditionName)) {
70-
stopConditions.add(new ReachedVertex(ctx.getChild(2).getText()));
126+
currentNode.addChild(new ReachedVertex(ctx.getChild(2).getText()));
71127
} else if ("reached_shared_state".equals(conditionName) || "reachedsharedstate".equals(conditionName)) {
72-
stopConditions.add(new ReachedSharedState(ctx.getChild(2).getText()));
128+
currentNode.addChild(new ReachedSharedState(ctx.getChild(2).getText()));
73129
} else if ("reached_edge".equals(conditionName) || "reachededge".equals(conditionName)) {
74-
stopConditions.add(new ReachedEdge(ctx.getChild(2).getText()));
130+
currentNode.addChild(new ReachedEdge(ctx.getChild(2).getText()));
75131
} else if ("time_duration".equals(conditionName) || "timeduration".equals(conditionName)) {
76-
stopConditions.add(new TimeDuration(Long.parseLong(ctx.getChild(2).getText()), TimeUnit.SECONDS));
132+
currentNode.addChild(new TimeDuration(Long.parseLong(ctx.getChild(2).getText()), TimeUnit.SECONDS));
77133
} else if ("dependency_edge_coverage".equals(conditionName) || "dependencyedgecoverage".equals(conditionName)) {
78-
stopConditions.add(new DependencyEdgeCoverage(Integer.parseInt(ctx.getChild(2).getText())));
134+
currentNode.addChild(new DependencyEdgeCoverage(Integer.parseInt(ctx.getChild(2).getText())));
79135
} else if ("requirement_coverage".equals(conditionName) || "requirementcoverage".equals(conditionName)) {
80-
stopConditions.add(new RequirementCoverage(Integer.parseInt(ctx.getChild(2).getText())));
136+
currentNode.addChild(new RequirementCoverage(Integer.parseInt(ctx.getChild(2).getText())));
81137
} else if ("length".equals(conditionName)) {
82-
stopConditions.add(new Length(Integer.parseInt(ctx.getChild(2).getText())));
138+
currentNode.addChild(new Length(Integer.parseInt(ctx.getChild(2).getText())));
83139
} else if ("predefined_path".equals(conditionName) || "predefinedpath".equals(conditionName)) {
84-
stopConditions.add(new PredefinedPathStopCondition());
140+
currentNode.addChild(new PredefinedPathStopCondition());
85141
}
86142
}
87143

88-
@Override
89-
public void exitLogicalExpression(GeneratorParser.LogicalExpressionContext ctx) {
90-
if (!ctx.OR().isEmpty()) {
91-
AlternativeCondition alternativeCondition = new AlternativeCondition();
92-
stopConditions.forEach(alternativeCondition::addStopCondition);
93-
stopCondition = alternativeCondition;
94-
}
144+
public void enterGenerator(GeneratorParser.GeneratorContext context) {
145+
root = new Node<StopCondition>(null);
146+
currentNode = root;
95147
}
96148

97149
@Override
98150
public void exitGenerator(GeneratorParser.GeneratorContext context) {
99-
if (stopConditions.size() == 1) {
100-
stopCondition = stopConditions.get(0);
151+
if ( root.getData() != null ) {
152+
stopCondition = (StopCondition)root.getData();
153+
} else {
154+
if (root.getChildren().size() == 0 ) {
155+
stopCondition = null;
156+
} else {
157+
Node node = (Node) root.getChildren().get(0);
158+
stopCondition = (StopCondition) node.getData();
159+
}
101160
}
161+
162+
163+
102164
String generatorName = context.getChild(0).getText().toLowerCase();
103165
if ("random".equals(generatorName) || "randompath".equals(generatorName)) {
104166
pathGenerators.add(new RandomPath(stopCondition));
@@ -118,7 +180,6 @@ public void exitGenerator(GeneratorParser.GeneratorContext context) {
118180
pathGenerators.add(pathGenerator);
119181
logger.debug("Generator: " + pathGenerator.getClass().getName() + " is loaded");
120182
}
121-
stopConditions.clear();
122183
}
123184

124185
public PathGenerator getGenerator() {

graphwalker-dsl/src/test/java/org/graphwalker/dsl/GeneratorFactoryTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,40 @@ public void multipleAlternativeStopConditions() {
297297
assertThat(((AlternativeCondition) generator.getStopCondition()).getStopConditions().size(), is(3));
298298
}
299299

300+
@Test
301+
public void issue_341_a() {
302+
PathGenerator generator = GeneratorFactory.parse("Random((vertex_coverage(100) and reached_vertex(myVertex)) or time_duration(90))");
303+
assertThat(generator, instanceOf(RandomPath.class));
304+
assertThat(generator.getStopCondition(), instanceOf(AlternativeCondition.class));
305+
306+
AlternativeCondition c1 = (AlternativeCondition) generator.getStopCondition();
307+
assertThat(c1.getStopConditions().size(), is(2));
308+
assertThat(c1.getStopConditions().get(0), instanceOf(CombinedCondition.class));
309+
assertThat(c1.getStopConditions().get(1), instanceOf(TimeDuration.class));
310+
311+
CombinedCondition c2 = (CombinedCondition)c1.getStopConditions().get(0);
312+
assertThat(c2.getStopConditions().size(), is(2));
313+
assertThat(c2.getStopConditions().get(0), instanceOf(VertexCoverage.class));
314+
assertThat(c2.getStopConditions().get(1), instanceOf(ReachedVertex.class));
315+
}
316+
317+
@Test
318+
public void issue_341_b() {
319+
PathGenerator generator = GeneratorFactory.parse("Random(time_duration(90) or (vertex_coverage(100) and reached_vertex(myVertex)))");
320+
assertThat(generator, instanceOf(RandomPath.class));
321+
assertThat(generator.getStopCondition(), instanceOf(AlternativeCondition.class));
322+
323+
AlternativeCondition c1 = (AlternativeCondition) generator.getStopCondition();
324+
assertThat(c1.getStopConditions().size(), is(2));
325+
assertThat(c1.getStopConditions().get(0), instanceOf(TimeDuration.class));
326+
assertThat(c1.getStopConditions().get(1), instanceOf(CombinedCondition.class));
327+
328+
CombinedCondition c2 = (CombinedCondition)c1.getStopConditions().get(1);
329+
assertThat(c2.getStopConditions().size(), is(2));
330+
assertThat(c2.getStopConditions().get(0), instanceOf(VertexCoverage.class));
331+
assertThat(c2.getStopConditions().get(1), instanceOf(ReachedVertex.class));
332+
}
333+
300334
@Test
301335
public void predefinedPath_predefinedPathStopCondition() {
302336
PathGenerator generator = GeneratorFactory.parse("predefined_path(predefined_path)");

graphwalker-dsl/src/test/java/org/graphwalker/dsl/GrammarTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ public class GrammarTest {
6262
"random(reached_vertex(e_SomeEdge) and edge_coverage(100))",
6363
"random((reached_vertex(e_SomeEdge) and reached_edge(e_SomeEdge)) || time(5000))",
6464
"random(edge_coverage(100) and never) a_star(reached_vertex(v_SomeName) || edge_coverage(90))",
65-
"random(reached_vertex(e_SomeEdge) and edge_coverage(100)) random((reached_vertex(e_SomeEdge) and reached_edge(e_SomeEdge)) || time(5000))"
65+
"random(reached_vertex(e_SomeEdge) and edge_coverage(100)) random((reached_vertex(e_SomeEdge) and reached_edge(e_SomeEdge)) || time(5000))",
66+
"Random((vertex_coverage(100) and reached_vertex(myVertex)) or time_duration(90))"
6667
);
6768

6869
@Test

0 commit comments

Comments
 (0)