From: Joseph Keenan Date: Thu, 15 Dec 2022 09:54:52 +0000 (+0000) Subject: Merge "Query Optimization" X-Git-Tag: 3.2.1~43 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=96c8e88e3750a16fa66d3f16ea0c84c0daf0be8f;hp=aec2a44c3ad4e9206300fd3494dbd542437678b3;p=cps.git Merge "Query Optimization" --- diff --git a/cps-dependencies/pom.xml b/cps-dependencies/pom.xml index 5bdf793fc..fb0638ea3 100755 --- a/cps-dependencies/pom.xml +++ b/cps-dependencies/pom.xml @@ -207,6 +207,11 @@ hazelcast-spring 4.2.5 + + com.google.guava + guava + 31.1-jre + diff --git a/cps-ncmp-rest-stub/pom.xml b/cps-ncmp-rest-stub/pom.xml index 93c73fcb5..35784fb25 100644 --- a/cps-ncmp-rest-stub/pom.xml +++ b/cps-ncmp-rest-stub/pom.xml @@ -91,11 +91,6 @@ slf4j-simple 1.8.0-beta4 - - com.google.guava - guava - 20.0 - cglib cglib-nodep diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImpl.java index 1a54a824b..bda0a728b 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImpl.java @@ -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 NO_QUERY_TO_EXECUTE = null; @@ -72,7 +73,7 @@ public class CmHandleQueriesImpl implements CmHandleQueries { } Map cmHandleIdToNcmpServiceCmHandles = null; for (final Map.Entry publicPropertyQueryPair : propertyQueryPairs.entrySet()) { - final String cpsPath = "//" + propertyType.getYangContainerName() + "[@name=\"" + final String cpsPath = DESCENDANT_PATH + propertyType.getYangContainerName() + "[@name=\"" + publicPropertyQueryPair.getKey() + "\" and @value=\"" + publicPropertyQueryPair.getValue() + "\"]"; diff --git a/cps-parent/pom.xml b/cps-parent/pom.xml index d3fe0f357..b8408f802 100755 --- a/cps-parent/pom.xml +++ b/cps-parent/pom.xml @@ -39,7 +39,7 @@ org.onap.cps.Application 11 0.97 - 42.5.0 + 42.5.1 ${project.reporting.outputDirectory}/jacoco-aggregate diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java index b22f171f2..c725b4224 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java @@ -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 childDataNodes = getChildDataNodes(fragmentEntity, fetchDescendantsOption); - Map leaves = new HashMap<>(); + Map 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 leaves) { + final Map leaves) { final FragmentEntity fragmentEntity = getFragmentWithoutDescendantsByXpath(dataspaceName, anchorName, xpath); fragmentEntity.setAttributes(jsonObjectMapper.asJsonString(leaves)); fragmentRepository.save(fragmentEntity); diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java index 03f021e76..c9f9a78ef 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java @@ -337,12 +337,14 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ */ private String getNameForChecksum( final String checksum, final Collection yangResourceEntities) { - return - yangResourceEntities.stream() + final Optional 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; } /** diff --git a/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java b/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java index 8d4df20b8..28b18b3b5 100644 --- a/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java +++ b/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java @@ -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 leaves); + void updateDataLeaves(String dataspaceName, String anchorName, String xpath, Map leaves); /** * Replaces an existing data node's content including descendants. diff --git a/cps-service/src/main/java/org/onap/cps/spi/model/DataNode.java b/cps-service/src/main/java/org/onap/cps/spi/model/DataNode.java index 8170db3da..76f33bbc1 100644 --- a/cps-service/src/main/java/org/onap/cps/spi/model/DataNode.java +++ b/cps-service/src/main/java/org/onap/cps/spi/model/DataNode.java @@ -46,7 +46,7 @@ public class DataNode implements Serializable { private ModuleReference moduleReference; private String xpath; private String moduleNamePrefix; - private Map leaves = Collections.emptyMap(); + private Map leaves = Collections.emptyMap(); private Collection xpathsChildren; private Collection childDataNodes = Collections.emptySet(); } diff --git a/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java b/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java index eaa2d77f4..1d8bac0dd 100644 --- a/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java +++ b/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java @@ -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 leaves = Collections.emptyMap(); + private Map leaves = Collections.emptyMap(); private Collection childDataNodes = Collections.emptySet(); /** @@ -102,7 +104,7 @@ public class DataNodeBuilder { * @param leaves for the data node * @return DataNodeBuilder */ - public DataNodeBuilder withLeaves(final Map leaves) { + public DataNodeBuilder withLeaves(final Map 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 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 leaves = new ImmutableMap.Builder() + private static void addYangLeaf(final DataNode currentDataNode, final String leafName, + final Serializable leafValue) { + final Map leaves = new ImmutableMap.Builder() .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 normalizedChildNodes = choiceNode.body(); + for (final NormalizedNode normalizedNode : normalizedChildNodes) { + addDataNodeFromNormalizedNode(currentDataNode, normalizedNode); + } + } + + } diff --git a/cps-service/src/test/groovy/org/onap/cps/spi/model/DataNodeBuilderSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/spi/model/DataNodeBuilderSpec.groovy index fcfb4826d..e46147c04 100644 --- a/cps-service/src/test/groovy/org/onap/cps/spi/model/DataNodeBuilderSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/spi/model/DataNodeBuilderSpec.groovy @@ -32,7 +32,7 @@ import spock.lang.Specification class DataNodeBuilderSpec extends Specification { - Map> expectedLeavesByXpathMap = [ + Map> 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 index 000000000..5f81ed8ed --- /dev/null +++ b/cps-service/src/test/resources/data-with-choice-node.json @@ -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 index 000000000..55c0bfbe6 --- /dev/null +++ b/cps-service/src/test/resources/yang-with-choice-node.yang @@ -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; + } + } + } + } +}