Skip to content

Commit ea04bd8

Browse files
committed
handle type conversion
1 parent 5cf9ac5 commit ea04bd8

18 files changed

+216
-102
lines changed

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

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package com.github.sidhant92.boolparser.application;
22

3+
import java.util.Collections;
34
import java.util.List;
45
import java.util.Map;
56
import java.util.Optional;
67
import java.util.stream.Collectors;
8+
import org.apache.commons.lang3.tuple.Pair;
79
import com.github.sidhant92.boolparser.constant.ContainerDataType;
810
import com.github.sidhant92.boolparser.constant.DataType;
911
import com.github.sidhant92.boolparser.constant.Operator;
@@ -77,27 +79,32 @@ private boolean evaluateComparisonToken(final ComparisonNode comparisonToken, fi
7779
() -> new DataNotFoundException(comparisonToken.getField()));
7880
final Object value = comparisonToken.isNullCheck() ? "null" : comparisonToken.getValue() instanceof ArithmeticBaseNode ? arithmeticExpressionEvaluator.evaluate(
7981
comparisonToken.getValue(), data) : comparisonToken.getValue();
80-
return operatorService.evaluateLogicalOperator(comparisonToken.getOperator(), ContainerDataType.PRIMITIVE, comparisonToken.getDataType(),
81-
fieldData, value);
82+
final DataType dataType = ValueUtils.getDataType(value);
83+
final DataType fieldDataType = ValueUtils.getDataType(fieldData);
84+
return operatorService.evaluateLogicalOperator(comparisonToken.getOperator(), ContainerDataType.PRIMITIVE, fieldData,
85+
fieldDataType, Collections.singletonList(Pair.of(value, dataType)));
8286
}
8387

8488
private boolean evaluateNumericRangeToken(final NumericRangeNode numericRangeToken, final Map<String, Object> data) {
8589
final Object fieldData = ValueUtils.getValueFromMap(numericRangeToken.getField(), data)
8690
.orElseThrow(() -> new DataNotFoundException(numericRangeToken.getField()));
87-
return operatorService.evaluateLogicalOperator(Operator.GREATER_THAN_EQUAL, ContainerDataType.PRIMITIVE, numericRangeToken.getFromDataType(),
88-
fieldData, numericRangeToken.getFromValue()) && operatorService.evaluateLogicalOperator(
89-
Operator.LESS_THAN_EQUAL, ContainerDataType.PRIMITIVE, numericRangeToken.getToDataType(), fieldData, numericRangeToken.getToValue());
91+
return operatorService.evaluateLogicalOperator(Operator.GREATER_THAN_EQUAL, ContainerDataType.PRIMITIVE, fieldData,
92+
numericRangeToken.getFromDataType(), Collections.singletonList(
93+
Pair.of(numericRangeToken.getFromValue(), numericRangeToken.getFromDataType()))) && operatorService.evaluateLogicalOperator(
94+
Operator.LESS_THAN_EQUAL, ContainerDataType.PRIMITIVE, fieldData, numericRangeToken.getToDataType(),
95+
Collections.singletonList(Pair.of(numericRangeToken.getToValue(), numericRangeToken.getToDataType())));
9096
}
9197

9298
private boolean evaluateInToken(final InNode inToken, final Map<String, Object> data) {
9399
final Object fieldData = ValueUtils.getValueFromMap(inToken.getField(), data)
94100
.orElseThrow(() -> new DataNotFoundException(inToken.getField()));
95101
final List<EvaluatedNode> items = resolveArrayElements(inToken.getItems(), data);
96102
final DataType dataType = ValueUtils.getDataType(fieldData);
97-
final Object[] values = items
103+
final List<Pair<Object, DataType>> values = items
98104
.stream()
99-
.map(EvaluatedNode::getValue).toArray();
100-
return operatorService.evaluateLogicalOperator(Operator.IN, ContainerDataType.PRIMITIVE, dataType, fieldData, values);
105+
.map(item -> Pair.of(item.getValue(), item.getDataType()))
106+
.collect(Collectors.toList());
107+
return operatorService.evaluateLogicalOperator(Operator.IN, ContainerDataType.PRIMITIVE, fieldData, dataType, values);
101108
}
102109

103110
private List<EvaluatedNode> resolveArrayElements(final List<Node> items, final Map<String, Object> data) {
@@ -123,10 +130,11 @@ private boolean evaluateArrayToken(final ArrayNode arrayNode, final Map<String,
123130
throw new HeterogeneousArrayException();
124131
}
125132
final DataType dataType = items.get(0).getDataType();
126-
final Object[] values = items
133+
final List<Pair<Object, DataType>> values = items
127134
.stream()
128-
.map(EvaluatedNode::getValue).toArray();
129-
return operatorService.evaluateLogicalOperator(arrayNode.getOperator(), ContainerDataType.LIST, dataType, fieldData, values);
135+
.map(item -> Pair.of(item.getValue(), item.getDataType()))
136+
.collect(Collectors.toList());
137+
return operatorService.evaluateLogicalOperator(arrayNode.getOperator(), ContainerDataType.LIST, fieldData, dataType, values);
130138
}
131139

132140
private boolean evaluateUnaryToken(final UnaryNode unaryToken, final Map<String, Object> data) {
Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
package com.github.sidhant92.boolparser.constant;
22

3+
import lombok.AllArgsConstructor;
4+
35
/**
46
* @author sidhant.aggarwal
57
* @since 05/03/2023
68
*/
9+
@AllArgsConstructor
710
public enum DataType {
8-
STRING,
9-
INTEGER,
10-
LONG,
11-
DECIMAL,
12-
VERSION,
13-
BOOLEAN
11+
STRING(6, false),
12+
INTEGER(3, true),
13+
LONG(4, true),
14+
DECIMAL(5, true),
15+
VERSION(2, true),
16+
BOOLEAN(1, false);
17+
18+
public final int priority;
19+
20+
public final boolean numeric;
1421
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import java.util.Arrays;
44
import java.util.List;
55
import java.util.Optional;
6-
import com.github.sidhant92.boolparser.operator.logical.AbstractOperator;
6+
import com.github.sidhant92.boolparser.operator.comparison.AbstractOperator;
77
import com.github.sidhant92.boolparser.operator.OperatorFactory;
88
import lombok.AccessLevel;
99
import lombok.AllArgsConstructor;

src/main/java/com/github/sidhant92/boolparser/operator/OperatorFactory.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@
1212
import com.github.sidhant92.boolparser.operator.arithmetic.MultiplyOperator;
1313
import com.github.sidhant92.boolparser.operator.arithmetic.SubtractOperator;
1414
import com.github.sidhant92.boolparser.operator.arithmetic.UnaryOperator;
15-
import com.github.sidhant92.boolparser.operator.logical.AbstractOperator;
16-
import com.github.sidhant92.boolparser.operator.logical.ContainsAllOperator;
17-
import com.github.sidhant92.boolparser.operator.logical.ContainsAnyOperator;
18-
import com.github.sidhant92.boolparser.operator.logical.EqualsOperator;
19-
import com.github.sidhant92.boolparser.operator.logical.GreaterThanEqualOperator;
20-
import com.github.sidhant92.boolparser.operator.logical.GreaterThanOperator;
21-
import com.github.sidhant92.boolparser.operator.logical.InOperator;
22-
import com.github.sidhant92.boolparser.operator.logical.LessThanEqualOperator;
23-
import com.github.sidhant92.boolparser.operator.logical.LessThanOperator;
24-
import com.github.sidhant92.boolparser.operator.logical.NotEqualsOperator;
15+
import com.github.sidhant92.boolparser.operator.comparison.AbstractOperator;
16+
import com.github.sidhant92.boolparser.operator.comparison.ContainsAllOperator;
17+
import com.github.sidhant92.boolparser.operator.comparison.ContainsAnyOperator;
18+
import com.github.sidhant92.boolparser.operator.comparison.EqualsOperator;
19+
import com.github.sidhant92.boolparser.operator.comparison.GreaterThanEqualOperator;
20+
import com.github.sidhant92.boolparser.operator.comparison.GreaterThanOperator;
21+
import com.github.sidhant92.boolparser.operator.comparison.InOperator;
22+
import com.github.sidhant92.boolparser.operator.comparison.LessThanEqualOperator;
23+
import com.github.sidhant92.boolparser.operator.comparison.LessThanOperator;
24+
import com.github.sidhant92.boolparser.operator.comparison.NotEqualsOperator;
2525

2626
/**
2727
* @author sidhant.aggarwal

src/main/java/com/github/sidhant92/boolparser/operator/OperatorService.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package com.github.sidhant92.boolparser.operator;
22

3+
import java.util.List;
34
import java.util.Objects;
5+
import org.apache.commons.lang3.tuple.Pair;
46
import com.github.sidhant92.boolparser.constant.ContainerDataType;
57
import com.github.sidhant92.boolparser.constant.DataType;
68
import com.github.sidhant92.boolparser.constant.Operator;
79
import com.github.sidhant92.boolparser.datatype.DataTypeFactory;
810
import com.github.sidhant92.boolparser.exception.InvalidContainerTypeException;
911
import com.github.sidhant92.boolparser.exception.InvalidDataType;
10-
import com.github.sidhant92.boolparser.operator.logical.AbstractOperator;
12+
import com.github.sidhant92.boolparser.operator.comparison.AbstractOperator;
1113

1214
/**
1315
* @author sidhant.aggarwal
@@ -19,19 +21,19 @@ public OperatorService() {
1921
OperatorFactory.initialize();
2022
}
2123

22-
public boolean evaluateLogicalOperator(final Operator operator, final ContainerDataType containerDataType, final DataType dataType,
23-
final Object leftOperand, final Object... rightOperands) {
24+
public boolean evaluateLogicalOperator(final Operator operator, final ContainerDataType containerDataType, final Object leftOperand,
25+
final DataType leftOperandDataType, final List<Pair<Object, DataType>> rightOperands) {
2426
final AbstractOperator abstractOperator = OperatorFactory.getLogicalOperator(operator);
2527
if (!abstractOperator.getAllowedContainerTypes().contains(containerDataType)) {
2628
throw new InvalidContainerTypeException(String.format("Invalid left container type %s for operator %s", containerDataType, operator));
2729
}
28-
if (!abstractOperator.getAllowedDataTypes().contains(dataType)) {
29-
throw new InvalidDataType(String.format("Invalid left operand data type %s for operator %s", dataType, operator));
30+
if (!abstractOperator.getAllowedDataTypes().contains(leftOperandDataType)) {
31+
throw new InvalidDataType(String.format("Invalid left operand data type %s for operator %s", leftOperandDataType, operator));
3032
}
31-
if (!containerDataType.isValid(dataType, leftOperand)) {
33+
if (!containerDataType.isValid(leftOperandDataType, leftOperand)) {
3234
throw new InvalidDataType(String.format("Validation failed for the operator %s for the operand %s", operator, leftOperand));
3335
}
34-
return OperatorFactory.getLogicalOperator(operator).evaluate(containerDataType, dataType, leftOperand, rightOperands);
36+
return OperatorFactory.getLogicalOperator(operator).evaluate(containerDataType, leftOperand, leftOperandDataType, rightOperands);
3537
}
3638

3739
public Object evaluateArithmeticOperator(final Object leftOperand, final DataType leftDataType, final Object rightOperand,

src/main/java/com/github/sidhant92/boolparser/operator/logical/AbstractOperator.java renamed to src/main/java/com/github/sidhant92/boolparser/operator/comparison/AbstractOperator.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
package com.github.sidhant92.boolparser.operator.logical;
1+
package com.github.sidhant92.boolparser.operator.comparison;
22

33
import java.util.List;
4+
import org.apache.commons.lang3.tuple.Pair;
45
import com.github.sidhant92.boolparser.constant.ContainerDataType;
56
import com.github.sidhant92.boolparser.constant.DataType;
67
import com.github.sidhant92.boolparser.constant.Operator;
@@ -10,8 +11,9 @@
1011
* @since 05/03/2023
1112
*/
1213
public abstract class AbstractOperator {
13-
public abstract <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final DataType dataType,
14-
final Object leftOperand, final Object... rightOperands);
14+
public abstract <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final Object leftOperand,
15+
final DataType leftOperandDataType,
16+
final List<Pair<Object, DataType>> rightOperands);
1517

1618
public abstract Operator getOperator();
1719

src/main/java/com/github/sidhant92/boolparser/operator/logical/ContainsAllOperator.java renamed to src/main/java/com/github/sidhant92/boolparser/operator/comparison/ContainsAllOperator.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
package com.github.sidhant92.boolparser.operator.logical;
1+
package com.github.sidhant92.boolparser.operator.comparison;
22

33
import java.util.Arrays;
44
import java.util.Collections;
55
import java.util.List;
6+
import java.util.stream.Collectors;
7+
import org.apache.commons.lang3.tuple.Pair;
68
import com.github.sidhant92.boolparser.constant.ContainerDataType;
79
import com.github.sidhant92.boolparser.constant.DataType;
810
import com.github.sidhant92.boolparser.constant.Operator;
@@ -13,15 +15,18 @@ public class ContainsAllOperator extends AbstractOperator {
1315
private final InOperator inOperator;
1416

1517
@Override
16-
public <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final DataType dataType,
17-
final Object leftOperand, final Object... rightOperands) {
18-
if (!containerDataType.isValid(dataType, leftOperand)) {
18+
public <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final Object leftOperand,
19+
final DataType leftOperandDataType, final List<Pair<Object, DataType>> rightOperands) {
20+
if (!containerDataType.isValid(leftOperandDataType, leftOperand)) {
1921
return false;
2022
}
21-
final Object[] leftOperandArray = ((List<?>) leftOperand).toArray();
22-
return Arrays
23-
.stream(rightOperands)
24-
.allMatch(rightOperand -> inOperator.evaluate(ContainerDataType.PRIMITIVE, dataType, rightOperand, leftOperandArray));
23+
final List<Pair<Object, DataType>> leftOperandArray = Arrays
24+
.stream(((List<?>) leftOperand).toArray())
25+
.map(a -> Pair.of(a, leftOperandDataType))
26+
.collect(Collectors.toList());
27+
return rightOperands
28+
.stream().allMatch(rightOperand -> inOperator.evaluate(ContainerDataType.PRIMITIVE, rightOperand.getLeft(), rightOperand.getRight(),
29+
leftOperandArray));
2530
}
2631

2732
@Override

src/main/java/com/github/sidhant92/boolparser/operator/logical/ContainsAnyOperator.java renamed to src/main/java/com/github/sidhant92/boolparser/operator/comparison/ContainsAnyOperator.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
package com.github.sidhant92.boolparser.operator.logical;
1+
package com.github.sidhant92.boolparser.operator.comparison;
22

33
import java.util.Arrays;
44
import java.util.Collections;
55
import java.util.List;
6+
import java.util.stream.Collectors;
7+
import org.apache.commons.lang3.tuple.Pair;
68
import com.github.sidhant92.boolparser.constant.ContainerDataType;
79
import com.github.sidhant92.boolparser.constant.DataType;
810
import com.github.sidhant92.boolparser.constant.Operator;
@@ -13,15 +15,18 @@ public class ContainsAnyOperator extends AbstractOperator {
1315
private final InOperator inOperator;
1416

1517
@Override
16-
public <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final DataType dataType,
17-
final Object leftOperand, final Object... rightOperands) {
18-
if (!containerDataType.isValid(dataType, leftOperand)) {
18+
public <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final Object leftOperand,
19+
final DataType leftOperandDataType, final List<Pair<Object, DataType>> rightOperands) {
20+
if (!containerDataType.isValid(leftOperandDataType, leftOperand)) {
1921
return false;
2022
}
21-
final Object[] leftOperandArray = ((List<?>) leftOperand).toArray();
22-
return Arrays
23-
.stream(rightOperands)
24-
.anyMatch(rightOperand -> inOperator.evaluate(ContainerDataType.PRIMITIVE, dataType, rightOperand, leftOperandArray));
23+
final List<Pair<Object, DataType>> leftOperandArray = Arrays
24+
.stream(((List<?>) leftOperand).toArray())
25+
.map(a -> Pair.of(a, leftOperandDataType))
26+
.collect(Collectors.toList());
27+
return rightOperands
28+
.stream().anyMatch(rightOperand -> inOperator.evaluate(ContainerDataType.PRIMITIVE, rightOperand.getLeft(), rightOperand.getRight(),
29+
leftOperandArray));
2530
}
2631

2732
@Override

src/main/java/com/github/sidhant92/boolparser/operator/logical/EqualsOperator.java renamed to src/main/java/com/github/sidhant92/boolparser/operator/comparison/EqualsOperator.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
package com.github.sidhant92.boolparser.operator.logical;
1+
package com.github.sidhant92.boolparser.operator.comparison;
22

33
import java.util.Arrays;
44
import java.util.Collections;
55
import java.util.List;
66
import java.util.Optional;
7+
import org.apache.commons.lang3.tuple.Pair;
78
import com.github.sidhant92.boolparser.constant.ContainerDataType;
89
import com.github.sidhant92.boolparser.constant.DataType;
910
import com.github.sidhant92.boolparser.constant.Operator;
@@ -14,11 +15,22 @@
1415
*/
1516
public class EqualsOperator extends AbstractOperator {
1617
@Override
17-
public <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final DataType dataType,
18-
final Object leftOperand, final Object... rightOperands) {
19-
final Optional<T> leftValueOptional = containerDataType.getValue(dataType, leftOperand);
20-
final Optional<T> rightValueOptional = containerDataType.getValue(dataType, rightOperands[0]);
21-
return leftValueOptional.flatMap(leftValue -> rightValueOptional.map(leftValue::compareTo).map(a -> a == 0)).orElse(false);
18+
public <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final Object leftOperand,
19+
final DataType leftOperandDataType, final List<Pair<Object, DataType>> rightOperands) {
20+
final DataType comparisonType = getComparableDataType(leftOperandDataType, rightOperands.get(0).getRight());
21+
final Optional<T> leftValueOptional = containerDataType.getValue(comparisonType, leftOperand);
22+
final Optional<T> rightValueOptional = containerDataType.getValue(comparisonType, rightOperands.get(0).getLeft());
23+
return leftValueOptional
24+
.flatMap(leftValue -> rightValueOptional
25+
.map(leftValue::compareTo)
26+
.map(a -> a == 0)).orElse(false);
27+
}
28+
29+
private DataType getComparableDataType(final DataType leftOperandDataType, final DataType rightOperandDataType) {
30+
if (leftOperandDataType.priority > rightOperandDataType.priority) {
31+
return leftOperandDataType;
32+
}
33+
return rightOperandDataType;
2234
}
2335

2436
@Override

0 commit comments

Comments
 (0)