Skip to content

Commit 797980a

Browse files
committed
support arithmetic in logical and substitute node
1 parent 8dffdb0 commit 797980a

12 files changed

Lines changed: 129 additions & 8 deletions

File tree

src/main/java/com/github/sidhant92/boolparser/application/ArithmeticExpressionEvaluator.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.github.sidhant92.boolparser.constant.ContainerDataType;
77
import com.github.sidhant92.boolparser.constant.DataType;
88
import com.github.sidhant92.boolparser.constant.Operator;
9+
import com.github.sidhant92.boolparser.domain.StringNode;
910
import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticLeafNode;
1011
import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticNode;
1112
import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticUnaryNode;
@@ -37,6 +38,10 @@ public Try<Object> evaluate(final String expression, final Map<String, Object> d
3738
return tokenOptional.map(node -> evaluateToken(node, data));
3839
}
3940

41+
protected Object evaluate(final Node node, final Map<String, Object> data) {
42+
return evaluateToken(node, data);
43+
}
44+
4045
private Object evaluateToken(final Node node, final Map<String, Object> data) {
4146
switch (node.getTokenType()) {
4247
case ARITHMETIC:
@@ -45,12 +50,18 @@ private Object evaluateToken(final Node node, final Map<String, Object> data) {
4550
return evaluateArithmeticLeafToken((ArithmeticLeafNode) node, data);
4651
case ARITHMETIC_UNARY:
4752
return evaluateUnaryArithmeticToken((ArithmeticUnaryNode) node, data);
53+
case STRING:
54+
return evaluateStringToken((StringNode) node, data);
4855
default:
4956
log.error("unsupported token {}", node.getTokenType());
5057
throw new UnsupportedToken();
5158
}
5259
}
5360

61+
private Object evaluateStringToken(final StringNode stringNode, final Map<String, Object> data) {
62+
return ValueUtils.getValueFromMap(stringNode.getField(), data).orElse(stringNode.getField());
63+
}
64+
5465
private Pair<Object, DataType> evaluateArithmeticLeafToken(final ArithmeticLeafNode arithmeticLeafNode, final Map<String, Object> data) {
5566
final Optional<Object> fetchedValue = ValueUtils.getValueFromMap(arithmeticLeafNode.getOperand().toString(), data);
5667
return fetchedValue

src/main/java/com/github/sidhant92/boolparser/application/BooleanExpressionEvaluator.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.github.sidhant92.boolparser.domain.ComparisonNode;
1313
import com.github.sidhant92.boolparser.domain.Node;
1414
import com.github.sidhant92.boolparser.domain.UnaryNode;
15+
import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticBaseNode;
1516
import com.github.sidhant92.boolparser.exception.DataNotFoundException;
1617
import com.github.sidhant92.boolparser.exception.HeterogeneousArrayException;
1718
import com.github.sidhant92.boolparser.exception.InvalidUnaryOperand;
@@ -31,9 +32,12 @@ public class BooleanExpressionEvaluator {
3132

3233
private final OperatorService operatorService;
3334

35+
private final ArithmeticExpressionEvaluator arithmeticExpressionEvaluator;
36+
3437
public BooleanExpressionEvaluator(final BoolExpressionParser boolExpressionParser) {
3538
this.boolExpressionParser = boolExpressionParser;
3639
operatorService = new OperatorService();
40+
arithmeticExpressionEvaluator = new ArithmeticExpressionEvaluator(boolExpressionParser);
3741
}
3842

3943
public Try<Boolean> evaluate(final String expression, final Map<String, Object> data, final String defaultField) {
@@ -66,8 +70,10 @@ private boolean evaluateToken(final Node node, final Map<String, Object> data) {
6670

6771
private boolean evaluateComparisonToken(final ComparisonNode comparisonToken, final Map<String, Object> data) {
6872
final Object fieldData = ValueUtils.getValueFromMap(comparisonToken.getField(), data).orElseThrow(DataNotFoundException::new);
73+
final Object value = comparisonToken.getValue() instanceof ArithmeticBaseNode ? arithmeticExpressionEvaluator.evaluate(
74+
(Node) comparisonToken.getValue(), data) : comparisonToken.getValue();
6975
return operatorService.evaluateLogicalOperator(comparisonToken.getOperator(), ContainerDataType.PRIMITIVE, comparisonToken.getDataType(),
70-
fieldData, comparisonToken.getValue());
76+
fieldData, value);
7177
}
7278

7379
private boolean evaluateNumericRangeToken(final NumericRangeNode numericRangeToken, final Map<String, Object> data) {

src/main/java/com/github/sidhant92/boolparser/constant/NodeType.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ public enum NodeType {
1313
UNARY,
1414
ARITHMETIC,
1515
ARITHMETIC_LEAF,
16-
ARITHMETIC_UNARY
16+
ARITHMETIC_UNARY,
17+
STRING
1718
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.github.sidhant92.boolparser.domain;
2+
3+
import com.github.sidhant92.boolparser.constant.NodeType;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Getter;
7+
import lombok.Setter;
8+
9+
/**
10+
* @author sidhant.aggarwal
11+
* @since 16/03/2024
12+
*/
13+
@AllArgsConstructor
14+
@Getter
15+
@Setter
16+
@Builder
17+
public class StringNode extends Node {
18+
private final String field;
19+
20+
@Override
21+
public NodeType getTokenType() {
22+
return NodeType.STRING;
23+
}
24+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.github.sidhant92.boolparser.domain.arithmetic;
2+
3+
import com.github.sidhant92.boolparser.domain.Node;
4+
5+
/**
6+
* @author sidhant.aggarwal
7+
* @since 16/03/2024
8+
*/
9+
public abstract class ArithmeticBaseNode extends Node {}

src/main/java/com/github/sidhant92/boolparser/domain/arithmetic/ArithmeticLeafNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
@Getter
1717
@Setter
1818
@Builder
19-
public class ArithmeticLeafNode extends Node {
19+
public class ArithmeticLeafNode extends ArithmeticBaseNode {
2020
private Object operand;
2121

2222
private DataType dataType;

src/main/java/com/github/sidhant92/boolparser/domain/arithmetic/ArithmeticNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
@Getter
1717
@Setter
1818
@Builder
19-
public class ArithmeticNode extends Node {
19+
public class ArithmeticNode extends ArithmeticBaseNode {
2020
private Node left;
2121

2222
private Node right;

src/main/java/com/github/sidhant92/boolparser/domain/arithmetic/ArithmeticUnaryNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
@Getter
1616
@Setter
1717
@Builder
18-
public class ArithmeticUnaryNode extends Node {
18+
public class ArithmeticUnaryNode extends ArithmeticBaseNode {
1919
private Node operand;
2020

2121
@Override

src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanFilterListener.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
import java.util.Objects;
55
import java.util.Stack;
66
import java.util.stream.Collectors;
7+
import org.antlr.v4.runtime.CommonToken;
78
import org.antlr.v4.runtime.Token;
89
import org.antlr.v4.runtime.tree.ParseTree;
910
import org.apache.commons.lang3.StringUtils;
1011
import org.apache.commons.lang3.tuple.Pair;
1112
import com.github.sidhant92.boolparser.constant.DataType;
1213
import com.github.sidhant92.boolparser.constant.LogicalOperationType;
1314
import com.github.sidhant92.boolparser.constant.Operator;
15+
import com.github.sidhant92.boolparser.domain.StringNode;
1416
import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticLeafNode;
1517
import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticNode;
1618
import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticUnaryNode;
@@ -33,6 +35,8 @@ public class BooleanFilterListener extends BooleanExpressionBaseListener {
3335

3436
private org.antlr.v4.runtime.Token lastToken;
3537

38+
private int tokenCount;
39+
3640
private String defaultField;
3741

3842
public BooleanFilterListener(final String defaultField) {
@@ -207,6 +211,9 @@ public void exitParse(BooleanExpressionParser.ParseContext ctx) {
207211
this.node = ArithmeticUnaryNode.builder().operand(secondNode).build();
208212
}
209213
}
214+
if (this.node == null && tokenCount == 1 && lastToken instanceof CommonToken) {
215+
this.node = StringNode.builder().field((lastToken.getText())).build();
216+
}
210217
if (this.node == null) {
211218
log.error("Error parsing expression for the string {}", ctx.getText());
212219
throw new InvalidExpressionException();
@@ -232,6 +239,7 @@ public void exitNotExpression(BooleanExpressionParser.NotExpressionContext ctx)
232239

233240
@Override
234241
public void exitTypesExpression(BooleanExpressionParser.TypesExpressionContext ctx) {
242+
tokenCount++;
235243
this.lastToken = ctx.start;
236244
}
237245

src/test/java/com/github/sidhant92/boolparser/application/ArithmeticExpressionEvaluatorTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,16 @@ public void testSimpleExponentOperationWithVariable() {
133133
assertEquals(resultOptional.get(), 100000);
134134
}
135135

136+
@Test
137+
public void testStringConcatenation() {
138+
final Map<String, Object> data = new HashMap<>();
139+
data.put("a", "first");
140+
data.put("b", "second");
141+
final Try<Object> resultOptional = arithmeticExpressionEvaluator.evaluate("a + \" \" + b", data);
142+
assertTrue(resultOptional.isSuccess());
143+
assertEquals(resultOptional.get(), "first second");
144+
}
145+
136146
@Test
137147
public void testExpressionWithParenthesisNoVariable() {
138148
final Map<String, Object> data = new HashMap<>();
@@ -177,4 +187,13 @@ public void testExpressionWithNestedUnaryNode() {
177187
assertTrue(resultOptional.isSuccess());
178188
assertEquals(resultOptional.get(), -15);
179189
}
190+
191+
@Test
192+
public void testExpressionWithNestedUnaryNode1() {
193+
final Map<String, Object> data = new HashMap<>();
194+
data.put("a", "test");
195+
final Try<Object> resultOptional = arithmeticExpressionEvaluator.evaluate("a", data);
196+
assertTrue(resultOptional.isSuccess());
197+
assertEquals(resultOptional.get(), "test");
198+
}
180199
}

0 commit comments

Comments
 (0)