[Cps Path Parser] Refactoring leaf conditions 82/138882/1
authordanielhanrahan <daniel.hanrahan@est.tech>
Sat, 31 Aug 2024 21:30:16 +0000 (22:30 +0100)
committerdanielhanrahan <daniel.hanrahan@est.tech>
Sat, 31 Aug 2024 21:32:12 +0000 (22:32 +0100)
Instead of DataLeaf and ComparativeOperators classes,
we more simply have LeafConditions class with all info.

Issue-ID: CPS-2365
Signed-off-by: danielhanrahan <daniel.hanrahan@est.tech>
Change-Id: I8fd18bb56b8ed9d26a3f9d36f487d00a9274c8bc

cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java
cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java
cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy
cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentQueryBuilder.java

index 0bb0923..1993e17 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2023 Nordix Foundation
+ *  Copyright (C) 2021-2024 Nordix Foundation
  *  Modifications Copyright (C) 2023 TechMahindra Ltd
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -43,7 +43,7 @@ public class CpsPathBuilder extends CpsPathBaseListener {
 
     private final CpsPathQuery cpsPathQuery = new CpsPathQuery();
 
-    private final List<CpsPathQuery.DataLeaf> leavesData = new ArrayList<>();
+    private final List<CpsPathQuery.LeafCondition> leafConditions = new ArrayList<>();
 
     private final StringBuilder normalizedXpathBuilder = new StringBuilder();
 
@@ -55,8 +55,6 @@ public class CpsPathBuilder extends CpsPathBaseListener {
 
     private final List<String> booleanOperators = new ArrayList<>();
 
-    private final List<String> comparativeOperators = new ArrayList<>();
-
     @Override
     public void exitInvalidPostFix(final CpsPathParser.InvalidPostFixContext ctx) {
         throw new PathParsingException(ctx.getText());
@@ -79,6 +77,8 @@ public class CpsPathBuilder extends CpsPathBaseListener {
 
     @Override
     public void exitLeafCondition(final LeafConditionContext ctx) {
+        final String leafName = ctx.leafName().getText();
+        final String operator = ctx.comparativeOperators().getText();
         final Object comparisonValue;
         if (ctx.IntegerLiteral() != null) {
             comparisonValue = Integer.valueOf(ctx.IntegerLiteral().getText());
@@ -87,7 +87,7 @@ public class CpsPathBuilder extends CpsPathBaseListener {
         } else {
             throw new PathParsingException("Unsupported comparison value encountered in expression" + ctx.getText());
         }
-        leafContext(ctx.leafName(), comparisonValue);
+        leafContext(leafName, operator, comparisonValue);
     }
 
     @Override
@@ -95,11 +95,6 @@ public class CpsPathBuilder extends CpsPathBaseListener {
         booleanOperators.add(ctx.getText());
     }
 
-    @Override
-    public void exitComparativeOperators(final CpsPathParser.ComparativeOperatorsContext ctx) {
-        comparativeOperators.add(ctx.getText());
-    }
-
     @Override
     public void exitDescendant(final DescendantContext ctx) {
         cpsPathQuery.setCpsPathPrefixType(DESCENDANT);
@@ -110,15 +105,14 @@ public class CpsPathBuilder extends CpsPathBaseListener {
     @Override
     public void enterMultipleLeafConditions(final MultipleLeafConditionsContext ctx)  {
         normalizedXpathBuilder.append(OPEN_BRACKET);
-        leavesData.clear();
+        leafConditions.clear();
         booleanOperators.clear();
-        comparativeOperators.clear();
     }
 
     @Override
     public void exitMultipleLeafConditions(final MultipleLeafConditionsContext ctx) {
         normalizedXpathBuilder.append(CLOSE_BRACKET);
-        cpsPathQuery.setLeavesData(leavesData);
+        cpsPathQuery.setLeafConditions(leafConditions);
     }
 
     @Override
@@ -164,7 +158,6 @@ public class CpsPathBuilder extends CpsPathBaseListener {
         cpsPathQuery.setNormalizedXpath(normalizedXpathBuilder.toString());
         cpsPathQuery.setContainerNames(containerNames);
         cpsPathQuery.setBooleanOperators(booleanOperators);
-        cpsPathQuery.setComparativeOperators(comparativeOperators);
         if (cpsPathQuery.hasAncestorAxis() && cpsPathQuery.getXpathPrefix()
                 .endsWith("/" + cpsPathQuery.getAncestorSchemaNodeIdentifier())) {
             cpsPathQuery.setAncestorSchemaNodeIdentifier("");
@@ -183,16 +176,16 @@ public class CpsPathBuilder extends CpsPathBaseListener {
         }
     }
 
-    private void leafContext(final CpsPathParser.LeafNameContext ctx, final Object comparisonValue) {
-        leavesData.add(new CpsPathQuery.DataLeaf(ctx.getText(), comparisonValue));
-        appendCondition(normalizedXpathBuilder, ctx.getText(), comparisonValue);
+    private void leafContext(final String leafName, final String operator, final Object comparisonValue) {
+        leafConditions.add(new CpsPathQuery.LeafCondition(leafName, operator, comparisonValue));
+        appendCondition(normalizedXpathBuilder, leafName, operator, comparisonValue);
         if (processingAncestorAxis) {
-            appendCondition(normalizedAncestorPathBuilder, ctx.getText(), comparisonValue);
+            appendCondition(normalizedAncestorPathBuilder, leafName, operator, comparisonValue);
         }
     }
 
     private void appendCondition(final StringBuilder currentNormalizedPathBuilder, final String name,
-                                 final Object value) {
+                                 final String operator, final Object value) {
         final char lastCharacter = currentNormalizedPathBuilder.charAt(currentNormalizedPathBuilder.length() - 1);
         final boolean isStartOfExpression = lastCharacter == '[';
         if (!isStartOfExpression) {
@@ -200,7 +193,7 @@ public class CpsPathBuilder extends CpsPathBaseListener {
         }
         currentNormalizedPathBuilder.append("@")
                                     .append(name)
-                                    .append(getLastElement(comparativeOperators))
+                                    .append(operator)
                                     .append("'")
                                     .append(value.toString().replace("'", "''"))
                                     .append("'");
index f98df05..03602b6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2023 Nordix Foundation
+ *  Copyright (C) 2021-2024 Nordix Foundation
  *  Modifications Copyright (C) 2023 TechMahindra Ltd
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,8 +25,6 @@ import static org.onap.cps.cpspath.parser.CpsPathPrefixType.ABSOLUTE;
 
 import java.util.List;
 import lombok.AccessLevel;
-import lombok.AllArgsConstructor;
-import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -40,12 +38,11 @@ public class CpsPathQuery {
     private List<String> containerNames;
     private CpsPathPrefixType cpsPathPrefixType = ABSOLUTE;
     private String descendantName;
-    private List<DataLeaf> leavesData;
+    private List<LeafCondition> leafConditions;
     private String ancestorSchemaNodeIdentifier = "";
     private String textFunctionConditionLeafName;
     private String textFunctionConditionValue;
     private List<String> booleanOperators;
-    private List<String> comparativeOperators;
     private String containsFunctionConditionLeafName;
     private String containsFunctionConditionValue;
 
@@ -74,7 +71,7 @@ public class CpsPathQuery {
      * @return boolean value.
      */
     public boolean hasLeafConditions() {
-        return leavesData != null;
+        return leafConditions != null;
     }
 
     /**
@@ -104,11 +101,6 @@ public class CpsPathQuery {
         return cpsPathPrefixType == ABSOLUTE && hasLeafConditions();
     }
 
-    @Getter
-    @EqualsAndHashCode
-    @AllArgsConstructor
-    public static class DataLeaf {
-        private final String name;
-        private final Object value;
-    }
+    public record LeafCondition(String name, String operator, Object value) { }
+
 }
index 15f6b11..730c826 100644 (file)
@@ -48,8 +48,8 @@ class CpsPathQuerySpec extends Specification {
         and: 'the right query parameters are set'
             assert result.xpathPrefix == expectedXpathPrefix
             assert result.hasLeafConditions()
-            assert result.leavesData[0].name == expectedLeafName
-            assert result.leavesData[0].value == expectedLeafValue
+            assert result.leafConditions[0].name() == expectedLeafName
+            assert result.leafConditions[0].value() == expectedLeafValue
         where: 'the following data is used'
             scenario               | cpsPath                                                    || expectedXpathPrefix                             | expectedLeafName       | expectedLeafValue
             'leaf of type String'  | '/parent/child[@common-leaf-name="common-leaf-value"]'     || '/parent/child'                                 | 'common-leaf-name'     | 'common-leaf-value'
@@ -123,11 +123,11 @@ class CpsPathQuerySpec extends Specification {
         when: 'the given cps path is parsed'
             def result = CpsPathQuery.createFrom(cpsPath)
         then: 'the expected number of leaves are returned'
-            result.leavesData.size() == expectedNumberOfLeaves
+            result.leafConditions.size() == expectedNumberOfLeaves
         and: 'the given operator(s) returns in the correct order'
             result.booleanOperators == expectedOperators
         and: 'the given comparativeOperator(s) returns in the correct order'
-            result.comparativeOperators == expectedComparativeOperator
+            result.leafConditions.operator == expectedComparativeOperator
         where: 'the following data is used'
             cpsPath                                                                                   || expectedNumberOfLeaves || expectedOperators || expectedComparativeOperator
             '/parent[@code=1]/child[@common-leaf-name-int=5]'                                         || 1                      || []                || ['=']
@@ -234,19 +234,19 @@ class CpsPathQuerySpec extends Specification {
         when: 'the given cps path is parsed using multiple conditions on same leaf'
             def result = CpsPathQuery.createFrom('/test[@same-name="value1" or @same-name="value2"]')
         then: 'two leaves are present with correct values'
-            assert result.leavesData.size() == 2
-            assert result.leavesData[0].name == "same-name"
-            assert result.leavesData[0].value == "value1"
-            assert result.leavesData[1].name == "same-name"
-            assert result.leavesData[1].value == "value2"
+            assert result.leafConditions.size() == 2
+            assert result.leafConditions[0].name == "same-name"
+            assert result.leafConditions[0].value == "value1"
+            assert result.leafConditions[1].name == "same-name"
+            assert result.leafConditions[1].value == "value2"
     }
 
     def 'Ordering of data leaves is preserved.'() {
         when: 'the given cps path is parsed'
             def result = CpsPathQuery.createFrom(cpsPath)
         then: 'the order of the data leaves is preserved'
-            assert result.leavesData[0].name == expectedFirstLeafName
-            assert result.leavesData[1].name == expectedSecondLeafName
+            assert result.leafConditions[0].name == expectedFirstLeafName
+            assert result.leafConditions[1].name == expectedSecondLeafName
         where: 'the following data is used'
             cpsPath                                      || expectedFirstLeafName | expectedSecondLeafName
             '/test[@name1="value1" and @name2="value2"]' || 'name1'               | 'name2'
index b201475..8171bbe 100644 (file)
@@ -194,22 +194,20 @@ public class FragmentQueryBuilder {
     private void queryLeafConditions(final CpsPathQuery cpsPathQuery, final StringBuilder sqlStringBuilder) {
         sqlStringBuilder.append(" AND (");
         final Queue<String> booleanOperatorsQueue = new LinkedList<>(cpsPathQuery.getBooleanOperators());
-        final Queue<String> comparativeOperatorQueue = new LinkedList<>(cpsPathQuery.getComparativeOperators());
-        cpsPathQuery.getLeavesData().forEach(leaf -> {
-            final String nextComparativeOperator = comparativeOperatorQueue.poll();
-            if (leaf.getValue() instanceof Integer) {
-                sqlStringBuilder.append("(attributes ->> '").append(leaf.getName()).append("')\\:\\:int");
-                sqlStringBuilder.append(nextComparativeOperator);
-                sqlStringBuilder.append(leaf.getValue());
+        cpsPathQuery.getLeafConditions().forEach(leafCondition -> {
+            if (leafCondition.value() instanceof Integer) {
+                sqlStringBuilder.append("(attributes ->> '").append(leafCondition.name()).append("')\\:\\:int");
+                sqlStringBuilder.append(leafCondition.operator());
+                sqlStringBuilder.append(leafCondition.value());
             } else {
-                if ("=".equals(nextComparativeOperator)) {
-                    final String leafValueAsText = leaf.getValue().toString();
-                    sqlStringBuilder.append("attributes ->> '").append(leaf.getName()).append("'");
+                if ("=".equals(leafCondition.operator())) {
+                    final String leafValueAsText = leafCondition.value().toString();
+                    sqlStringBuilder.append("attributes ->> '").append(leafCondition.name()).append("'");
                     sqlStringBuilder.append(" = '");
                     sqlStringBuilder.append(EscapeUtils.escapeForSqlStringLiteral(leafValueAsText));
                     sqlStringBuilder.append("'");
                 } else {
-                    throw new CpsPathException(" can use only " + nextComparativeOperator + " with integer ");
+                    throw new CpsPathException(" can use only " + leafCondition.operator() + " with integer ");
                 }
             }
             if (!booleanOperatorsQueue.isEmpty()) {