Add get cm handles by modules names - service layer 73/125473/6
authorniamhcore <niamh.core@est.tech>
Thu, 28 Oct 2021 12:39:24 +0000 (13:39 +0100)
committerniamhcore <niamh.core@est.tech>
Tue, 2 Nov 2021 15:05:39 +0000 (15:05 +0000)
Issue-ID: CPS-644
Signed-off-by: niamhcore <niamh.core@est.tech>
Change-Id: Ic2a57df02d533a0066382c12c35be8d524b6cdad

14 files changed:
cps-ncmp-rest/docs/openapi/components.yaml
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
cps-ncmp-rest/src/test/resources/cmhandle-search.json [new file with mode: 0644]
cps-ncmp-rest/src/test/resources/invalid-cmhandle-search.json [new file with mode: 0644]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.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/NetworkCmProxyDataServiceImplSpec.groovy
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java
cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy
cps-service/src/main/java/org/onap/cps/api/CpsAdminService.java
cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java
cps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java
cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAdminServiceImplSpec.groovy

index 1f55ce1..7c9e1e8 100644 (file)
@@ -83,13 +83,13 @@ components:
           type: string
           example: hasAllModules
         conditionParameters:
-          $ref: '#/components/schemas/ConditionParameters'
-    ConditionParameters:
+          $ref: '#/components/schemas/ModuleNamesAsJsonArray'
+    ModuleNamesAsJsonArray:
       type: array
       items:
         type: object
-        $ref: '#/components/schemas/ConditionParameter'
-    ConditionParameter:
+        $ref: '#/components/schemas/ModuleNameAsJsonObject'
+    ModuleNameAsJsonObject:
         properties:
           moduleName:
             type: string
index 14f33d1..ca661b8 100755 (executable)
@@ -24,13 +24,23 @@ package org.onap.cps.ncmp.rest.controller;
 
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
 import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
+import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
 import org.onap.cps.ncmp.rest.api.NetworkCmProxyApi;
+import org.onap.cps.ncmp.rest.model.CmHandleProperties;
+import org.onap.cps.ncmp.rest.model.CmHandleProperty;
 import org.onap.cps.ncmp.rest.model.CmHandles;
+import org.onap.cps.ncmp.rest.model.ConditionProperties;
 import org.onap.cps.ncmp.rest.model.Conditions;
+import org.onap.cps.ncmp.rest.model.ModuleNameAsJsonObject;
+import org.onap.cps.ncmp.rest.model.ModuleNamesAsJsonArray;
 import org.onap.cps.spi.FetchDescendantsOption;
 import org.onap.cps.spi.model.DataNode;
 import org.onap.cps.spi.model.ModuleReference;
@@ -40,6 +50,7 @@ import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+@Slf4j
 @RestController
 @RequestMapping("${rest.api.ncmp-base-path}")
 public class NetworkCmProxyController implements NetworkCmProxyApi {
@@ -197,7 +208,12 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
 
     @Override
     public ResponseEntity<CmHandles> executeCmHandleSearch(final Conditions conditions) {
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+        final List<ConditionProperties> conditionProperties =
+            conditions.getConditions().stream().collect(Collectors.toList());
+        final CmHandles cmHandles = new CmHandles();
+        final Collection<String> cmHandleIdentifiers = processConditions(conditionProperties);
+        cmHandleIdentifiers.forEach(cmHandle -> cmHandles.setCmHandles(toCmHandleProperties(cmHandle)));
+        return ResponseEntity.ok(cmHandles);
     }
 
     @Override
@@ -207,4 +223,38 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
         return new ResponseEntity<>(new Gson().toJson(moduleReferences), HttpStatus.OK);
     }
 
+    private Collection<String> processConditions(final List<ConditionProperties> conditionProperties) {
+        for (final ConditionProperties conditionProperty : conditionProperties) {
+            if (conditionProperty.getName().equals("hasAllModules")) {
+                return executeCmHandleSearchesForModuleNames(conditionProperty);
+            } else {
+                log.warn("Unrecognized condition name {}.", conditionProperty.getName());
+            }
+        }
+        log.warn("No valid conditions found {}.", conditionProperties);
+        return Collections.emptyList();
+    }
+
+    private Collection<String> executeCmHandleSearchesForModuleNames(final ConditionProperties conditionProperties) {
+        return networkCmProxyDataService
+            .executeCmHandleHasAllModulesSearch(getModuleNames(conditionProperties.getConditionParameters()));
+    }
+
+    private Collection<String> getModuleNames(final ModuleNamesAsJsonArray moduleNamesAsJsonArray) {
+        final Collection<String> moduleNames = new ArrayList<>(moduleNamesAsJsonArray.size());
+        for (final ModuleNameAsJsonObject moduleNameAsJsonObject : moduleNamesAsJsonArray) {
+            moduleNames.add(moduleNameAsJsonObject.getModuleName());
+        }
+        return moduleNames;
+    }
+
+    private CmHandleProperties toCmHandleProperties(final String cmHandleId) {
+        final CmHandleProperties cmHandleProperties = new CmHandleProperties();
+        final CmHandleProperty cmHandleProperty = new CmHandleProperty();
+        cmHandleProperty.setCmHandleId(cmHandleId);
+        cmHandleProperties.add(cmHandleProperty);
+        return cmHandleProperties;
+    }
+
+
 }
index 342f41b..a609cfa 100644 (file)
@@ -22,6 +22,7 @@
 
 package org.onap.cps.ncmp.rest.controller
 
+import org.onap.cps.TestUtils
 import org.onap.cps.spi.model.ModuleReference
 
 import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
@@ -252,5 +253,33 @@ class NetworkCmProxyControllerSpec extends Specification {
         and: 'response returns an OK http code'
             response.status == HttpStatus.OK.value()
     }
+
+    def 'Retrieve cm handles.'() {
+        given: 'an endpoint and json data'
+            def searchesEndpoint = "$ncmpBasePathV1/ch/searches"
+            String jsonData = TestUtils.getResourceFileContent('cmhandle-search.json')
+        and: 'the service method is invoked with module names and returns a cm handle id'
+            mockNetworkCmProxyDataService.executeCmHandleHasAllModulesSearch(['module1', 'module2']) >> ['some-cmhandle-id']
+        when: 'the searches api is invoked'
+            def response = mvc.perform(post(searchesEndpoint)
+                    .contentType(MediaType.APPLICATION_JSON)
+                    .content(jsonData)).andReturn().response
+        then: 'response status returns OK'
+            response.status == HttpStatus.OK.value()
+        and: 'the expected response content is returned'
+            response.contentAsString == '{"cmHandles":[{"cmHandleId":"some-cmhandle-id"}]}'
+    }
+
+    def 'Call execute cm handle searches with unrecognized condition name.'() {
+        given: 'an endpoint and json data'
+            def searchesEndpoint = "$ncmpBasePathV1/ch/searches"
+            String jsonData = TestUtils.getResourceFileContent('invalid-cmhandle-search.json')
+        when: 'the searches api is invoked'
+            def response = mvc.perform(post(searchesEndpoint)
+                    .contentType(MediaType.APPLICATION_JSON)
+                    .content(jsonData)).andReturn().response
+        then: 'an empty cm handle identifier is returned'
+            response.contentAsString == '{"cmHandles":null}'
+    }
 }
 
diff --git a/cps-ncmp-rest/src/test/resources/cmhandle-search.json b/cps-ncmp-rest/src/test/resources/cmhandle-search.json
new file mode 100644 (file)
index 0000000..e3c721b
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "conditions": [
+    {
+      "name": "hasAllModules",
+      "conditionParameters": [
+        {
+          "moduleName": "module1"
+        },
+        {
+          "moduleName": "module2"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/cps-ncmp-rest/src/test/resources/invalid-cmhandle-search.json b/cps-ncmp-rest/src/test/resources/invalid-cmhandle-search.json
new file mode 100644 (file)
index 0000000..838c948
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "conditions": [
+    {
+      "name": "does-not-exist"
+    }
+  ]
+}
\ No newline at end of file
index cb2f782..e480a46 100644 (file)
@@ -159,4 +159,13 @@ public interface NetworkCmProxyDataService {
      * @return a collection of modules names and revisions
      */
     Collection<ModuleReference> getYangResourcesModuleReferences(@NotNull String cmHandle);
+
+    /**
+     * Query cm handle identifiers for the given collection of module names.
+     *
+     * @param moduleNames module names.
+     * @return a collection of cm handle identifiers. The schema set for each cm handle must include all the
+     *         given module names
+     */
+    Collection<String> executeCmHandleHasAllModulesSearch(Collection<String> moduleNames);
 }
index 7020c74..94544f3 100755 (executable)
@@ -67,7 +67,7 @@ import org.springframework.util.StringUtils;
 @Service
 public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService {
 
-    private static final String NF_PROXY_DATASPACE_NAME = "NFP-Operational";
+    private static final String NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME = "NFP-Operational";
 
     private static final String NCMP_DATASPACE_NAME = "NCMP-Admin";
 
@@ -115,37 +115,44 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
     @Override
     public DataNode getDataNode(final String cmHandle, final String xpath,
         final FetchDescendantsOption fetchDescendantsOption) {
-        return cpsDataService.getDataNode(NF_PROXY_DATASPACE_NAME, cmHandle, xpath, fetchDescendantsOption);
+        return cpsDataService
+            .getDataNode(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle, xpath, fetchDescendantsOption);
     }
 
     @Override
     public Collection<DataNode> queryDataNodes(final String cmHandle, final String cpsPath,
         final FetchDescendantsOption fetchDescendantsOption) {
-        return cpsQueryService.queryDataNodes(NF_PROXY_DATASPACE_NAME, cmHandle, cpsPath, fetchDescendantsOption);
+        return cpsQueryService
+            .queryDataNodes(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle, cpsPath, fetchDescendantsOption);
     }
 
     @Override
     public void createDataNode(final String cmHandle, final String parentNodeXpath, final String jsonData) {
         if (!StringUtils.hasText(parentNodeXpath) || "/".equals(parentNodeXpath)) {
-            cpsDataService.saveData(NF_PROXY_DATASPACE_NAME, cmHandle, jsonData, NO_TIMESTAMP);
+            cpsDataService.saveData(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle, jsonData, NO_TIMESTAMP);
         } else {
-            cpsDataService.saveData(NF_PROXY_DATASPACE_NAME, cmHandle, parentNodeXpath, jsonData, NO_TIMESTAMP);
+            cpsDataService
+                .saveData(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle, parentNodeXpath, jsonData, NO_TIMESTAMP);
         }
     }
 
     @Override
     public void addListNodeElements(final String cmHandle, final String parentNodeXpath, final String jsonData) {
-        cpsDataService.saveListElements(NF_PROXY_DATASPACE_NAME, cmHandle, parentNodeXpath, jsonData, NO_TIMESTAMP);
+        cpsDataService.saveListElements(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle, parentNodeXpath, jsonData,
+            NO_TIMESTAMP);
     }
 
     @Override
     public void updateNodeLeaves(final String cmHandle, final String parentNodeXpath, final String jsonData) {
-        cpsDataService.updateNodeLeaves(NF_PROXY_DATASPACE_NAME, cmHandle, parentNodeXpath, jsonData, NO_TIMESTAMP);
+        cpsDataService
+            .updateNodeLeaves(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle, parentNodeXpath, jsonData,
+                NO_TIMESTAMP);
     }
 
     @Override
     public void replaceNodeTree(final String cmHandle, final String parentNodeXpath, final String jsonData) {
-        cpsDataService.replaceNodeTree(NF_PROXY_DATASPACE_NAME, cmHandle, parentNodeXpath, jsonData, NO_TIMESTAMP);
+        cpsDataService.replaceNodeTree(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle, parentNodeXpath, jsonData,
+            NO_TIMESTAMP);
     }
 
     @Override
@@ -226,7 +233,18 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
 
     @Override
     public Collection<ModuleReference> getYangResourcesModuleReferences(final String cmHandle) {
-        return cpsModuleService.getYangResourcesModuleReferences(NF_PROXY_DATASPACE_NAME, cmHandle);
+        return cpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle);
+    }
+
+    /**
+     * Retrieve cm handle identifiers for the given list of module names.
+     *
+     * @param moduleNames module names.
+     * @return a collection of anchor identifiers
+     */
+    @Override
+    public Collection<String> executeCmHandleHasAllModulesSearch(final Collection<String> moduleNames) {
+        return cpsAdminService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNames);
     }
 
     private DataNode fetchDataNodeFromDmiRegistryForCmHandle(final String cmHandle) {
@@ -379,7 +397,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
 
     private void fetchAndSyncModules(final PersistenceCmHandle persistenceCmHandle) {
         final Map<String, String> cmHandlePropertiesAsMap = getCmHandlePropertiesAsMap(
-                persistenceCmHandle.getAdditionalProperties());
+            persistenceCmHandle.getAdditionalProperties());
 
         final List<ModuleReference> moduleReferencesFromCmHandle =
             fetchModuleReferencesFromDmi(persistenceCmHandle, cmHandlePropertiesAsMap);
@@ -394,8 +412,9 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
             newYangResourcesModuleNameToContentMap = getNewYangResourcesFromDmi(persistenceCmHandle,
                 unknownModuleReferences, cmHandlePropertiesAsMap);
         }
-        cpsModuleService.createSchemaSetFromModules(NF_PROXY_DATASPACE_NAME, persistenceCmHandle.getId(),
-            newYangResourcesModuleNameToContentMap, existingModuleReferences);
+        cpsModuleService
+            .createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, persistenceCmHandle.getId(),
+                newYangResourcesModuleNameToContentMap, existingModuleReferences);
     }
 
     private void prepareModuleSubsets(final List<ModuleReference> moduleReferencesFromCmHandle,
@@ -403,7 +422,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
                                       final List<ModuleReference> unknownModuleReferences) {
 
         final Collection<ModuleReference> knownModuleReferencesInCps =
-            cpsModuleService.getYangResourceModuleReferences(NF_PROXY_DATASPACE_NAME);
+            cpsModuleService.getYangResourceModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME);
 
         for (final ModuleReference moduleReferenceFromDmiForCmHandle : moduleReferencesFromCmHandle) {
             if (knownModuleReferencesInCps.contains(moduleReferenceFromDmiForCmHandle)) {
@@ -427,7 +446,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
     }
 
     private void createAnchor(final PersistenceCmHandle persistenceCmHandle) {
-        cpsAdminService.createAnchor(NF_PROXY_DATASPACE_NAME, persistenceCmHandle.getId(), persistenceCmHandle.getId());
+        cpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, persistenceCmHandle.getId(),
+            persistenceCmHandle.getId());
     }
 
     private String getRequestBodyToFetchYangResourceFromDmi(final List<ModuleReference> unknownModuleReferences,
index ae252b8..88277d3 100644 (file)
@@ -450,6 +450,13 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             result == expectedRequestBody
     }
 
+    def 'Get cm handle identifiers for the given module names.'() {
+        when: 'execute a cm handle search for the given module names'
+            objectUnderTest.executeCmHandleHasAllModulesSearch(['some-module-name'])
+        then: 'get anchor identifiers is invoked  with the expected parameters'
+            1 * mockCpsAdminService.queryAnchorNames('NFP-Operational', ['some-module-name'])
+    }
+
     def getObjectUnderTestWithModelSyncDisabled() {
         def objectUnderTest = Spy(new NetworkCmProxyDataServiceImpl(mockDmiOperations, mockCpsModuleService,
                 mockCpsDataService, mockCpsQueryService, mockCpsAdminService, spyObjectMapper))
index 2b63169..cd3c30b 100755 (executable)
@@ -94,7 +94,7 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic
     }
 
     @Override
-    public Collection<Anchor> getAnchors(final String dataspaceName, final Collection<String> inputModuleNames) {
+    public Collection<Anchor> queryAnchors(final String dataspaceName, final Collection<String> inputModuleNames) {
         validateDataspaceAndModuleNames(dataspaceName, inputModuleNames);
         final Collection<AnchorEntity> anchorEntities =
             anchorRepository.getAnchorsByDataspaceNameAndModuleNames(dataspaceName, inputModuleNames);
index c376510..af199be 100644 (file)
@@ -144,9 +144,9 @@ class CpsAdminPersistenceServiceSpec extends CpsPersistenceSpecBase {
     }
 
     @Sql([CLEAR_DATA, SAMPLE_DATA_FOR_ANCHORS_WITH_MODULES])
-    def 'Get anchors that have #scenario.'() {
+    def 'Query anchors that have #scenario.'() {
         when: 'all anchor are retrieved for the given dataspace name and module names'
-            def anchors = objectUnderTest.getAnchors('DATASPACE-001', inputModuleNames)
+            def anchors = objectUnderTest.queryAnchors('DATASPACE-001', inputModuleNames)
         then: 'the expected anchors are returned'
             anchors.size() == expectedAnchors.size()
             anchors.containsAll(expectedAnchors)
@@ -159,9 +159,9 @@ class CpsAdminPersistenceServiceSpec extends CpsPersistenceSpecBase {
     }
 
     @Sql([CLEAR_DATA, SAMPLE_DATA_FOR_ANCHORS_WITH_MODULES])
-    def 'Get all anchors for an #scenario.'() {
-        when: 'attempt to get anchors'
-            objectUnderTest.getAnchors(dataspaceName, moduleNames)
+    def 'Query all anchors for an #scenario.'() {
+        when: 'attempt to query anchors'
+            objectUnderTest.queryAnchors(dataspaceName, moduleNames)
         then: 'the correct exception is thrown with the relevant details'
             def thrownException = thrown(expectedException)
             thrownException.details.contains(expectedMessageDetails)
index 5b2e104..1d08cde 100755 (executable)
@@ -77,4 +77,15 @@ public interface CpsAdminService {
      * @param anchorName    anchor name
      */
     void deleteAnchor(@NonNull String dataspaceName, @NonNull String anchorName);
+
+    /**
+     * Query anchor names for the given module names in the provided dataspace.
+     *
+     *
+     * @param dataspaceName dataspace name
+     * @param moduleNames a collection of module names
+     * @return a collection of anchor names in the given dataspace. The schema set for each anchor must include all the
+     *         given module names
+     */
+    Collection<String> queryAnchorNames(String dataspaceName, Collection<String> moduleNames);
 }
index 47da648..4640a0f 100755 (executable)
@@ -23,6 +23,7 @@
 package org.onap.cps.api.impl;
 
 import java.util.Collection;
+import java.util.stream.Collectors;
 import org.onap.cps.api.CpsAdminService;
 import org.onap.cps.spi.CpsAdminPersistenceService;
 import org.onap.cps.spi.model.Anchor;
@@ -59,4 +60,10 @@ public class CpsAdminServiceImpl implements CpsAdminService {
     public void deleteAnchor(final String dataspaceName, final String anchorName) {
         cpsAdminPersistenceService.deleteAnchor(dataspaceName, anchorName);
     }
+
+    @Override
+    public Collection<String> queryAnchorNames(final String dataspaceName, final Collection<String> moduleNames) {
+        final Collection<Anchor> anchors = cpsAdminPersistenceService.queryAnchors(dataspaceName, moduleNames);
+        return anchors.stream().map(anchor -> anchor.getName()).collect(Collectors.toList());
+    }
 }
index f29735f..104ac4f 100755 (executable)
@@ -59,13 +59,15 @@ public interface CpsAdminPersistenceService {
     Collection<Anchor> getAnchors(@NonNull String dataspaceName);
 
     /**
-     * Get anchors for the given dataspace name and collection of module names.
+     * Query anchor names for the given module names in the provided dataspace.
+     *
      *
      * @param dataspaceName dataspace name
      * @param moduleNames a collection of module names
-     * @return a collection of anchors
+     * @return a collection of anchor names in the given dataspace. The schema set for each anchor must include all the
+     *         given module names
      */
-    Collection<Anchor> getAnchors(String dataspaceName, Collection<String> moduleNames);
+    Collection<Anchor> queryAnchors(String dataspaceName, Collection<String> moduleNames);
 
     /**
      * Get an anchor in the given dataspace using the anchor name.
index be213c0..95afeb4 100755 (executable)
@@ -70,4 +70,12 @@ class CpsAdminServiceImplSpec extends Specification {
         then: 'associated persistence service method is invoked with same parameters'
              1 * mockCpsAdminPersistenceService.deleteAnchor('someDataspace','someAnchor')
     }
+
+    def 'Query all anchor identifiers for a dataspace and module names.'() {
+        given: 'the persistence service is invoked with the expected parameters and returns a list of anchors'
+            mockCpsAdminPersistenceService.queryAnchors('some-dataspace-name', ['some-module-name']) >> [new Anchor(name:'some-anchor-identifier')]
+        expect: 'get anchor identifiers returns the same anchor identifier returned by the persistence layer'
+            objectUnderTest.queryAnchorNames('some-dataspace-name', ['some-module-name']) == ['some-anchor-identifier']
+
+    }
 }