Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.github.sidhant92.boolparser.application;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import com.github.sidhant92.boolparser.constant.ContainerDataType;
import com.github.sidhant92.boolparser.constant.DataType;
import com.github.sidhant92.boolparser.constant.Operator;
Expand Down Expand Up @@ -77,27 +79,32 @@ private boolean evaluateComparisonToken(final ComparisonNode comparisonToken, fi
() -> new DataNotFoundException(comparisonToken.getField()));
final Object value = comparisonToken.isNullCheck() ? "null" : comparisonToken.getValue() instanceof ArithmeticBaseNode ? arithmeticExpressionEvaluator.evaluate(
comparisonToken.getValue(), data) : comparisonToken.getValue();
return operatorService.evaluateLogicalOperator(comparisonToken.getOperator(), ContainerDataType.PRIMITIVE, comparisonToken.getDataType(),
fieldData, value);
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 evaluateNumericRangeToken(final NumericRangeNode numericRangeToken, final Map<String, Object> data) {
final Object fieldData = ValueUtils.getValueFromMap(numericRangeToken.getField(), data)
.orElseThrow(() -> new DataNotFoundException(numericRangeToken.getField()));
return operatorService.evaluateLogicalOperator(Operator.GREATER_THAN_EQUAL, ContainerDataType.PRIMITIVE, numericRangeToken.getFromDataType(),
fieldData, numericRangeToken.getFromValue()) && operatorService.evaluateLogicalOperator(
Operator.LESS_THAN_EQUAL, ContainerDataType.PRIMITIVE, numericRangeToken.getToDataType(), fieldData, numericRangeToken.getToValue());
return operatorService.evaluateLogicalOperator(Operator.GREATER_THAN_EQUAL, ContainerDataType.PRIMITIVE, fieldData,
numericRangeToken.getFromDataType(), Collections.singletonList(
Pair.of(numericRangeToken.getFromValue(), numericRangeToken.getFromDataType()))) && operatorService.evaluateLogicalOperator(
Operator.LESS_THAN_EQUAL, ContainerDataType.PRIMITIVE, fieldData, numericRangeToken.getToDataType(),
Collections.singletonList(Pair.of(numericRangeToken.getToValue(), numericRangeToken.getToDataType())));
}

private boolean evaluateInToken(final InNode inToken, final Map<String, Object> data) {
final Object fieldData = ValueUtils.getValueFromMap(inToken.getField(), data)
.orElseThrow(() -> new DataNotFoundException(inToken.getField()));
final List<EvaluatedNode> items = resolveArrayElements(inToken.getItems(), data);
final DataType dataType = ValueUtils.getDataType(fieldData);
final Object[] values = items
final List<Pair<Object, DataType>> values = items
.stream()
.map(EvaluatedNode::getValue).toArray();
return operatorService.evaluateLogicalOperator(Operator.IN, ContainerDataType.PRIMITIVE, dataType, fieldData, values);
.map(item -> Pair.of(item.getValue(), item.getDataType()))
.collect(Collectors.toList());
return operatorService.evaluateLogicalOperator(Operator.IN, ContainerDataType.PRIMITIVE, fieldData, dataType, values);
}

private List<EvaluatedNode> resolveArrayElements(final List<Node> items, final Map<String, Object> data) {
Expand All @@ -123,10 +130,11 @@ private boolean evaluateArrayToken(final ArrayNode arrayNode, final Map<String,
throw new HeterogeneousArrayException();
}
final DataType dataType = items.get(0).getDataType();
final Object[] values = items
final List<Pair<Object, DataType>> values = items
.stream()
.map(EvaluatedNode::getValue).toArray();
return operatorService.evaluateLogicalOperator(arrayNode.getOperator(), ContainerDataType.LIST, dataType, fieldData, values);
.map(item -> Pair.of(item.getValue(), item.getDataType()))
.collect(Collectors.toList());
return operatorService.evaluateLogicalOperator(arrayNode.getOperator(), ContainerDataType.LIST, fieldData, dataType, values);
}

private boolean evaluateUnaryToken(final UnaryNode unaryToken, final Map<String, Object> data) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package com.github.sidhant92.boolparser.constant;

import lombok.AllArgsConstructor;

/**
* @author sidhant.aggarwal
* @since 05/03/2023
*/
@AllArgsConstructor
public enum DataType {
STRING,
INTEGER,
LONG,
DECIMAL,
VERSION,
BOOLEAN
STRING(6, false),
INTEGER(3, true),
LONG(4, true),
DECIMAL(5, true),
VERSION(2, true),
BOOLEAN(1, false);

public final int priority;

public final boolean numeric;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import com.github.sidhant92.boolparser.operator.logical.AbstractOperator;
import com.github.sidhant92.boolparser.operator.comparison.AbstractOperator;
import com.github.sidhant92.boolparser.operator.OperatorFactory;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@
import com.github.sidhant92.boolparser.operator.arithmetic.MultiplyOperator;
import com.github.sidhant92.boolparser.operator.arithmetic.SubtractOperator;
import com.github.sidhant92.boolparser.operator.arithmetic.UnaryOperator;
import com.github.sidhant92.boolparser.operator.logical.AbstractOperator;
import com.github.sidhant92.boolparser.operator.logical.ContainsAllOperator;
import com.github.sidhant92.boolparser.operator.logical.ContainsAnyOperator;
import com.github.sidhant92.boolparser.operator.logical.EqualsOperator;
import com.github.sidhant92.boolparser.operator.logical.GreaterThanEqualOperator;
import com.github.sidhant92.boolparser.operator.logical.GreaterThanOperator;
import com.github.sidhant92.boolparser.operator.logical.InOperator;
import com.github.sidhant92.boolparser.operator.logical.LessThanEqualOperator;
import com.github.sidhant92.boolparser.operator.logical.LessThanOperator;
import com.github.sidhant92.boolparser.operator.logical.NotEqualsOperator;
import com.github.sidhant92.boolparser.operator.comparison.AbstractOperator;
import com.github.sidhant92.boolparser.operator.comparison.ContainsAllOperator;
import com.github.sidhant92.boolparser.operator.comparison.ContainsAnyOperator;
import com.github.sidhant92.boolparser.operator.comparison.EqualsOperator;
import com.github.sidhant92.boolparser.operator.comparison.GreaterThanEqualOperator;
import com.github.sidhant92.boolparser.operator.comparison.GreaterThanOperator;
import com.github.sidhant92.boolparser.operator.comparison.InOperator;
import com.github.sidhant92.boolparser.operator.comparison.LessThanEqualOperator;
import com.github.sidhant92.boolparser.operator.comparison.LessThanOperator;
import com.github.sidhant92.boolparser.operator.comparison.NotEqualsOperator;

/**
* @author sidhant.aggarwal
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.github.sidhant92.boolparser.operator;

import java.util.List;
import java.util.Objects;
import org.apache.commons.lang3.tuple.Pair;
import com.github.sidhant92.boolparser.constant.ContainerDataType;
import com.github.sidhant92.boolparser.constant.DataType;
import com.github.sidhant92.boolparser.constant.Operator;
import com.github.sidhant92.boolparser.datatype.DataTypeFactory;
import com.github.sidhant92.boolparser.exception.InvalidContainerTypeException;
import com.github.sidhant92.boolparser.exception.InvalidDataType;
import com.github.sidhant92.boolparser.operator.logical.AbstractOperator;
import com.github.sidhant92.boolparser.operator.comparison.AbstractOperator;

/**
* @author sidhant.aggarwal
Expand All @@ -19,19 +21,24 @@ public OperatorService() {
OperatorFactory.initialize();
}

public boolean evaluateLogicalOperator(final Operator operator, final ContainerDataType containerDataType, final DataType dataType,
final Object leftOperand, final Object... rightOperands) {
public boolean evaluateLogicalOperator(final Operator operator, final ContainerDataType containerDataType, final Object leftOperand,
final DataType leftOperandDataType, final List<Pair<Object, DataType>> rightOperands) {
final AbstractOperator abstractOperator = OperatorFactory.getLogicalOperator(operator);
if (!abstractOperator.getAllowedContainerTypes().contains(containerDataType)) {
throw new InvalidContainerTypeException(String.format("Invalid left container type %s for operator %s", containerDataType, operator));
}
if (!abstractOperator.getAllowedDataTypes().contains(dataType)) {
throw new InvalidDataType(String.format("Invalid left operand data type %s for operator %s", dataType, operator));
if (!abstractOperator.getAllowedDataTypes().contains(leftOperandDataType)) {
throw new InvalidDataType(String.format("Invalid left operand data type %s for operator %s", leftOperandDataType, operator));
}
if (!containerDataType.isValid(dataType, leftOperand)) {
if (!containerDataType.isValid(leftOperandDataType, leftOperand)) {
throw new InvalidDataType(String.format("Validation failed for the operator %s for the operand %s", operator, leftOperand));
}
return OperatorFactory.getLogicalOperator(operator).evaluate(containerDataType, dataType, leftOperand, rightOperands);
rightOperands.forEach(rightOperand -> {
if (!abstractOperator.getAllowedDataTypes().contains(rightOperand.getRight())) {
throw new InvalidDataType(String.format("Invalid right operand data type %s for operator %s", rightOperand.getRight(), operator));
}
});
return OperatorFactory.getLogicalOperator(operator).evaluate(containerDataType, leftOperand, leftOperandDataType, rightOperands);
}

public Object evaluateArithmeticOperator(final Object leftOperand, final DataType leftDataType, final Object rightOperand,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.sidhant92.boolparser.operator.logical;
package com.github.sidhant92.boolparser.operator.comparison;

import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import com.github.sidhant92.boolparser.constant.ContainerDataType;
import com.github.sidhant92.boolparser.constant.DataType;
import com.github.sidhant92.boolparser.constant.Operator;
Expand All @@ -10,8 +11,9 @@
* @since 05/03/2023
*/
public abstract class AbstractOperator {
public abstract <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final DataType dataType,
final Object leftOperand, final Object... rightOperands);
public abstract <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final Object leftOperand,
final DataType leftOperandDataType,
final List<Pair<Object, DataType>> rightOperands);

public abstract Operator getOperator();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.github.sidhant92.boolparser.operator.logical;
package com.github.sidhant92.boolparser.operator.comparison;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import com.github.sidhant92.boolparser.constant.ContainerDataType;
import com.github.sidhant92.boolparser.constant.DataType;
import com.github.sidhant92.boolparser.constant.Operator;
Expand All @@ -13,15 +15,18 @@ public class ContainsAllOperator extends AbstractOperator {
private final InOperator inOperator;

@Override
public <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final DataType dataType,
final Object leftOperand, final Object... rightOperands) {
if (!containerDataType.isValid(dataType, leftOperand)) {
public <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final Object leftOperand,
final DataType leftOperandDataType, final List<Pair<Object, DataType>> rightOperands) {
if (!containerDataType.isValid(leftOperandDataType, leftOperand)) {
return false;
}
final Object[] leftOperandArray = ((List<?>) leftOperand).toArray();
return Arrays
.stream(rightOperands)
.allMatch(rightOperand -> inOperator.evaluate(ContainerDataType.PRIMITIVE, dataType, rightOperand, leftOperandArray));
final List<Pair<Object, DataType>> leftOperandArray = Arrays
.stream(((List<?>) leftOperand).toArray())
.map(a -> Pair.of(a, leftOperandDataType))
.collect(Collectors.toList());
return rightOperands
.stream().allMatch(rightOperand -> inOperator.evaluate(ContainerDataType.PRIMITIVE, rightOperand.getLeft(), rightOperand.getRight(),
leftOperandArray));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.github.sidhant92.boolparser.operator.logical;
package com.github.sidhant92.boolparser.operator.comparison;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import com.github.sidhant92.boolparser.constant.ContainerDataType;
import com.github.sidhant92.boolparser.constant.DataType;
import com.github.sidhant92.boolparser.constant.Operator;
Expand All @@ -13,15 +15,18 @@ public class ContainsAnyOperator extends AbstractOperator {
private final InOperator inOperator;

@Override
public <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final DataType dataType,
final Object leftOperand, final Object... rightOperands) {
if (!containerDataType.isValid(dataType, leftOperand)) {
public <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final Object leftOperand,
final DataType leftOperandDataType, final List<Pair<Object, DataType>> rightOperands) {
if (!containerDataType.isValid(leftOperandDataType, leftOperand)) {
return false;
}
final Object[] leftOperandArray = ((List<?>) leftOperand).toArray();
return Arrays
.stream(rightOperands)
.anyMatch(rightOperand -> inOperator.evaluate(ContainerDataType.PRIMITIVE, dataType, rightOperand, leftOperandArray));
final List<Pair<Object, DataType>> leftOperandArray = Arrays
.stream(((List<?>) leftOperand).toArray())
.map(a -> Pair.of(a, leftOperandDataType))
.collect(Collectors.toList());
return rightOperands
.stream().anyMatch(rightOperand -> inOperator.evaluate(ContainerDataType.PRIMITIVE, rightOperand.getLeft(), rightOperand.getRight(),
leftOperandArray));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package com.github.sidhant92.boolparser.operator.logical;
package com.github.sidhant92.boolparser.operator.comparison;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.apache.commons.lang3.tuple.Pair;
import com.github.sidhant92.boolparser.constant.ContainerDataType;
import com.github.sidhant92.boolparser.constant.DataType;
import com.github.sidhant92.boolparser.constant.Operator;
Expand All @@ -14,11 +15,22 @@
*/
public class EqualsOperator extends AbstractOperator {
@Override
public <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final DataType dataType,
final Object leftOperand, final Object... rightOperands) {
final Optional<T> leftValueOptional = containerDataType.getValue(dataType, leftOperand);
final Optional<T> rightValueOptional = containerDataType.getValue(dataType, rightOperands[0]);
return leftValueOptional.flatMap(leftValue -> rightValueOptional.map(leftValue::compareTo).map(a -> a == 0)).orElse(false);
public <T extends Comparable<? super T>> boolean evaluate(final ContainerDataType containerDataType, final Object leftOperand,
final DataType leftOperandDataType, final List<Pair<Object, DataType>> rightOperands) {
final DataType comparisonType = getComparableDataType(leftOperandDataType, rightOperands.get(0).getRight());
final Optional<T> leftValueOptional = containerDataType.getValue(comparisonType, leftOperand);
final Optional<T> rightValueOptional = containerDataType.getValue(comparisonType, rightOperands.get(0).getLeft());
return leftValueOptional
.flatMap(leftValue -> rightValueOptional
.map(leftValue::compareTo)
.map(a -> a == 0)).orElse(false);
}

private DataType getComparableDataType(final DataType leftOperandDataType, final DataType rightOperandDataType) {
if (leftOperandDataType.priority > rightOperandDataType.priority) {
return leftOperandDataType;
}
return rightOperandDataType;
}

@Override
Expand Down
Loading