Merge "Query Optimization"
authorJoseph Keenan <joseph.keenan@est.tech>
Thu, 15 Dec 2022 09:54:52 +0000 (09:54 +0000)
committerGerrit Code Review <gerrit@onap.org>
Thu, 15 Dec 2022 09:54:52 +0000 (09:54 +0000)
12 files changed:
cps-dependencies/pom.xml
cps-ncmp-rest-stub/pom.xml
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImpl.java
cps-parent/pom.xml
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java
cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java
cps-service/src/main/java/org/onap/cps/spi/model/DataNode.java
cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java
cps-service/src/test/groovy/org/onap/cps/spi/model/DataNodeBuilderSpec.groovy
cps-service/src/test/resources/data-with-choice-node.json [new file with mode: 0644]
cps-service/src/test/resources/yang-with-choice-node.yang [new file with mode: 0644]

index 5bdf793..fb0638e 100755 (executable)
                 <artifactId>hazelcast-spring</artifactId>
                 <version>4.2.5</version>
             </dependency>
+            <dependency>
+                <groupId>com.google.guava</groupId>
+                <artifactId>guava</artifactId>
+                <version>31.1-jre</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 </project>
index 93c73fc..35784fb 100644 (file)
             <artifactId>slf4j-simple</artifactId>
             <version>1.8.0-beta4</version>
         </dependency>
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-            <version>20.0</version>
-        </dependency>
         <dependency>
             <groupId>cglib</groupId>
             <artifactId>cglib-nodep</artifactId>
index 1a54a82..bda0a72 100644 (file)
@@ -47,6 +47,7 @@ public class CmHandleQueriesImpl implements CmHandleQueries {
 
     private static final String NCMP_DATASPACE_NAME = "NCMP-Admin";
     private static final String NCMP_DMI_REGISTRY_ANCHOR = "ncmp-dmi-registry";
+    private static final String DESCENDANT_PATH = "//";
 
     private final CpsDataPersistenceService cpsDataPersistenceService;
     private static final Map<String, NcmpServiceCmHandle> NO_QUERY_TO_EXECUTE = null;
@@ -72,7 +73,7 @@ public class CmHandleQueriesImpl implements CmHandleQueries {
         }
         Map<String, NcmpServiceCmHandle> cmHandleIdToNcmpServiceCmHandles = null;
         for (final Map.Entry<String, String> publicPropertyQueryPair : propertyQueryPairs.entrySet()) {
-            final String cpsPath = "//" + propertyType.getYangContainerName() + "[@name=\""
+            final String cpsPath = DESCENDANT_PATH + propertyType.getYangContainerName() + "[@name=\""
                     + publicPropertyQueryPair.getKey()
                     + "\" and @value=\"" + publicPropertyQueryPair.getValue() + "\"]";
 
index d3fe0f3..b8408f8 100755 (executable)
@@ -39,7 +39,7 @@
         <app>org.onap.cps.Application</app>
         <java.version>11</java.version>
         <minimum-coverage>0.97</minimum-coverage>
-        <postgres.version>42.5.0</postgres.version>
+        <postgres.version>42.5.1</postgres.version>
 
         <jacoco.reportDirectory.aggregate>${project.reporting.outputDirectory}/jacoco-aggregate</jacoco.reportDirectory.aggregate>
         <sonar.coverage.jacoco.xmlReportPaths>
index b22f171..c725b42 100644 (file)
@@ -24,6 +24,7 @@ package org.onap.cps.spi.impl;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSet.Builder;
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -346,7 +347,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
     private DataNode toDataNode(final FragmentEntity fragmentEntity,
                                 final FetchDescendantsOption fetchDescendantsOption) {
         final List<DataNode> childDataNodes = getChildDataNodes(fragmentEntity, fetchDescendantsOption);
-        Map<String, Object> leaves = new HashMap<>();
+        Map<String, Serializable> leaves = new HashMap<>();
         if (fragmentEntity.getAttributes() != null) {
             leaves = jsonObjectMapper.convertJsonString(fragmentEntity.getAttributes(), Map.class);
         }
@@ -368,7 +369,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
 
     @Override
     public void updateDataLeaves(final String dataspaceName, final String anchorName, final String xpath,
-                                 final Map<String, Object> leaves) {
+                                 final Map<String, Serializable> leaves) {
         final FragmentEntity fragmentEntity = getFragmentWithoutDescendantsByXpath(dataspaceName, anchorName, xpath);
         fragmentEntity.setAttributes(jsonObjectMapper.asJsonString(leaves));
         fragmentRepository.save(fragmentEntity);
index 03f021e..c9f9a78 100755 (executable)
@@ -337,12 +337,14 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
      */
     private String getNameForChecksum(
             final String checksum, final Collection<YangResourceEntity> yangResourceEntities) {
-        return
-                yangResourceEntities.stream()
+        final Optional<String> optionalFileName = yangResourceEntities.stream()
                         .filter(entity -> StringUtils.equals(checksum, (entity.getChecksum())))
                         .findFirst()
-                        .map(YangResourceEntity::getFileName)
-                        .orElse(null);
+                        .map(YangResourceEntity::getFileName);
+        if (optionalFileName.isPresent()) {
+            return optionalFileName.get();
+        }
+        return null;
     }
 
     /**
index 8d4df20..28b18b3 100644 (file)
@@ -22,6 +22,7 @@
 
 package org.onap.cps.spi;
 
+import java.io.Serializable;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -97,7 +98,7 @@ public interface CpsDataPersistenceService {
      * @param xpath         xpath
      * @param leaves        the leaves as a map where key is a leaf name and a value is a leaf value
      */
-    void updateDataLeaves(String dataspaceName, String anchorName, String xpath, Map<String, Object> leaves);
+    void updateDataLeaves(String dataspaceName, String anchorName, String xpath, Map<String, Serializable> leaves);
 
     /**
      * Replaces an existing data node's content including descendants.
index 8170db3..76f33bb 100644 (file)
@@ -46,7 +46,7 @@ public class DataNode implements Serializable {
     private ModuleReference moduleReference;
     private String xpath;
     private String moduleNamePrefix;
-    private Map<String, Object> leaves = Collections.emptyMap();
+    private Map<String, Serializable> leaves = Collections.emptyMap();
     private Collection<String> xpathsChildren;
     private Collection<DataNode> childDataNodes = Collections.emptySet();
 }
index eaa2d77..1d8bac0 100644 (file)
@@ -23,6 +23,7 @@ package org.onap.cps.spi.model;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import java.io.Serializable;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -33,6 +34,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.spi.exceptions.DataValidationException;
 import org.onap.cps.utils.YangUtils;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
@@ -48,7 +50,7 @@ public class DataNodeBuilder {
     private String xpath;
     private String moduleNamePrefix;
     private String parentNodeXpath = "";
-    private Map<String, Object> leaves = Collections.emptyMap();
+    private Map<String, Serializable> leaves = Collections.emptyMap();
     private Collection<DataNode> childDataNodes = Collections.emptySet();
 
     /**
@@ -102,7 +104,7 @@ public class DataNodeBuilder {
      * @param leaves for the data node
      * @return DataNodeBuilder
      */
-    public DataNodeBuilder withLeaves(final Map<String, Object> leaves) {
+    public DataNodeBuilder withLeaves(final Map<String, Serializable> leaves) {
         this.leaves = leaves;
         return this;
     }
@@ -173,14 +175,16 @@ public class DataNodeBuilder {
     private static void addDataNodeFromNormalizedNode(final DataNode currentDataNode,
         final NormalizedNode normalizedNode) {
 
-        if (normalizedNode instanceof DataContainerNode) {
+        if (normalizedNode instanceof ChoiceNode) {
+            addChoiceNode(currentDataNode, (ChoiceNode) normalizedNode);
+        } else if (normalizedNode instanceof DataContainerNode) {
             addYangContainer(currentDataNode, (DataContainerNode) normalizedNode);
         } else if (normalizedNode instanceof MapNode) {
             addDataNodeForEachListElement(currentDataNode, (MapNode) normalizedNode);
         } else if (normalizedNode instanceof ValueNode) {
             final ValueNode<NormalizedNode> valuesNode = (ValueNode) normalizedNode;
             addYangLeaf(currentDataNode, valuesNode.getIdentifier().getNodeType().getLocalName(),
-                    valuesNode.body());
+                    (Serializable) valuesNode.body());
         } else if (normalizedNode instanceof LeafSetNode) {
             addYangLeafList(currentDataNode, (LeafSetNode<?>) normalizedNode);
         } else {
@@ -199,8 +203,9 @@ public class DataNodeBuilder {
         }
     }
 
-    private static void addYangLeaf(final DataNode currentDataNode, final String leafName, final Object leafValue) {
-        final Map<String, Object> leaves = new ImmutableMap.Builder<String, Object>()
+    private static void addYangLeaf(final DataNode currentDataNode, final String leafName,
+                                    final Serializable leafValue) {
+        final Map<String, Serializable> leaves = new ImmutableMap.Builder<String, Serializable>()
             .putAll(currentDataNode.getLeaves())
             .put(leafName, leafValue)
             .build();
@@ -213,7 +218,7 @@ public class DataNodeBuilder {
                 .stream()
                 .map(normalizedNode -> (normalizedNode).body())
                 .collect(Collectors.toUnmodifiableList());
-        addYangLeaf(currentDataNode, leafListName, leafListValues);
+        addYangLeaf(currentDataNode, leafListName, (Serializable) leafListValues);
     }
 
     private static void addDataNodeForEachListElement(final DataNode currentDataNode, final MapNode mapNode) {
@@ -236,4 +241,13 @@ public class DataNodeBuilder {
         return newChildDataNode;
     }
 
+    private static void addChoiceNode(final DataNode currentDataNode, final ChoiceNode choiceNode) {
+
+        final Collection<DataContainerChild> normalizedChildNodes = choiceNode.body();
+        for (final NormalizedNode normalizedNode : normalizedChildNodes) {
+            addDataNodeFromNormalizedNode(currentDataNode, normalizedNode);
+        }
+    }
+
+
 }
index fcfb482..e46147c 100644 (file)
@@ -32,7 +32,7 @@ import spock.lang.Specification
 
 class DataNodeBuilderSpec extends Specification {
 
-    Map<String, Map<String, Object>> expectedLeavesByXpathMap = [
+    Map<String, Map<String, Serializable>> expectedLeavesByXpathMap = [
             '/test-tree'                                            : [],
             '/test-tree/branch[@name=\'Left\']'                     : [name: 'Left'],
             '/test-tree/branch[@name=\'Left\']/nest'                : [name: 'Small', birds: ['Sparrow', 'Robin', 'Finch']],
@@ -140,6 +140,25 @@ class DataNodeBuilderSpec extends Specification {
             assert result.leaves['source-tp'] == '1-2-1'
     }
 
+    def 'Converting NormalizedNode (tree) to a DataNode (tree) -- with ChoiceNode.'() {
+        given: 'a schema context for expected model'
+            def yangResourceNameToContent = TestUtils.getYangResourcesAsMap('yang-with-choice-node.yang')
+            def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent) getSchemaContext()
+        and: 'the json data fragment parsed into normalized node object'
+            def jsonData = TestUtils.getResourceFileContent('data-with-choice-node.json')
+            def normalizedNode = YangUtils.parseJsonData(jsonData, schemaContext)
+        when: 'the normalized node is converted to a data node'
+            def result = new DataNodeBuilder().withNormalizedNodeTree(normalizedNode).build()
+            def mappedResult = TestUtils.getFlattenMapByXpath(result)
+        then: 'the resulting data node contains only one xpath with 3 leaves'
+            mappedResult.keySet().containsAll([
+                "/container-with-choice-leaves"
+            ])
+            assert result.leaves['leaf-1'] == "test"
+            assert result.leaves['choice-case1-leaf-a'] == "test"
+            assert result.leaves['choice-case1-leaf-b'] == "test"
+    }
+
     def 'Converting NormalizedNode into DataNode collection: #scenario.'() {
         given: 'a schema context for expected model'
             def yangResourceNameToContent = TestUtils.getYangResourcesAsMap('test-tree.yang')
diff --git a/cps-service/src/test/resources/data-with-choice-node.json b/cps-service/src/test/resources/data-with-choice-node.json
new file mode 100644 (file)
index 0000000..5f81ed8
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "container-with-choice-leaves": {
+    "leaf-1": "test",
+    "choice-case1-leaf-a": "test",
+    "choice-case1-leaf-b": "test"
+  }
+}
+
diff --git a/cps-service/src/test/resources/yang-with-choice-node.yang b/cps-service/src/test/resources/yang-with-choice-node.yang
new file mode 100644 (file)
index 0000000..55c0bfb
--- /dev/null
@@ -0,0 +1,27 @@
+module yang-with-choice-node {
+  yang-version 1.1;
+  namespace "org:onap:cps:test:yang-with-choice-node";
+  prefix "yang-with-choice-node";
+
+  container container-with-choice-leaves {
+    leaf leaf-1 {
+      type string;
+    }
+
+    choice choicenode {
+      case case-1 {
+        leaf choice-case1-leaf-a {
+          type string;
+        }
+        leaf choice-case1-leaf-b {
+          type string;
+        }
+      }
+      case case-2 {
+        leaf choice-case2-leaf-a {
+          type string;
+        }
+      }
+    }
+  }
+}