From fbe059f3ffb80afeb902ff67f30a2db8fd162ae5 Mon Sep 17 00:00:00 2001 From: Krishna Kondaka <41027584+kkondaka@users.noreply.github.com> Date: Thu, 9 May 2024 13:54:36 -0700 Subject: [PATCH] Modify typeof operator grammar and add support for ArrayList (#4523) * Modify typeof operator grammar and add support for ArrayList Signed-off-by: Krishna Kondaka * Fixed checkstyle error Signed-off-by: Krishna Kondaka * Added test case for more code coverage Signed-off-by: Krishna Kondaka --------- Signed-off-by: Krishna Kondaka Co-authored-by: Krishna Kondaka --- .../dataprepper/model/event/DataType.java | 3 ++- .../src/main/antlr/DataPrepperExpression.g4 | 20 ++++++++++++++++++- .../expression/ParseTreeCoercionService.java | 3 +++ .../ParseTreeCoercionServiceTest.java | 13 ++++++++++++ .../expression/TypeOfOperatorTest.java | 6 ++++++ 5 files changed, 43 insertions(+), 2 deletions(-) diff --git a/data-prepper-api/src/main/java/org/opensearch/dataprepper/model/event/DataType.java b/data-prepper-api/src/main/java/org/opensearch/dataprepper/model/event/DataType.java index 482c764c8a..44852a36ab 100644 --- a/data-prepper-api/src/main/java/org/opensearch/dataprepper/model/event/DataType.java +++ b/data-prepper-api/src/main/java/org/opensearch/dataprepper/model/event/DataType.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import java.util.Arrays; +import java.util.ArrayList; import java.util.Map; import java.util.stream.Collectors; @@ -98,7 +99,7 @@ public static boolean isSameType(final Object object, final String option) { case MAP: return (object instanceof Map); case ARRAY: - return (object.getClass().isArray()); + return (object instanceof ArrayList || object.getClass().isArray()); case DOUBLE: return (object instanceof Double); case BOOLEAN: diff --git a/data-prepper-expression/src/main/antlr/DataPrepperExpression.g4 b/data-prepper-expression/src/main/antlr/DataPrepperExpression.g4 index 897cd0fa64..e0ac5502b2 100644 --- a/data-prepper-expression/src/main/antlr/DataPrepperExpression.g4 +++ b/data-prepper-expression/src/main/antlr/DataPrepperExpression.g4 @@ -91,7 +91,7 @@ relationalOperator ; typeOfOperatorExpression - : JsonPointer TYPEOF String + : JsonPointer TYPEOF DataTypes ; setOperatorExpression @@ -285,6 +285,16 @@ EscapeSequence : '\\' [btnfr"'\\$] ; +DataTypes + : INTEGER + | BOOLEAN + | LONG + | MAP + | ARRAY + | DOUBLE + | STRING + ; + SET_DELIMITER : COMMA ; @@ -324,6 +334,14 @@ EXPONENTLETTER | 'e' ; +INTEGER: 'integer'; +BOOLEAN: 'boolean'; +LONG : 'long'; +DOUBLE : 'double'; +STRING : 'string'; +MAP : 'map'; +ARRAY : 'array'; + fragment SPACE : ' '; diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ParseTreeCoercionService.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ParseTreeCoercionService.java index 6d93cef132..9459dd7845 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ParseTreeCoercionService.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ParseTreeCoercionService.java @@ -82,6 +82,9 @@ public Object coercePrimaryTerminalNode(final TerminalNode node, final Event eve return Boolean.valueOf(nodeStringValue); case DataPrepperExpressionParser.Null: return null; + case DataPrepperExpressionParser.DataTypes: + return nodeStringValue; + default: throw new ExpressionCoercionException("Unsupported terminal node type symbol string: " + DataPrepperExpressionParser.VOCABULARY.getDisplayName(nodeType)); diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeCoercionServiceTest.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeCoercionServiceTest.java index 4dca1dc812..35f10b148c 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeCoercionServiceTest.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeCoercionServiceTest.java @@ -15,6 +15,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.opensearch.dataprepper.expression.antlr.DataPrepperExpressionParser; @@ -112,6 +113,18 @@ void testCoerceTerminalNodeFloatType() { assertThat(result, equalTo(testFloat)); } + @ParameterizedTest + @ValueSource(strings={"integer", "boolean", "long", "string", "double", "map", "array"}) + void testCoerceTerminalNodeDataTypesType(String testString) { + when(token.getType()).thenReturn(DataPrepperExpressionParser.DataTypes); + when(terminalNode.getSymbol()).thenReturn(token); + when(terminalNode.getText()).thenReturn(testString); + final Event testEvent = createTestEvent(new HashMap<>()); + final Object result = objectUnderTest.coercePrimaryTerminalNode(terminalNode, testEvent); + assertThat(result, instanceOf(String.class)); + assertThat(result, equalTo(testString)); + } + @Test void testCoerceTerminalNodeBooleanType() { when(token.getType()).thenReturn(DataPrepperExpressionParser.Boolean); diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/TypeOfOperatorTest.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/TypeOfOperatorTest.java index e780e8e4ca..07e52401ff 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/TypeOfOperatorTest.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/TypeOfOperatorTest.java @@ -20,6 +20,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.stream.Stream; @@ -66,6 +68,9 @@ void testEvalInValidArgType() { private static Stream getTypeOfTestData() { int testArray[] = {1,2}; + List testArrayList = new ArrayList(); + testArrayList.add(1); + testArrayList.add(2); return Stream.of( Arguments.of(2, "integer", true), Arguments.of("testString", "string", true), @@ -74,6 +79,7 @@ private static Stream getTypeOfTestData() { Arguments.of(true, "boolean", true), Arguments.of(Map.of("k","v"), "map", true), Arguments.of(testArray, "array", true), + Arguments.of(testArrayList, "array", true), Arguments.of(2.0, "integer", false), Arguments.of(2, "string", false), Arguments.of("testString", "long", false),