Skip to content

Commit

Permalink
Merge pull request #47 from sidhant92/enhance_comparison
Browse files Browse the repository at this point in the history
make left side of comparison generic
  • Loading branch information
sidhant92 authored Feb 23, 2025
2 parents 1d62964 + a5f4269 commit 50899ff
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.sidhant92.boolparser.application;

import static com.github.sidhant92.boolparser.constant.NodeType.UNARY;
import java.util.Collections;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -72,17 +73,31 @@ private boolean evaluateToken(final Node node, final Map<String, Object> data) {
}
}

private boolean evaluateComparisonToken(final ComparisonNode comparisonToken, final Map<String, Object> data) {
final Optional<Object> fieldDataOptional = ValueUtils.getValueFromMap(comparisonToken.getField(), data);
private Optional<Object> getValue(final Node node, final Map<String, Object> data) {
switch (node.getTokenType()) {
case FIELD:
return ValueUtils.getValueFromMap(((FieldNode) node).getField(), data);
case UNARY:
final UnaryNode unaryNode = (UnaryNode) node;
return Optional.of(unaryNode.getValue());
default:
if (node instanceof ArithmeticBaseNode) {
return Optional.of(arithmeticExpressionEvaluator.evaluate(node, data));
}
return Optional.of(evaluateToken(node, data));
}
}

final Object fieldData = comparisonToken.isNullCheck() ? fieldDataOptional.orElse("null") : fieldDataOptional.orElseThrow(
() -> new DataNotFoundException(comparisonToken.getField()));
final Object value = comparisonToken.isNullCheck() ? "null" : comparisonToken.getValue() instanceof ArithmeticBaseNode ? arithmeticExpressionEvaluator.evaluate(
comparisonToken.getValue(), data) : comparisonToken.getValue();
final DataType dataType = ValueUtils.getDataType(value);
final DataType fieldDataType = ValueUtils.getDataType(fieldData);
return operatorService.evaluateLogicalOperator(comparisonToken.getOperator(), ContainerDataType.PRIMITIVE, fieldData, fieldDataType,
Collections.singletonList(Pair.of(value, dataType)));
private boolean evaluateComparisonToken(final ComparisonNode comparisonToken, final Map<String, Object> data) {
final Optional<Object> leftValueOptional = getValue(comparisonToken.getLeft(), data);

final Object leftData = comparisonToken.isNullCheck() ? leftValueOptional.orElse("null") : leftValueOptional.orElseThrow(
() -> new DataNotFoundException(((FieldNode) comparisonToken.getLeft()).getField()));
final Object rightData = comparisonToken.isNullCheck() ? "null" : getValue(comparisonToken.getRight(), data).get();
final DataType rightDataType = ValueUtils.getDataType(rightData);
final DataType leftDataType = ValueUtils.getDataType(leftData);
return operatorService.evaluateLogicalOperator(comparisonToken.getOperator(), ContainerDataType.PRIMITIVE, leftData, leftDataType,
Collections.singletonList(Pair.of(rightData, rightDataType)));
}

private boolean evaluateNumericRangeToken(final NumericRangeNode numericRangeToken, final Map<String, Object> data) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
@Setter
@Builder
public class ComparisonNode extends Node {
private final String field;
private final Node left;

private final Node value;
private final Node right;

private final Operator operator;

Expand All @@ -32,6 +32,6 @@ public NodeType getTokenType() {
}

public boolean isNullCheck() {
return Operator.getEqualityOperators().contains(this.operator) && this.value instanceof FieldNode && ((FieldNode) this.value).isNull();
return Operator.getEqualityOperators().contains(this.operator) && (this.right instanceof FieldNode && ((FieldNode) this.right).isNull() || this.left instanceof FieldNode && ((FieldNode) this.left).isNull());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,17 @@ private Node mapContextToNode(final ParseTree ctx) {
}

private FieldNode mapTypesExpressionContextField(BooleanExpressionParser.TypesExpressionContext ctx) {
return new FieldNode(ctx.getText());
final String value = StringUtils.isBlank(ctx.getText()) ? defaultField : ctx.getText();
return new FieldNode(value);
}

private Node mapTypesExpressionContext(BooleanExpressionParser.TypesExpressionContext ctx) {
if (ctx.start.getType() == BooleanExpressionLexer.FIELD) {
return mapTypesExpressionContextField(ctx);
}
if (StringUtils.isBlank(ctx.getText())) {
return mapTypesExpressionContextField(ctx);
}
final DataType dataType = getDataType(ctx.start);
final Object value = ValueUtils.convertValue(ctx.start.getText(), dataType);
return new UnaryNode(dataType, value);
Expand All @@ -150,15 +154,19 @@ private ArithmeticFunctionNode mapArithmeticFunctionExpressionContext(BooleanExp
}

private ComparisonNode mapComparatorExpressionContext(BooleanExpressionParser.ComparatorExpressionContext ctx) {
final String variableName = getField(ctx.left.getText());
final Operator operator = Operator.getOperatorFromSymbol(ctx.op.getText()).orElse(Operator.EQUALS);
if (!(ctx.right instanceof BooleanExpressionParser.TypesExpressionContext) && !currentNodes.isEmpty()) {
final Node value = currentNodes.pop();
return new ComparisonNode(variableName, value, operator, DataType.INTEGER);
return new ComparisonNode(mapContextToNode(ctx.left), value, operator, DataType.INTEGER);
} else {
if (ctx.left instanceof BooleanExpressionParser.ParentExpressionContext && !currentNodes.isEmpty()) {
final DataType dataType = getDataType(ctx.right.getStart());
final Node value = mapContextToNode(ctx.right);
return new ComparisonNode(currentNodes.pop(), value, operator, dataType);
}
final DataType dataType = getDataType(ctx.right.getStart());
final Node value = mapContextToNode(ctx.right);
return new ComparisonNode(variableName, value, operator, dataType);
return new ComparisonNode(mapContextToNode(ctx.left), value, operator, dataType);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,15 @@ public void testNumericGreaterThanCorrectExpression() {
assertTrue(booleanOptional.get());
}

@Test
public void testNumericGreaterThanCorrectExpressionInverted() {
final Map<String, Object> data = new HashMap<>();
data.put("age", 24);
final Try<Boolean> booleanOptional = booleanExpressionEvaluator.evaluate("20 < age", data);
assertTrue(booleanOptional.isSuccess());
assertTrue(booleanOptional.get());
}

@Test
public void testNumericGreaterThanCorrectExpressionWithField() {
final Map<String, Object> data = new HashMap<>();
Expand Down Expand Up @@ -553,6 +562,15 @@ public void testComparisonWithArithmeticTrueCondition() {
assertTrue(booleanOptional.get());
}

@Test
public void testComparisonWithArithmeticTrueConditionInverted() {
final Map<String, Object> data = new HashMap<>();
data.put("age", "20");
final Try<Boolean> booleanOptional = booleanExpressionEvaluator.evaluate("(5 + 10) < age", data);
assertTrue(booleanOptional.isSuccess());
assertTrue(booleanOptional.get());
}

@Test
public void testComparisonWithArithmeticFunction() {
final Map<String, Object> data = new HashMap<>();
Expand Down Expand Up @@ -614,6 +632,15 @@ public void testNullCheck() {
assertEquals(resultOptional.get(), true);
}

@Test
public void testNullCheckInverted() {
final Map<String, Object> data = new HashMap<>();
data.put("a", 2.7);
final Try<Boolean> resultOptional = booleanExpressionEvaluator.evaluate("null = b", data);
assertTrue(resultOptional.isSuccess());
assertEquals(resultOptional.get(), true);
}

@Test
public void testNullCheck1() {
final Map<String, Object> data = new HashMap<>();
Expand All @@ -640,4 +667,13 @@ public void testBooleanNullCheck() {
assertTrue(resultOptional.isSuccess());
assertEquals(resultOptional.get(), true);
}

@Test
public void testArithmeticFunctionAndComparison() {
final Map<String, Object> data = new HashMap<>();
data.put("a", "test");
final Try<Boolean> resultOptional = booleanExpressionEvaluator.evaluate("len(a) = 4", data);
assertTrue(resultOptional.isSuccess());
assertEquals(resultOptional.get(), true);
}
}
Loading

0 comments on commit 50899ff

Please sign in to comment.