-
Notifications
You must be signed in to change notification settings - Fork 208
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature: operators in data-prepper expression (#1065)
* FEAT: operators and tests Signed-off-by: Chen <[email protected]> * MAINT: lower -> less Signed-off-by: Chen <[email protected]> * MAINT: use int for symbol Signed-off-by: Chen <[email protected]> * MAINT: include null in equality operators Signed-off-by: Chen <[email protected]> * MAINT: operator classes package private Signed-off-by: Chen <[email protected]> * STY: eval -> evaluate Signed-off-by: Chen <[email protected]> * MAINT: simplify numerical value comparison operators Signed-off-by: Chen <[email protected]> * MAINT: DI annotation on operators Signed-off-by: Chen <[email protected]> * MAINT: OperatorFactory to produce negate and numeric comparison operator Signed-off-by: Chen <[email protected]> * MAINT: use NumericCompareOperator Signed-off-by: Chen <[email protected]> * MAINT: generic operator to cover negate Signed-off-by: Chen <[email protected]> * MAINT: generic operators Signed-off-by: Chen <[email protected]> * STY: static final Signed-off-by: Chen <[email protected]> * MNT: Objects::equals Signed-off-by: Chen <[email protected]>
- Loading branch information
1 parent
7f8d83d
commit 3831d57
Showing
23 changed files
with
1,032 additions
and
0 deletions.
There are no files selected for viewing
32 changes: 32 additions & 0 deletions
32
data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/AndOperator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.dataprepper.expression; | ||
|
||
import org.opensearch.dataprepper.expression.antlr.DataPrepperExpressionParser; | ||
|
||
import javax.inject.Named; | ||
|
||
import static com.google.common.base.Preconditions.checkArgument; | ||
|
||
@Named | ||
class AndOperator implements Operator<Boolean> { | ||
private static final Integer SYMBOL = DataPrepperExpressionParser.AND; | ||
private static final String DISPLAY_NAME = DataPrepperExpressionParser.VOCABULARY | ||
.getDisplayName(DataPrepperExpressionParser.AND); | ||
|
||
@Override | ||
public Integer getSymbol() { | ||
return SYMBOL; | ||
} | ||
|
||
@Override | ||
public Boolean evaluate(final Object... args) { | ||
checkArgument(args.length == 2, DISPLAY_NAME + " requires operands length to be 2."); | ||
checkArgument(args[0] instanceof Boolean, DISPLAY_NAME + " requires left operand to be Boolean."); | ||
checkArgument(args[1] instanceof Boolean, DISPLAY_NAME + " requires right operand to be Boolean."); | ||
return ((Boolean) args[0]) && ((Boolean) args[1]); | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
...-expression/src/main/java/org/opensearch/dataprepper/expression/GenericEqualOperator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.dataprepper.expression; | ||
|
||
import org.opensearch.dataprepper.expression.antlr.DataPrepperExpressionParser; | ||
|
||
import java.util.function.BiPredicate; | ||
|
||
import static com.google.common.base.Preconditions.checkArgument; | ||
|
||
public class GenericEqualOperator implements Operator<Boolean> { | ||
private final Integer symbol; | ||
private final String displayName; | ||
private final BiPredicate<Object, Object> operation; | ||
|
||
public GenericEqualOperator(final Integer symbol, BiPredicate<Object, Object> operation) { | ||
this.symbol = symbol; | ||
displayName = DataPrepperExpressionParser.VOCABULARY.getDisplayName(symbol); | ||
this.operation = operation; | ||
} | ||
|
||
@Override | ||
public Integer getSymbol() { | ||
return symbol; | ||
} | ||
|
||
@Override | ||
public Boolean evaluate(final Object... args) { | ||
checkArgument(args.length == 2, displayName + " requires operands length to be 2."); | ||
final Object leftOperand = args[0]; | ||
final Object rightOperand = args[1]; | ||
return operation.test(leftOperand, rightOperand); | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
...-expression/src/main/java/org/opensearch/dataprepper/expression/GenericInSetOperator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.dataprepper.expression; | ||
|
||
import org.opensearch.dataprepper.expression.antlr.DataPrepperExpressionParser; | ||
|
||
import java.util.Set; | ||
import java.util.function.BiPredicate; | ||
|
||
import static com.google.common.base.Preconditions.checkArgument; | ||
|
||
public class GenericInSetOperator implements Operator<Boolean> { | ||
private final Integer symbol; | ||
private final String displayName; | ||
private final BiPredicate<Object, Object> operation; | ||
|
||
public GenericInSetOperator(final Integer symbol, BiPredicate<Object, Object> operation) { | ||
this.symbol = symbol; | ||
displayName = DataPrepperExpressionParser.VOCABULARY.getDisplayName(symbol); | ||
this.operation = operation; | ||
} | ||
|
||
@Override | ||
public Integer getSymbol() { | ||
return symbol; | ||
} | ||
|
||
@Override | ||
public Boolean evaluate(final Object... args) { | ||
checkArgument(args.length == 2, displayName + " requires operands length to be 2."); | ||
if (!(args[1] instanceof Set)) { | ||
throw new IllegalArgumentException(displayName + " requires right operand to be Set."); | ||
} | ||
return operation.test(args[0], args[1]); | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
...ession/src/main/java/org/opensearch/dataprepper/expression/GenericRegexMatchOperator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.dataprepper.expression; | ||
|
||
import org.opensearch.dataprepper.expression.antlr.DataPrepperExpressionParser; | ||
|
||
import java.util.function.BiPredicate; | ||
import java.util.regex.PatternSyntaxException; | ||
|
||
import static com.google.common.base.Preconditions.checkArgument; | ||
|
||
public class GenericRegexMatchOperator implements Operator<Boolean> { | ||
private final Integer symbol; | ||
private final String displayName; | ||
private final BiPredicate<Object, Object> operation; | ||
|
||
public GenericRegexMatchOperator(final Integer symbol, BiPredicate<Object, Object> operation) { | ||
this.symbol = symbol; | ||
displayName = DataPrepperExpressionParser.VOCABULARY.getDisplayName(symbol); | ||
this.operation = operation; | ||
} | ||
|
||
@Override | ||
public Integer getSymbol() { | ||
return symbol; | ||
} | ||
|
||
@Override | ||
public Boolean evaluate(final Object... args) { | ||
checkArgument(args.length == 2, displayName + " requires operands length needs to be 2."); | ||
checkArgument(args[0] instanceof String, displayName + " requires left operand to be String."); | ||
checkArgument(args[1] instanceof String, displayName + " requires right operand to be String."); | ||
try { | ||
return operation.test(args[0], args[1]); | ||
} catch (final PatternSyntaxException e) { | ||
throw new IllegalArgumentException(e); | ||
} | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/NotOperator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.dataprepper.expression; | ||
|
||
import org.opensearch.dataprepper.expression.antlr.DataPrepperExpressionParser; | ||
|
||
import javax.inject.Named; | ||
|
||
import static com.google.common.base.Preconditions.checkArgument; | ||
|
||
@Named | ||
class NotOperator implements Operator<Boolean> { | ||
private static final Integer SYMBOL = DataPrepperExpressionParser.NOT; | ||
private static final String DISPLAY_NAME = DataPrepperExpressionParser.VOCABULARY | ||
.getDisplayName(DataPrepperExpressionParser.NOT); | ||
|
||
@Override | ||
public Integer getSymbol() { | ||
return SYMBOL; | ||
} | ||
|
||
@Override | ||
public Boolean evaluate(final Object... args) { | ||
checkArgument(args.length == 1, DISPLAY_NAME + " requires operands length to be 1."); | ||
checkArgument(args[0] instanceof Boolean, DISPLAY_NAME + " requires operand to be Boolean."); | ||
return !((Boolean) args[0]); | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
...xpression/src/main/java/org/opensearch/dataprepper/expression/NumericCompareOperator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.dataprepper.expression; | ||
|
||
import org.opensearch.dataprepper.expression.antlr.DataPrepperExpressionParser; | ||
|
||
import java.util.Map; | ||
import java.util.function.BiFunction; | ||
|
||
import static com.google.common.base.Preconditions.checkArgument; | ||
|
||
public class NumericCompareOperator implements Operator<Boolean> { | ||
private final Integer symbol; | ||
private final String displayName; | ||
private final Map<Class<? extends Number>, Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>>> operandsToOperationMap; | ||
|
||
public NumericCompareOperator( | ||
final Integer symbol, | ||
final Map<Class<? extends Number>, Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>>> operandsToOperationMap) { | ||
this.symbol = symbol; | ||
displayName = DataPrepperExpressionParser.VOCABULARY.getDisplayName(symbol); | ||
this.operandsToOperationMap = operandsToOperationMap; | ||
} | ||
|
||
@Override | ||
public Integer getSymbol() { | ||
return symbol; | ||
} | ||
|
||
@Override | ||
public Boolean evaluate(final Object... args) { | ||
checkArgument(args.length == 2, displayName + " requires operands length needs to be 2."); | ||
final Object leftValue = args[0]; | ||
final Object rightValue = args[1]; | ||
final Class<?> leftValueClass = leftValue.getClass(); | ||
final Class<?> rightValueClass = rightValue.getClass(); | ||
if (!operandsToOperationMap.containsKey(leftValueClass)) { | ||
throw new IllegalArgumentException(displayName + " requires left operand to be either Float or Integer."); | ||
} | ||
Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>> rightOperandToOperation = | ||
operandsToOperationMap.get(leftValueClass); | ||
if (!rightOperandToOperation.containsKey(rightValueClass)) { | ||
throw new IllegalArgumentException(displayName + " requires right operand to be either Float or Integer."); | ||
} | ||
final BiFunction<Object, Object, Boolean> operation = rightOperandToOperation.get(rightValueClass); | ||
return operation.apply(leftValue, rightValue); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/Operator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.dataprepper.expression; | ||
|
||
interface Operator<T> { | ||
Integer getSymbol(); | ||
|
||
/** | ||
* @since 1.3 | ||
* Placeholder interface for implementing Data-Prepper supported binary/unary operations on operands that | ||
* returns custom type T. | ||
* @param args operands | ||
* @return T | ||
*/ | ||
T evaluate(final Object... args); | ||
} |
130 changes: 130 additions & 0 deletions
130
...epper-expression/src/main/java/org/opensearch/dataprepper/expression/OperatorFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.dataprepper.expression; | ||
|
||
import org.opensearch.dataprepper.expression.antlr.DataPrepperExpressionParser; | ||
import org.springframework.context.annotation.Bean; | ||
|
||
import javax.inject.Named; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
import java.util.Set; | ||
import java.util.function.BiFunction; | ||
import java.util.function.BiPredicate; | ||
|
||
@Named | ||
public class OperatorFactory { | ||
public final BiPredicate<Object, Object> regexEquals = (x, y) -> ((String) x).matches((String) y); | ||
public final BiPredicate<Object, Object> equals = Objects::equals; | ||
public final BiPredicate<Object, Object> inSet = (x, y) -> ((Set<?>) y).contains(x); | ||
|
||
@Bean | ||
public NumericCompareOperator greaterThanOperator() { | ||
final Map<Class<? extends Number>, Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>>> | ||
operandsToOperationMap = new HashMap<>(); | ||
final Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>> intOperations = | ||
new HashMap<Class<? extends Number>, BiFunction<Object, Object, Boolean>>() {{ | ||
put(Integer.class, (lhs, rhs) -> (Integer) lhs > (Integer) rhs); | ||
put(Float.class, (lhs, rhs) -> (Integer) lhs > (Float) rhs);}}; | ||
final Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>> floatOperations = | ||
new HashMap<Class<? extends Number>, BiFunction<Object, Object, Boolean>>() {{ | ||
put(Integer.class, (lhs, rhs) -> (Float) lhs > (Integer) rhs); | ||
put(Float.class, (lhs, rhs) -> (Float) lhs > (Float) rhs);}}; | ||
|
||
operandsToOperationMap.put(Integer.class, intOperations); | ||
operandsToOperationMap.put(Float.class, floatOperations); | ||
|
||
return new NumericCompareOperator(DataPrepperExpressionParser.GT, operandsToOperationMap); | ||
} | ||
|
||
@Bean | ||
public NumericCompareOperator greaterThanOrEqualOperator() { | ||
final Map<Class<? extends Number>, Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>>> | ||
operandsToOperationMap = new HashMap<>(); | ||
final Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>> intOperations = | ||
new HashMap<Class<? extends Number>, BiFunction<Object, Object, Boolean>>() {{ | ||
put(Integer.class, (lhs, rhs) -> (Integer) lhs >= (Integer) rhs); | ||
put(Float.class, (lhs, rhs) -> (Integer) lhs >= (Float) rhs);}}; | ||
final Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>> floatOperations = | ||
new HashMap<Class<? extends Number>, BiFunction<Object, Object, Boolean>>() {{ | ||
put(Integer.class, (lhs, rhs) -> (Float) lhs >= (Integer) rhs); | ||
put(Float.class, (lhs, rhs) -> (Float) lhs >= (Float) rhs);}}; | ||
|
||
operandsToOperationMap.put(Integer.class, intOperations); | ||
operandsToOperationMap.put(Float.class, floatOperations); | ||
|
||
return new NumericCompareOperator(DataPrepperExpressionParser.GTE, operandsToOperationMap); | ||
} | ||
|
||
@Bean | ||
public NumericCompareOperator lessThanOperator() { | ||
final Map<Class<? extends Number>, Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>>> | ||
operandsToOperationMap = new HashMap<>(); | ||
final Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>> intOperations = | ||
new HashMap<Class<? extends Number>, BiFunction<Object, Object, Boolean>>() {{ | ||
put(Integer.class, (lhs, rhs) -> (Integer) lhs < (Integer) rhs); | ||
put(Float.class, (lhs, rhs) -> (Integer) lhs < (Float) rhs);}}; | ||
final Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>> floatOperations = | ||
new HashMap<Class<? extends Number>, BiFunction<Object, Object, Boolean>>() {{ | ||
put(Integer.class, (lhs, rhs) -> (Float) lhs < (Integer) rhs); | ||
put(Float.class, (lhs, rhs) -> (Float) lhs < (Float) rhs);}}; | ||
|
||
operandsToOperationMap.put(Integer.class, intOperations); | ||
operandsToOperationMap.put(Float.class, floatOperations); | ||
|
||
return new NumericCompareOperator(DataPrepperExpressionParser.LT, operandsToOperationMap); | ||
} | ||
|
||
@Bean | ||
public NumericCompareOperator lessThanOrEqualOperator() { | ||
final Map<Class<? extends Number>, Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>>> | ||
operandsToOperationMap = new HashMap<>(); | ||
final Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>> intOperations = | ||
new HashMap<Class<? extends Number>, BiFunction<Object, Object, Boolean>>() {{ | ||
put(Integer.class, (lhs, rhs) -> (Integer) lhs <= (Integer) rhs); | ||
put(Float.class, (lhs, rhs) -> (Integer) lhs <= (Float) rhs);}}; | ||
final Map<Class<? extends Number>, BiFunction<Object, Object, Boolean>> floatOperations = | ||
new HashMap<Class<? extends Number>, BiFunction<Object, Object, Boolean>>() {{ | ||
put(Integer.class, (lhs, rhs) -> (Float) lhs <= (Integer) rhs); | ||
put(Float.class, (lhs, rhs) -> (Float) lhs <= (Float) rhs);}}; | ||
|
||
operandsToOperationMap.put(Integer.class, intOperations); | ||
operandsToOperationMap.put(Float.class, floatOperations); | ||
|
||
return new NumericCompareOperator(DataPrepperExpressionParser.LTE, operandsToOperationMap); | ||
} | ||
|
||
@Bean | ||
public GenericRegexMatchOperator regexEqualOperator() { | ||
return new GenericRegexMatchOperator(DataPrepperExpressionParser.MATCH_REGEX_PATTERN, regexEquals); | ||
} | ||
|
||
@Bean | ||
public GenericRegexMatchOperator regexNotEqualOperator() { | ||
return new GenericRegexMatchOperator(DataPrepperExpressionParser.NOT_MATCH_REGEX_PATTERN, regexEquals.negate()); | ||
} | ||
|
||
@Bean | ||
public GenericEqualOperator equalOperator() { | ||
return new GenericEqualOperator(DataPrepperExpressionParser.EQUAL, equals); | ||
} | ||
|
||
@Bean | ||
public GenericEqualOperator notEqualOperator() { | ||
return new GenericEqualOperator(DataPrepperExpressionParser.NOT_EQUAL, equals.negate()); | ||
} | ||
|
||
@Bean | ||
public GenericInSetOperator inSetOperator() { | ||
return new GenericInSetOperator(DataPrepperExpressionParser.IN_SET, inSet); | ||
} | ||
|
||
@Bean | ||
public GenericInSetOperator notInSetOperator() { | ||
return new GenericInSetOperator(DataPrepperExpressionParser.NOT_IN_SET, inSet.negate()); | ||
} | ||
} |
Oops, something went wrong.