Fix performance degradation bug 29/129629/13
authorkissand <andras.zoltan.kiss@est.tech>
Tue, 28 Jun 2022 15:08:33 +0000 (16:08 +0100)
committerkissand <andras.zoltan.kiss@est.tech>
Thu, 30 Jun 2022 06:58:32 +0000 (08:58 +0200)
- do NOT use cpsPath query for gettign individual CM Handles
- change order of queries for more efficency (property query first)

Issue-ID: CPS-1085
Change-Id: Ia3bdf4f0d245a2b128557352685d2aa17c1f939c
Signed-off-by: kissand <andras.zoltan.kiss@est.tech>
Signed-off-by: ToineSiebelink <toine.siebelink@est.tech>
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyCmHandlerQueryService.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceImpl.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
cps-service/src/main/java/org/onap/cps/spi/model/DataNodeIdentifier.java [deleted file]

index 92b1e82..faf58b9 100644 (file)
@@ -20,9 +20,9 @@
 
 package org.onap.cps.ncmp.api;
 
-import java.util.Collection;
+import java.util.Set;
+import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
 import org.onap.cps.spi.model.CmHandleQueryServiceParameters;
-import org.onap.cps.spi.model.DataNode;
 
 public interface NetworkCmProxyCmHandlerQueryService {
     /**
@@ -31,5 +31,13 @@ public interface NetworkCmProxyCmHandlerQueryService {
      * @param cmHandleQueryServiceParameters the cm handle query parameters
      * @return collection of cm handles
      */
-    Collection<DataNode> queryCmHandles(CmHandleQueryServiceParameters cmHandleQueryServiceParameters);
+    Set<NcmpServiceCmHandle> queryCmHandles(CmHandleQueryServiceParameters cmHandleQueryServiceParameters);
+
+    /**
+     * Query and return cm handles that match the given query parameters.
+     *
+     * @param cmHandleQueryServiceParameters the cm handle query parameters
+     * @return collection of cm handle ids
+     */
+    Set<String> queryCmHandleIds(CmHandleQueryServiceParameters cmHandleQueryServiceParameters);
 }
index 3deaa7d..d64dfb4 100644 (file)
@@ -22,6 +22,7 @@ package org.onap.cps.ncmp.api.impl;
 
 import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NCMP_DATASPACE_NAME;
 import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NCMP_DMI_REGISTRY_ANCHOR;
+import static org.onap.cps.ncmp.api.impl.utils.YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle;
 import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS;
 import static org.onap.cps.utils.CmHandleQueryRestParametersValidator.validateModuleNameConditionProperties;
 
@@ -29,20 +30,22 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService;
+import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
+import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
 import org.onap.cps.spi.CpsAdminPersistenceService;
 import org.onap.cps.spi.CpsDataPersistenceService;
 import org.onap.cps.spi.model.Anchor;
 import org.onap.cps.spi.model.CmHandleQueryServiceParameters;
 import org.onap.cps.spi.model.ConditionProperties;
 import org.onap.cps.spi.model.DataNode;
-import org.onap.cps.spi.model.DataNodeIdentifier;
-import org.onap.cps.utils.JsonObjectMapper;
 import org.springframework.stereotype.Service;
 
 @Service
@@ -52,9 +55,9 @@ public class NetworkCmProxyCmHandlerQueryServiceImpl implements NetworkCmProxyCm
 
     private static final String PROPERTY_QUERY_NAME = "hasAllProperties";
     private static final String MODULE_QUERY_NAME = "hasAllModules";
+    private static final Object NO_QUERY_EXECUTED = null;
     private final CpsDataPersistenceService cpsDataPersistenceService;
     private final CpsAdminPersistenceService cpsAdminPersistenceService;
-    private final JsonObjectMapper jsonObjectMapper;
 
     /**
      * Query and return cm handles that match the given query parameters.
@@ -63,86 +66,124 @@ public class NetworkCmProxyCmHandlerQueryServiceImpl implements NetworkCmProxyCm
      * @return collection of cm handles
      */
     @Override
-    public Collection<DataNode> queryCmHandles(final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
+    public Set<NcmpServiceCmHandle> queryCmHandles(
+        final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
 
         if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
             return getAllCmHandles();
         }
 
-        final Collection<DataNodeIdentifier> amalgamatedQueryResultIdentifiers = new ArrayList<>();
-        final Map<DataNodeIdentifier, DataNode> amalgamatedQueryResults = new HashMap<>();
+        final Map<String, NcmpServiceCmHandle> publicPropertyQueryResult
+            = executePublicPropertyQueries(cmHandleQueryServiceParameters);
 
-        final boolean firstQuery = moduleNameQuery(cmHandleQueryServiceParameters,
-                amalgamatedQueryResultIdentifiers, amalgamatedQueryResults);
+        final Map<String, NcmpServiceCmHandle> combinedQueryResult =
+            combineWithModuleNameQuery(cmHandleQueryServiceParameters, publicPropertyQueryResult);
 
-        publicPropertyQuery(cmHandleQueryServiceParameters, amalgamatedQueryResultIdentifiers,
-                amalgamatedQueryResults, firstQuery);
+        return combinedQueryResult == NO_QUERY_EXECUTED
+            ? Collections.emptySet() : new HashSet<NcmpServiceCmHandle>(combinedQueryResult.values());
+    }
 
-        final Collection<DataNode> filteredDataNodes = new ArrayList<>();
-        amalgamatedQueryResultIdentifiers.forEach(amalgamatedQueryResultIdentifier ->
-            filteredDataNodes.add(amalgamatedQueryResults.get(amalgamatedQueryResultIdentifier))
-        );
+    /**
+     * Query and return cm handles that match the given query parameters.
+     *
+     * @param cmHandleQueryServiceParameters the cm handle query parameters
+     * @return collection of cm handle ids
+     */
+    @Override
+    public Set<String> queryCmHandleIds(
+        final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
+
+        if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
+            return getAllCmHandleIds();
+        }
+
+        final Map<String, NcmpServiceCmHandle> publicPropertyQueryResult
+            = executePublicPropertyQueries(cmHandleQueryServiceParameters);
+
+        final Collection<String> moduleNamesForQuery =
+            getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
+        if (moduleNamesForQuery.isEmpty()) {
+            return publicPropertyQueryResult == NO_QUERY_EXECUTED
+                ? Collections.emptySet() : publicPropertyQueryResult.keySet();
+        }
+        final Set<String> moduleNameQueryResult = getNamesOfAnchorsWithGivenModules(moduleNamesForQuery);
+
+        if (publicPropertyQueryResult == NO_QUERY_EXECUTED) {
+            return moduleNameQueryResult;
+        }
 
-        return filteredDataNodes;
+        moduleNameQueryResult.retainAll(publicPropertyQueryResult.keySet());
+        return moduleNameQueryResult;
     }
 
-    private void publicPropertyQuery(final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
-                                     final Collection<DataNodeIdentifier> amalgamatedQueryResultIdentifiers,
-                                     final Map<DataNodeIdentifier, DataNode> amalgamatedQueryResults,
-                                     boolean firstQuery) {
-        for (final Map.Entry<String, String> entry :
-                getPublicPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters()).entrySet()) {
-            final String cmHandlePath = "//public-properties[@name='" + entry.getKey() + "' " + "and @value='"
-                    + entry.getValue() + "']" + "/ancestor::cm-handles";
-
-            final Collection<DataNode> dataNodes = getDataNodes(cmHandlePath);
-
-            if (firstQuery) {
-                firstQuery = false;
-                dataNodes.forEach(dataNode -> {
-                    final DataNodeIdentifier dataNodeIdentifier =
-                            jsonObjectMapper.convertToValueType(dataNode, DataNodeIdentifier.class);
-                    amalgamatedQueryResultIdentifiers.add(dataNodeIdentifier);
-                    amalgamatedQueryResults.put(dataNodeIdentifier, dataNode);
-                });
+    private Map<String, NcmpServiceCmHandle> executePublicPropertyQueries(
+        final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
+        final Map<String, String> publicPropertyQueryPairs =
+            getPublicPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
+        if (publicPropertyQueryPairs.isEmpty()) {
+            return null;
+        }
+        Map<String, NcmpServiceCmHandle> cmHandleIdToNcmpServiceCmHandles = null;
+        for (final Map.Entry<String, String> entry : publicPropertyQueryPairs.entrySet()) {
+            final String cmHandlePath = "//public-properties[@name='" + entry.getKey() + "' and @value='"
+                + entry.getValue() + "']/ancestor::cm-handles";
+
+            final Collection<DataNode> dataNodes = queryDataNodes(cmHandlePath);
+            if (cmHandleIdToNcmpServiceCmHandles == NO_QUERY_EXECUTED) {
+                cmHandleIdToNcmpServiceCmHandles = collectDataNodesToNcmpServiceCmHandles(dataNodes);
             } else {
-                final Collection<DataNodeIdentifier> singleConditionQueryDataNodeIdentifiers = new ArrayList<>();
-                dataNodes.forEach(dataNode -> {
-                    final DataNodeIdentifier dataNodeIdentifier =
-                            jsonObjectMapper.convertToValueType(dataNode, DataNodeIdentifier.class);
-                    singleConditionQueryDataNodeIdentifiers.add(dataNodeIdentifier);
-                    amalgamatedQueryResults.put(dataNodeIdentifier, dataNode);
-                });
-                amalgamatedQueryResultIdentifiers.retainAll(singleConditionQueryDataNodeIdentifiers);
+                final Collection<String> cmHandleIdsToRetain = dataNodes.parallelStream()
+                    .map(dataNode -> dataNode.getLeaves().get("id").toString()).collect(Collectors.toSet());
+                cmHandleIdToNcmpServiceCmHandles.keySet().retainAll(cmHandleIdsToRetain);
             }
-
-            if (amalgamatedQueryResultIdentifiers.isEmpty()) {
+            if (cmHandleIdToNcmpServiceCmHandles.isEmpty()) {
                 break;
             }
         }
+        return cmHandleIdToNcmpServiceCmHandles;
     }
 
-    private boolean moduleNameQuery(final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
-                                    final Collection<DataNodeIdentifier> amalgamatedQueryResultIdentifiers,
-                                    final Map<DataNodeIdentifier, DataNode> amalgamatedQueryResults) {
-        boolean firstQuery = true;
-        if (!getModuleNames(cmHandleQueryServiceParameters.getCmHandleQueryParameters()).isEmpty()) {
-            final Collection<String> anchorNames = cpsAdminPersistenceService.queryAnchors("NFP-Operational",
-                    getModuleNames(cmHandleQueryServiceParameters.getCmHandleQueryParameters()))
-                    .parallelStream().map(Anchor::getName).collect(Collectors.toList());
-
-            getAllCmHandles().forEach(dataNode -> {
-                if (anchorNames.contains(dataNode.getLeaves().get("id").toString())) {
-                    final DataNodeIdentifier dataNodeIdentifier =
-                            jsonObjectMapper.convertToValueType(dataNode, DataNodeIdentifier.class);
-                    amalgamatedQueryResultIdentifiers.add(dataNodeIdentifier);
-                    amalgamatedQueryResults.put(dataNodeIdentifier, dataNode);
+    private Map<String, NcmpServiceCmHandle> combineWithModuleNameQuery(
+        final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
+        final Map<String, NcmpServiceCmHandle> previousQueryResult) {
+        final Collection<String> moduleNamesForQuery =
+            getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
+        if (moduleNamesForQuery.isEmpty()) {
+            return previousQueryResult;
+        }
+        final Collection<String> cmHandleIdsByModuleName = getNamesOfAnchorsWithGivenModules(moduleNamesForQuery);
+        if (cmHandleIdsByModuleName.isEmpty()) {
+            return Collections.emptyMap();
+        }
+        final Map<String, NcmpServiceCmHandle> queryResult = new HashMap<>(cmHandleIdsByModuleName.size());
+        if (previousQueryResult == NO_QUERY_EXECUTED) {
+            //TODO Discuss performance/scaling of getting ALL cmHandles here
+            getAllCmHandles().forEach(ncmpServiceCmHandle -> {
+                if (cmHandleIdsByModuleName.contains(ncmpServiceCmHandle.getCmHandleId())) {
+                    queryResult.put(ncmpServiceCmHandle.getCmHandleId(), ncmpServiceCmHandle);
                 }
             });
-
-            firstQuery = false;
+            return queryResult;
         }
-        return firstQuery;
+        previousQueryResult.keySet().retainAll(cmHandleIdsByModuleName);
+        queryResult.putAll(previousQueryResult);
+        return queryResult;
+    }
+
+    private Set<String> getNamesOfAnchorsWithGivenModules(final Collection<String> moduleNamesForQuery) {
+        final Collection<Anchor> anchors =
+            cpsAdminPersistenceService.queryAnchors("NFP-Operational", moduleNamesForQuery);
+        return anchors.parallelStream().map(Anchor::getName).collect(Collectors.toSet());
+    }
+
+    private Map<String, NcmpServiceCmHandle> collectDataNodesToNcmpServiceCmHandles(
+        final Collection<DataNode> dataNodes) {
+        final Map<String, NcmpServiceCmHandle> cmHandleIdToNcmpServiceCmHandle = new HashMap<>();
+        dataNodes.forEach(dataNode -> {
+            final NcmpServiceCmHandle ncmpServiceCmHandle = createNcmpServiceCmHandle(dataNode);
+            cmHandleIdToNcmpServiceCmHandle.put(ncmpServiceCmHandle.getCmHandleId(), ncmpServiceCmHandle);
+        });
+        return cmHandleIdToNcmpServiceCmHandle;
     }
 
     private List<Map<String, String>> getConditions(final List<ConditionProperties> conditionProperties,
@@ -155,13 +196,13 @@ public class NetworkCmProxyCmHandlerQueryServiceImpl implements NetworkCmProxyCm
         return Collections.emptyList();
     }
 
-    private List<String> getModuleNames(final List<ConditionProperties> conditionProperties) {
+    private Collection<String> getModuleNamesForQuery(final List<ConditionProperties> conditionProperties) {
         final List<String> result = new ArrayList<>();
         getConditions(conditionProperties, MODULE_QUERY_NAME).parallelStream().forEach(
-                conditionProperty -> {
-                    validateModuleNameConditionProperties(conditionProperty);
-                    result.add(conditionProperty.get("moduleName"));
-                }
+            conditionProperty -> {
+                validateModuleNameConditionProperties(conditionProperty);
+                result.add(conditionProperty.get("moduleName"));
+            }
         );
         return result;
     }
@@ -172,12 +213,23 @@ public class NetworkCmProxyCmHandlerQueryServiceImpl implements NetworkCmProxyCm
         return result;
     }
 
-    private Collection<DataNode> getAllCmHandles() {
-        return getDataNodes("//public-properties/ancestor::cm-handles");
+    private Set<NcmpServiceCmHandle> getAllCmHandles() {
+        return queryDataNodes("/dmi-registry/cm-handles").stream()
+            .map(this::createNcmpServiceCmHandle).collect(Collectors.toSet());
+    }
+
+    private Set<String> getAllCmHandleIds() {
+        return cpsAdminPersistenceService.getAnchors("NFP-Operational")
+            .parallelStream().map(Anchor::getName).collect(Collectors.toSet());
+    }
+
+    private List<DataNode> queryDataNodes(final String cmHandlePath) {
+        return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
+            cmHandlePath, INCLUDE_ALL_DESCENDANTS);
     }
 
-    private List<DataNode> getDataNodes(final String cmHandlePath) {
-        return cpsDataPersistenceService.queryDataNodes(
-                NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cmHandlePath, INCLUDE_ALL_DESCENDANTS);
+    private NcmpServiceCmHandle createNcmpServiceCmHandle(final DataNode dataNode) {
+        return convertYangModelCmHandleToNcmpServiceCmHandle(YangDataConverter
+            .convertCmHandleToYangModel(dataNode, dataNode.getLeaves().get("id").toString()));
     }
 }
index bfc7407..e118bf1 100755 (executable)
@@ -41,7 +41,6 @@ import java.util.Set;
 import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.api.CpsAdminService;
 import org.onap.cps.api.CpsDataService;
 import org.onap.cps.api.CpsModuleService;
 import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService;
@@ -53,7 +52,6 @@ import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
 import org.onap.cps.ncmp.api.inventory.CmHandleState;
 import org.onap.cps.ncmp.api.inventory.CompositeState;
 import org.onap.cps.ncmp.api.inventory.InventoryPersistence;
-import org.onap.cps.ncmp.api.inventory.sync.ModuleSyncService;
 import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters;
 import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse;
 import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError;
@@ -84,14 +82,10 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
 
     private final CpsModuleService cpsModuleService;
 
-    private final CpsAdminService cpsAdminService;
-
     private final NetworkCmProxyDataServicePropertyHandler networkCmProxyDataServicePropertyHandler;
 
     private final InventoryPersistence inventoryPersistence;
 
-    private final ModuleSyncService moduleSyncService;
-
     private final NetworkCmProxyCmHandlerQueryService networkCmProxyCmHandlerQueryService;
 
     @Override
@@ -167,16 +161,12 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
      */
     @Override
     public Set<NcmpServiceCmHandle> executeCmHandleSearch(final CmHandleQueryApiParameters cmHandleQueryApiParameters) {
-
         final CmHandleQueryServiceParameters cmHandleQueryServiceParameters = jsonObjectMapper.convertToValueType(
                 cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class);
 
         validateCmHandleQueryParameters(cmHandleQueryServiceParameters);
 
-        return networkCmProxyCmHandlerQueryService.queryCmHandles(cmHandleQueryServiceParameters).stream()
-                .map(dataNode -> YangDataConverter
-                        .convertCmHandleToYangModel(dataNode, dataNode.getLeaves().get("id").toString()))
-                .map(YangDataConverter::convertYangModelCmHandleToNcmpServiceCmHandle).collect(Collectors.toSet());
+        return networkCmProxyCmHandlerQueryService.queryCmHandles(cmHandleQueryServiceParameters);
     }
 
     /**
@@ -187,8 +177,12 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
      */
     @Override
     public Set<String> executeCmHandleIdSearch(final CmHandleQueryApiParameters cmHandleQueryApiParameters) {
-        return executeCmHandleSearch(cmHandleQueryApiParameters).stream().map(NcmpServiceCmHandle::getCmHandleId)
-                .collect(Collectors.toSet());
+        final CmHandleQueryServiceParameters cmHandleQueryServiceParameters = jsonObjectMapper.convertToValueType(
+                cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class);
+
+        validateCmHandleQueryParameters(cmHandleQueryServiceParameters);
+
+        return networkCmProxyCmHandlerQueryService.queryCmHandleIds(cmHandleQueryServiceParameters);
     }
 
     /**
index 46c8662..6e60979 100644 (file)
@@ -20,7 +20,6 @@
 
 package org.onap.cps.ncmp.api.impl
 
-import com.fasterxml.jackson.databind.ObjectMapper
 import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService
 import org.onap.cps.spi.CpsAdminPersistenceService
 import org.onap.cps.spi.CpsDataPersistenceService
@@ -28,7 +27,6 @@ import org.onap.cps.spi.model.Anchor
 import org.onap.cps.spi.model.CmHandleQueryServiceParameters
 import org.onap.cps.spi.model.ConditionProperties
 import org.onap.cps.spi.model.DataNode
-import org.onap.cps.utils.JsonObjectMapper
 import spock.lang.Specification
 
 import java.util.stream.Collectors
@@ -39,8 +37,7 @@ class NetworkCmProxyCmHandlerQueryServiceSpec extends Specification {
     def cpsAdminPersistenceService = Mock(CpsAdminPersistenceService)
 
     NetworkCmProxyCmHandlerQueryService objectUnderTest = new NetworkCmProxyCmHandlerQueryServiceImpl(
-        cpsDataPersistenceService, cpsAdminPersistenceService, new JsonObjectMapper(new ObjectMapper())
-    )
+        cpsDataPersistenceService, cpsAdminPersistenceService)
 
     def 'Retrieve cm handles with public properties when #scenario.'() {
         given: 'a condition property'
@@ -51,16 +48,19 @@ class NetworkCmProxyCmHandlerQueryServiceSpec extends Specification {
             cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties])
         and: 'mock services'
             mockResponses()
-        when: 'the service is invoked'
-            def returnedCmHandles = objectUnderTest.queryCmHandles(cmHandleQueryParameters)
-        then: 'the correct expected cm handles are returned'
-            returnedCmHandles.stream().map(d -> d.leaves.get('id').toString()).collect(Collectors.toSet()) == expectedCmHandleIds as Set
+        when: 'a query is execute (with and without Data)'
+            def returnedCmHandlesJustIds = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters)
+            def returnedCmHandlesWithData = objectUnderTest.queryCmHandles(cmHandleQueryParameters)
+        then: 'the correct expected cm handles ids are returned'
+            returnedCmHandlesJustIds == expectedCmHandleIds as Set
+        and: 'the correct cm handle data objects are returned'
+            returnedCmHandlesWithData.stream().map(dataNode -> dataNode.cmHandleId).collect(Collectors.toSet()) == expectedCmHandleIds as Set
         where: 'the following data is used'
-            scenario                                       | publicProperties                                                                                  || expectedCmHandleIds
-            'single matching property'                     | [['Contact' : 'newemailforstore@bookstore.com']]                                                  || ['PNFDemo', 'PNFDemo2', 'PNFDemo4']
-            'public property dont match'                   | [['wont_match' : 'wont_match']]                                                                   || []
-            '2 properties, only one match (and)'           | [['Contact' : 'newemailforstore@bookstore.com'], ['Contact2': 'newemailforstore2@bookstore.com']] || ['PNFDemo4']
-            '2 properties, no match (and)'                 | [['Contact' : 'newemailforstore@bookstore.com'], ['Contact2': '']]                                || []
+            scenario                         | publicProperties                                                                                  || expectedCmHandleIds
+            'single property matches'        | [['Contact' : 'newemailforstore@bookstore.com']]                                                  || ['PNFDemo1', 'PNFDemo2', 'PNFDemo4']
+            'public property does not match' | [['wont_match' : 'wont_match']]                                                                   || []
+            '2 properties, only one match'   | [['Contact' : 'newemailforstore@bookstore.com'], ['Contact2': 'newemailforstore2@bookstore.com']] || ['PNFDemo4']
+            '2 properties, no matches'       | [['Contact' : 'newemailforstore@bookstore.com'], ['Contact2': '']]                                || []
     }
 
     def 'Retrieve cm handles with module names when #scenario.'() {
@@ -73,15 +73,17 @@ class NetworkCmProxyCmHandlerQueryServiceSpec extends Specification {
         and: 'mock services'
             mockResponses()
         when: 'the service is invoked'
-            def returnedCmHandles = objectUnderTest.queryCmHandles(cmHandleQueryParameters)
+            def returnedCmHandlesJustIds = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters)
+            def returnedCmHandlesWithData = objectUnderTest.queryCmHandles(cmHandleQueryParameters)
         then: 'the correct expected cm handles are returned'
-            returnedCmHandles.stream().map(d -> d.leaves.get('id').toString()).collect(Collectors.toSet()) == expectedCmHandleIds as Set
+            returnedCmHandlesJustIds == expectedCmHandleIds as Set
+            returnedCmHandlesWithData.stream().map(dataNode -> dataNode.cmHandleId).collect(Collectors.toSet()) == expectedCmHandleIds as Set
         where: 'the following data is used'
-            scenario                               | moduleNames                                                             || expectedCmHandleIds
-            'single matching module name'          | [['moduleName' : 'MODULE-NAME-001']]                                    || ['PNFDemo3', 'PNFDemo', 'PNFDemo2']
-            'module name dont match'               | [['moduleName' : 'MODULE-NAME-004']]                                    || []
-            '2 module names, only one match (and)' | [['moduleName' : 'MODULE-NAME-002'], ['moduleName': 'MODULE-NAME-003']] || ['PNFDemo4']
-            '2 module names, no match (and)'       | [['moduleName' : 'MODULE-NAME-002'], ['moduleName': 'MODULE-NAME-004']] || []
+            scenario                         | moduleNames                                                             || expectedCmHandleIds
+            'single matching module name'    | [['moduleName' : 'MODULE-NAME-001']]                                    || ['PNFDemo3', 'PNFDemo1', 'PNFDemo2']
+            'module name dont match'         | [['moduleName' : 'MODULE-NAME-004']]                                    || []
+            '2 module names, only one match' | [['moduleName' : 'MODULE-NAME-002'], ['moduleName': 'MODULE-NAME-003']] || ['PNFDemo4']
+            '2 module names, no matches'     | [['moduleName' : 'MODULE-NAME-002'], ['moduleName': 'MODULE-NAME-004']] || []
     }
 
     def 'Retrieve cm handles with combined queries when #scenario.'() {
@@ -97,12 +99,14 @@ class NetworkCmProxyCmHandlerQueryServiceSpec extends Specification {
         and: 'mock services'
             mockResponses()
         when: 'the service is invoked'
-            def returnedCmHandles = objectUnderTest.queryCmHandles(cmHandleQueryParameters)
+            def returnedCmHandlesJustIds = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters)
+            def returnedCmHandlesWithData = objectUnderTest.queryCmHandles(cmHandleQueryParameters)
         then: 'the correct expected cm handles are returned'
-            returnedCmHandles.stream().map(d -> d.leaves.get('id').toString()).collect(Collectors.toSet()) == expectedCmHandleIds as Set
+            returnedCmHandlesJustIds == expectedCmHandleIds as Set
+            returnedCmHandlesWithData.stream().map(d -> d.cmHandleId).collect(Collectors.toSet()) == expectedCmHandleIds as Set
         where: 'the following data is used'
             scenario                 | moduleNames                          | publicProperties                                   || expectedCmHandleIds
-            'particularly intersect' | [['moduleName' : 'MODULE-NAME-001']] | [['Contact' : 'newemailforstore@bookstore.com']]   || ['PNFDemo2', 'PNFDemo']
+            'particularly intersect' | [['moduleName' : 'MODULE-NAME-001']] | [['Contact' : 'newemailforstore@bookstore.com']]   || ['PNFDemo1', 'PNFDemo2']
             'empty intersect'        | [['moduleName' : 'MODULE-NAME-004']] | [['Contact' : 'newemailforstore@bookstore.com']]   || []
             'total intersect'        | [['moduleName' : 'MODULE-NAME-002']] | [['Contact2' : 'newemailforstore2@bookstore.com']] || ['PNFDemo4']
     }
@@ -112,38 +116,37 @@ class NetworkCmProxyCmHandlerQueryServiceSpec extends Specification {
             mockResponses()
         when: 'the service is invoked'
             def cmHandleQueryParameters = new CmHandleQueryServiceParameters()
-            def returnedCmHandles = objectUnderTest.queryCmHandles(cmHandleQueryParameters)
+            def returnedCmHandlesJustIds = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters)
+            def returnedCmHandlesWithData = objectUnderTest.queryCmHandles(cmHandleQueryParameters)
         then: 'the correct expected cm handles are returned'
-            returnedCmHandles.stream().map(d -> d.leaves.get('id').toString()).collect(Collectors.toSet()) == ['PNFDemo', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4'] as Set
+            returnedCmHandlesJustIds == ['PNFDemo1', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4'] as Set
+            returnedCmHandlesWithData.stream().map(d -> d.cmHandleId).collect(Collectors.toSet()) == ['PNFDemo1', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4'] as Set
     }
 
     void mockResponses() {
-        def pNFDemo = new DataNode(xpath: 'cmHandle/id[\'PNFDemo\']', leaves: ['id':'PNFDemo'])
-        def pNFDemo2 = new DataNode(xpath: 'cmHandle/id[\'PNFDemo2\']', leaves: ['id':'PNFDemo2'])
-        def pNFDemo3 = new DataNode(xpath: 'cmHandle/id[\'PNFDemo3\']', leaves: ['id':'PNFDemo3'])
-        def pNFDemo4 = new DataNode(xpath: 'cmHandle/id[\'PNFDemo4\']', leaves: ['id':'PNFDemo4'])
+        def pNFDemo1 = new DataNode(xpath: '/dmi-registry/cm-handles[@id=\'PNFDemo1\']', leaves: ['id':'PNFDemo1'])
+        def pNFDemo2 = new DataNode(xpath: '/dmi-registry/cm-handles[@id=\'PNFDemo2\']', leaves: ['id':'PNFDemo2'])
+        def pNFDemo3 = new DataNode(xpath: '/dmi-registry/cm-handles[@id=\'PNFDemo3\']', leaves: ['id':'PNFDemo3'])
+        def pNFDemo4 = new DataNode(xpath: '/dmi-registry/cm-handles[@id=\'PNFDemo4\']', leaves: ['id':'PNFDemo4'])
+
+        cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\'Contact\' and @value=\'newemailforstore@bookstore.com\']/ancestor::cm-handles', _) >> [pNFDemo1, pNFDemo2, pNFDemo4]
+        cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\'wont_match\' and @value=\'wont_match\']/ancestor::cm-handles', _) >> []
+        cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\'Contact2\' and @value=\'newemailforstore2@bookstore.com\']/ancestor::cm-handles', _) >> [pNFDemo4]
+        cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\'Contact2\' and @value=\'\']/ancestor::cm-handles', _) >> []
+        cpsDataPersistenceService.queryDataNodes(_, _, '/dmi-registry/cm-handles', _) >> [pNFDemo1, pNFDemo2, pNFDemo3, pNFDemo4]
 
-        cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\'Contact\' and @value=\'newemailforstore@bookstore.com\']/ancestor::cm-handles', _)
-                >> [pNFDemo, pNFDemo2, pNFDemo4]
-        cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\'wont_match\' and @value=\'wont_match\']/ancestor::cm-handles', _)
-                >> []
-        cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\'Contact2\' and @value=\'newemailforstore2@bookstore.com\']/ancestor::cm-handles', _)
-                >> [pNFDemo4]
-        cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\'Contact2\' and @value=\'\']/ancestor::cm-handles', _)
-                >> []
-        cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties/ancestor::cm-handles', _)
-                >> [pNFDemo, pNFDemo2, pNFDemo3, pNFDemo4]
-        cpsDataPersistenceService.queryDataNodes(_, _, '//cm-handles[@id=\'PNFDemo\']', _) >> [pNFDemo]
-        cpsDataPersistenceService.queryDataNodes(_, _, '//cm-handles[@id=\'PNFDemo2\']', _) >> [pNFDemo2]
-        cpsDataPersistenceService.queryDataNodes(_, _, '//cm-handles[@id=\'PNFDemo3\']', _) >> [pNFDemo3]
-        cpsDataPersistenceService.queryDataNodes(_, _, '//cm-handles[@id=\'PNFDemo4\']', _) >> [pNFDemo4]
+        cpsDataPersistenceService.getDataNode(_, _, '/dmi-registry/cm-handles[@id=\'PNFDemo1\']', _) >> pNFDemo1
+        cpsDataPersistenceService.getDataNode(_, _, '/dmi-registry/cm-handles[@id=\'PNFDemo2\']', _) >> pNFDemo2
+        cpsDataPersistenceService.getDataNode(_, _, '/dmi-registry/cm-handles[@id=\'PNFDemo3\']', _) >> pNFDemo3
+        cpsDataPersistenceService.getDataNode(_, _, '/dmi-registry/cm-handles[@id=\'PNFDemo4\']', _) >> pNFDemo4
 
-        cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-001']) >> [new Anchor(name: 'PNFDemo2'), new Anchor(name: 'PNFDemo3'), new Anchor(name: 'PNFDemo')]
+        cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-001']) >> [new Anchor(name: 'PNFDemo1'), new Anchor(name: 'PNFDemo2'), new Anchor(name: 'PNFDemo3')]
         cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-004']) >> []
         cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-003', 'MODULE-NAME-002']) >> [new Anchor(name: 'PNFDemo4')]
         cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-002', 'MODULE-NAME-003']) >> [new Anchor(name: 'PNFDemo4')]
         cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-004', 'MODULE-NAME-002']) >> []
         cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-002', 'MODULE-NAME-004']) >> []
         cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-002']) >> [new Anchor(name: 'PNFDemo2'), new Anchor(name: 'PNFDemo4')]
+        cpsAdminPersistenceService.getAnchors(_) >> [new Anchor(name: 'PNFDemo1'), new Anchor(name: 'PNFDemo2'), new Anchor(name: 'PNFDemo3'), new Anchor(name: 'PNFDemo4')]
     }
 }
index 5d6d0a5..c11d09d 100644 (file)
@@ -59,11 +59,9 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
     def mockCpsDataService = Mock(CpsDataService)
     def mockCpsModuleService = Mock(CpsModuleService)
     def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
-    def mockCpsAdminService = Mock(CpsAdminService)
     def mockDmiDataOperations = Mock(DmiDataOperations)
     def mockNetworkCmProxyDataServicePropertyHandler = Mock(NetworkCmProxyDataServicePropertyHandler)
     def mockInventoryPersistence = Mock(InventoryPersistence)
-    def mockModuleSyncService = Mock(ModuleSyncService)
     def stubbedNetworkCmProxyCmHandlerQueryService = Stub(NetworkCmProxyCmHandlerQueryService)
     def noTimestamp = null
     def objectUnderTest = getObjectUnderTest()
@@ -352,7 +350,6 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
 
     def getObjectUnderTest() {
         return Spy(new NetworkCmProxyDataServiceImpl(mockCpsDataService, spiedJsonObjectMapper, mockDmiDataOperations,
-            mockCpsModuleService, mockCpsAdminService, mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence,
-            mockModuleSyncService, stubbedNetworkCmProxyCmHandlerQueryService))
+            mockCpsModuleService, mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, stubbedNetworkCmProxyCmHandlerQueryService))
     }
 }
index 92183f9..48c28a8 100644 (file)
@@ -34,11 +34,11 @@ import org.onap.cps.ncmp.api.models.ConditionApiProperties
 import org.onap.cps.ncmp.api.models.DmiPluginRegistration
 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
 import org.onap.cps.spi.exceptions.DataValidationException
-import org.onap.cps.ncmp.api.inventory.sync.ModuleSyncService
 import org.onap.cps.spi.model.CmHandleQueryServiceParameters
-import org.onap.cps.spi.model.ConditionProperties
 import spock.lang.Shared
 
+import java.util.stream.Collectors
+
 import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL
 import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING
 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.CREATE
@@ -46,7 +46,6 @@ import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum
 
 import org.onap.cps.utils.JsonObjectMapper
 import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.api.CpsAdminService
 import org.onap.cps.api.CpsDataService
 import org.onap.cps.api.CpsModuleService
 import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations
@@ -60,12 +59,10 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
 
     def mockCpsDataService = Mock(CpsDataService)
     def mockCpsModuleService = Mock(CpsModuleService)
-    def mockCpsAdminService = Mock(CpsAdminService)
     def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
     def mockDmiDataOperations = Mock(DmiDataOperations)
     def nullNetworkCmProxyDataServicePropertyHandler = null
     def mockInventoryPersistence = Mock(InventoryPersistence)
-    def mockModuleSyncService = Mock(ModuleSyncService)
     def mockDmiPluginRegistration = Mock(DmiPluginRegistration)
     def mockCpsCmHandlerQueryService = Mock(NetworkCmProxyCmHandlerQueryService)
 
@@ -77,8 +74,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
     def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle-id')
 
     def objectUnderTest = new NetworkCmProxyDataServiceImpl(mockCpsDataService, spiedJsonObjectMapper, mockDmiDataOperations,
-        mockCpsModuleService, mockCpsAdminService, nullNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence,
-        mockModuleSyncService, mockCpsCmHandlerQueryService)
+        mockCpsModuleService, nullNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockCpsCmHandlerQueryService)
 
     def cmHandleXPath = "/dmi-registry/cm-handles[@id='testCmHandle']"
 
@@ -291,14 +287,10 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             conditionApiProperties.conditionName = 'hasAllModules'
             conditionApiProperties.conditionParameters = [[moduleName: 'module-name-1']]
             cmHandleQueryApiParameters.cmHandleQueryParameters = [conditionApiProperties]
-        and: 'valid CmHandleQueryParameters input'
-            def cmHandleQueryParameters = new CmHandleQueryServiceParameters()
-            def conditionProperties = new ConditionProperties()
-            conditionProperties.conditionName = 'hasAllModules'
-            conditionProperties.conditionParameters = [[moduleName: 'module-name-1']]
-            cmHandleQueryParameters.cmHandleQueryParameters = [conditionProperties]
         and: 'query cm handle method return with a data node list'
-            mockCpsCmHandlerQueryService.queryCmHandles(cmHandleQueryParameters) >> [new DataNode(leaves: [id: 'cm-handle-id-1'])]
+            mockCpsCmHandlerQueryService.queryCmHandleIds(
+                    spiedJsonObjectMapper.convertToValueType(cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class))
+                    >> ['cm-handle-id-1']
         when: 'execute cm handle search is called'
             def result = objectUnderTest.executeCmHandleIdSearch(cmHandleQueryApiParameters)
         then: 'result is the same collection as returned by the CPS Data Service'
@@ -307,8 +299,25 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
 
     def dataStores() {
         CompositeState.DataStores.builder()
-            .operationalDataStore(CompositeState.Operational.builder()
-                .syncState(SyncState.NONE_REQUESTED)
-                .lastSyncTime('some-timestamp').build()).build()
+                .operationalDataStore(CompositeState.Operational.builder()
+                        .syncState(SyncState.NONE_REQUESTED)
+                        .lastSyncTime('some-timestamp').build()).build()
+    }
+
+    def 'Execute cm handle search'() {
+        given: 'valid CmHandleQueryApiParameters input'
+            def cmHandleQueryApiParameters = new CmHandleQueryApiParameters()
+            def conditionApiProperties = new ConditionApiProperties()
+            conditionApiProperties.conditionName = 'hasAllModules'
+            conditionApiProperties.conditionParameters = [[moduleName: 'module-name-1']]
+            cmHandleQueryApiParameters.cmHandleQueryParameters = [conditionApiProperties]
+        and: 'query cm handle method return with a data node list'
+            mockCpsCmHandlerQueryService.queryCmHandles(
+                    spiedJsonObjectMapper.convertToValueType(cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class))
+                    >> [new NcmpServiceCmHandle(cmHandleId: 'cm-handle-id-1')]
+        when: 'execute cm handle search is called'
+            def result = objectUnderTest.executeCmHandleSearch(cmHandleQueryApiParameters)
+        then: 'result is the same collection as returned by the CPS Data Service'
+            assert result.stream().map(d -> d.cmHandleId).collect(Collectors.toSet()) == ['cm-handle-id-1'] as Set
     }
 }
diff --git a/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeIdentifier.java b/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeIdentifier.java
deleted file mode 100644 (file)
index 2bd2b77..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2022 Nordix Foundation.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.spi.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.Setter;
-
-@Setter
-@Getter
-@EqualsAndHashCode
-@JsonIgnoreProperties(ignoreUnknown = true)
-public class DataNodeIdentifier {
-    private String dataspace;
-    private String schemaSetName;
-    private String anchorName;
-    private String xpath;
-}