CPS-1553 :REST endpoint to accept collection of cm handles for GET operation 58/133858/21
authorsourabh_sourabh <sourabh.sourabh@est.tech>
Mon, 27 Mar 2023 13:36:20 +0000 (14:36 +0100)
committersourabh_sourabh <sourabh.sourabh@est.tech>
Thu, 27 Apr 2023 11:36:02 +0000 (12:36 +0100)
-Introduced an interface having all un-implemented or default defination
of any method that is further extended or implemented by abstract or
stubbed controller.
-Exposed an endpoint to accept bulk request
-Modified an existing methods for more readability. (Parameterized datasource for ... methods)
-Code impl. for getResourceDataFromDmi method to send bulk request to
new proposed dmi-plugin endpoint that would accept bulk request.
-We need to investigate a groovy test that fails only into onap CICD pipeline.
For now it's commented out by added TODO tag.  (org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy:205)

Issue-ID: CPS-1553

Signed-off-by: sourabh_sourabh <sourabh.sourabh@est.tech>
Change-Id: Ieac39690956e3a0eab41068db57c5d93a16d04f0
Signed-off-by: sourabh_sourabh <sourabh.sourabh@est.tech>
39 files changed:
cps-ncmp-rest-stub/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java
cps-ncmp-rest-stub/src/main/java/org/onap/cps/ncmp/rest/stub/handlers/NetworkCmProxyApiStubDefaultImpl.java [new file with mode: 0644]
cps-ncmp-rest/docs/openapi/components.yaml
cps-ncmp-rest/docs/openapi/ncmp.yml
cps-ncmp-rest/docs/openapi/openapi.yml
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpCachedResourceRequestHandler.java [new file with mode: 0644]
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreOperationalQueryHandler.java [deleted file]
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreOperationalResourceRequestHandler.java [deleted file]
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughOperationalResourceRequestHandler.java [deleted file]
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughRunningResourceRequestHandler.java [deleted file]
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandler.java
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactory.java
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpPassthroughResourceRequestHandler.java [new file with mode: 0644]
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/TaskManagementDefaultHandler.java [new file with mode: 0644]
cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandlerFactorySpec.groovy
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/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/avcsubscription/SubscriptionEventForwarder.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/executor/TaskExecutor.java [new file with mode: 0644]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DataStoreEnum.java [new file with mode: 0644]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationEnum.java [new file with mode: 0644]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java [new file with mode: 0644]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/SyncUtils.java
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy
dmi-plugin-stub/mappings/batchCmHandles.json

index 3990dd1..6d5ee8c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2022 Bell Canada
- *  Modifications Copyright (c) 2022 Nordix Foundation
+ *  Modifications Copyright (c) 2022-2023 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -31,14 +31,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.rest.api.NetworkCmProxyApi;
 import org.onap.cps.ncmp.rest.controller.handlers.DatastoreType;
 import org.onap.cps.ncmp.rest.model.CmHandleQueryParameters;
-import org.onap.cps.ncmp.rest.model.RestModuleDefinition;
-import org.onap.cps.ncmp.rest.model.RestModuleReference;
 import org.onap.cps.ncmp.rest.model.RestOutputCmHandle;
-import org.onap.cps.ncmp.rest.model.RestOutputCmHandleCompositeState;
-import org.onap.cps.ncmp.rest.model.RestOutputCmHandlePublicProperties;
+import org.onap.cps.ncmp.rest.stub.handlers.NetworkCmProxyApiStubDefaultImpl;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.core.io.ClassPathResource;
 import org.springframework.http.HttpStatus;
@@ -49,9 +45,7 @@ import org.springframework.web.bind.annotation.RestController;
 @Slf4j
 @RestController
 @RequestMapping("${rest.api.ncmp-stub-base-path}")
-public class NetworkCmProxyStubController implements NetworkCmProxyApi {
-
-    public static final String ASYNC_REQUEST_ID = "requestId";
+public class NetworkCmProxyStubController implements NetworkCmProxyApiStubDefaultImpl {
 
     @Value("${stub.path}")
     private String pathToResponseFiles;
@@ -86,23 +80,6 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
         return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
     }
 
-    @Override
-    public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String datastoreName,
-                                                                     final String resourceIdentifier,
-                                                                     final String cmHandleId,
-                                                                     final Object body,
-                                                                     final String contentType) {
-        return new ResponseEntity<>(HttpStatus.CREATED);
-    }
-
-    @Override
-    public ResponseEntity<Void> deleteResourceDataRunningForCmHandle(final String datastoreName,
-                                                                     final String cmHandleId,
-                                                                     final String resourceIdentifier,
-                                                                     final String contentType) {
-        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
-    }
-
     @Override
     public ResponseEntity<List<RestOutputCmHandle>> searchCmHandles(
             final CmHandleQueryParameters cmHandleQueryParameters) {
@@ -120,78 +97,12 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
         return ResponseEntity.ok(restOutputCmHandles);
     }
 
-    @Override
-    public ResponseEntity<Object> setDataSyncEnabledFlagForCmHandle(final String cmHandleId,
-                                                                    final Boolean dataSyncEnabled) {
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
-    @Override
-    public ResponseEntity<List<String>> searchCmHandleIds(
-            final CmHandleQueryParameters cmHandleQueryParameters) {
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
-    @Override
-    public ResponseEntity<RestOutputCmHandlePublicProperties> getCmHandlePublicPropertiesByCmHandleId(
-            final String cmHandleId) {
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
-    @Override
-    public ResponseEntity<RestOutputCmHandleCompositeState> getCmHandleStateByCmHandleId(final String cmHandle) {
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
-    @Override
-    public ResponseEntity<List<RestModuleDefinition>> getModuleDefinitionsByCmHandleId(final String cmHandle) {
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
-    @Override
-    public ResponseEntity<List<RestModuleReference>> getModuleReferencesByCmHandle(final String cmHandleId) {
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
-    @Override
-    public ResponseEntity<Object> patchResourceDataRunningForCmHandle(final String datastoreName,
-                                                                      final String resourceIdentifier,
-                                                                      final String cmHandleId,
-                                                                      final Object body,
-                                                                      final String contentType) {
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
-    @Override
-    public ResponseEntity<Object> queryResourceDataForCmHandle(final String datastoreName,
-                                                               final String cmHandle,
-                                                               final String cpsPath,
-                                                               final String options,
-                                                               final String topic,
-                                                               final Boolean includeDescendants) {
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
-    @Override
-    public ResponseEntity<RestOutputCmHandle> retrieveCmHandleDetailsById(final String cmHandleId) {
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
-    @Override
-    public ResponseEntity<Object> updateResourceDataRunningForCmHandle(final String datastoreName,
-                                                                       final String resourceIdentifier,
-                                                                       final String cmHandleId,
-                                                                       final Object body,
-                                                                       final String contentType) {
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
     private ResponseEntity<Map<String, Object>> populateAsyncResponse(final String topicParamInQuery) {
         final Map<String, Object> responseData;
-        if (topicParamInQuery != null) {
-            responseData = getAsyncResponseData();
-        } else {
+        if (topicParamInQuery == null) {
             responseData = null;
+        } else {
+            responseData = getAsyncResponseData();
         }
         return ResponseEntity.ok().body(responseData);
     }
diff --git a/cps-ncmp-rest-stub/src/main/java/org/onap/cps/ncmp/rest/stub/handlers/NetworkCmProxyApiStubDefaultImpl.java b/cps-ncmp-rest-stub/src/main/java/org/onap/cps/ncmp/rest/stub/handlers/NetworkCmProxyApiStubDefaultImpl.java
new file mode 100644 (file)
index 0000000..6e28dbc
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 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.ncmp.rest.stub.handlers;
+
+import java.util.List;
+import org.onap.cps.ncmp.rest.api.NetworkCmProxyApi;
+import org.onap.cps.ncmp.rest.model.CmHandleQueryParameters;
+import org.onap.cps.ncmp.rest.model.RestModuleDefinition;
+import org.onap.cps.ncmp.rest.model.RestModuleReference;
+import org.onap.cps.ncmp.rest.model.RestOutputCmHandle;
+import org.onap.cps.ncmp.rest.model.RestOutputCmHandleCompositeState;
+import org.onap.cps.ncmp.rest.model.RestOutputCmHandlePublicProperties;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+public interface NetworkCmProxyApiStubDefaultImpl extends NetworkCmProxyApi {
+
+    String ASYNC_REQUEST_ID = "requestId";
+
+    @Override
+    default ResponseEntity<Object> getResourceDataForCmHandle(final String datastoreName,
+                                                              final String cmHandle,
+                                                              final String resourceIdentifier,
+                                                              final String optionsParamInQuery,
+                                                              final String topicParamInQuery,
+                                                              final Boolean includeDescendants) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+    }
+
+    @Override
+    default ResponseEntity<Object> getResourceDataForCmHandleBatch(final String resourceIdentifier,
+                                                                   final String topicParamInQuery,
+                                                                   final String datastoreName,
+                                                                   final Object requestBody,
+                                                                   final String optionsParamInQuery,
+                                                                   final Boolean includeDescendants) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+    }
+
+    @Override
+    default ResponseEntity<List<RestOutputCmHandle>> searchCmHandles(
+            final CmHandleQueryParameters cmHandleQueryParameters) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+    }
+
+    @Override
+    default ResponseEntity<Void> createResourceDataRunningForCmHandle(final String datastoreName,
+                                                                      final String resourceIdentifier,
+                                                                      final String cmHandleId,
+                                                                      final Object requestBody,
+                                                                      final String contentType) {
+        return new ResponseEntity<>(HttpStatus.CREATED);
+    }
+
+    @Override
+    default ResponseEntity<Void> deleteResourceDataRunningForCmHandle(final String datastoreName,
+                                                                      final String cmHandleId,
+                                                                      final String resourceIdentifier,
+                                                                      final String contentType) {
+        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+    }
+
+    @Override
+    default ResponseEntity<Object> setDataSyncEnabledFlagForCmHandle(final String cmHandleId,
+                                                                     final Boolean dataSyncEnabled) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+    }
+
+    @Override
+    default ResponseEntity<List<String>> searchCmHandleIds(final CmHandleQueryParameters cmHandleQueryParameters) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+    }
+
+    @Override
+    default ResponseEntity<RestOutputCmHandlePublicProperties> getCmHandlePublicPropertiesByCmHandleId(
+            final String cmHandleId) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+    }
+
+    @Override
+    default ResponseEntity<RestOutputCmHandleCompositeState> getCmHandleStateByCmHandleId(final String cmHandle) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+    }
+
+    @Override
+    default ResponseEntity<List<RestModuleDefinition>> getModuleDefinitionsByCmHandleId(final String cmHandle) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+    }
+
+    @Override
+    default ResponseEntity<List<RestModuleReference>> getModuleReferencesByCmHandle(final String cmHandleId) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+    }
+
+    @Override
+    default ResponseEntity<Object> patchResourceDataRunningForCmHandle(final String datastoreName,
+                                                                       final String resourceIdentifier,
+                                                                       final String cmHandleId,
+                                                                       final Object requestBody,
+                                                                       final String contentType) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+    }
+
+    @Override
+    default ResponseEntity<Object> queryResourceDataForCmHandle(final String datastoreName,
+                                                                final String cmHandle,
+                                                                final String cpsPath,
+                                                                final String optionsParamInQuery,
+                                                                final String topicParamInQuery,
+                                                                final Boolean includeDescendants) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+    }
+
+    @Override
+    default ResponseEntity<RestOutputCmHandle> retrieveCmHandleDetailsById(final String cmHandleId) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+    }
+
+    @Override
+    default ResponseEntity<Object> updateResourceDataRunningForCmHandle(final String datastoreName,
+                                                                        final String resourceIdentifier,
+                                                                        final String cmHandleId,
+                                                                        final Object requestBody,
+                                                                        final String contentType) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+    }
+}
index 6ca63c7..7fc1063 100644 (file)
@@ -1,5 +1,5 @@
 #  ============LICENSE_START=======================================================
-#  Copyright (C) 2021-2022 Nordix Foundation
+#  Copyright (C) 2021-2023 Nordix Foundation
 #  Modifications Copyright (C) 2021 Pantheon.tech
 #  Modifications Copyright (C) 2022 Bell Canada
 #  ================================================================================
@@ -522,6 +522,18 @@ components:
         sample 1:
           value:
             topic: my-topic-name
+    requiredTopicParamInQuery:
+      name: topic
+      in: query
+      description: mandatory topic parameter in query.
+      required: true
+      schema:
+        type: string
+      allowReserved: true
+      examples:
+        sample 1:
+          value:
+            topic: my-topic-name
     contentParamInHeader:
       name: Content-Type
       in: header
index 1f7cce9..2b70d94 100755 (executable)
@@ -1,5 +1,5 @@
 #  ============LICENSE_START=======================================================
-#  Copyright (C) 2021-2022 Nordix Foundation
+#  Copyright (C) 2021-2023 Nordix Foundation
 #  Modifications Copyright (C) 2021 Pantheon.tech
 #  Modifications Copyright (C) 2021-2022 Bell Canada
 #  ================================================================================
@@ -194,6 +194,43 @@ resourceDataForCmHandle:
       502:
         $ref: 'components.yaml#/components/responses/BadGateway'
 
+getResourceDataForCmHandleBatch:
+  post:
+    tags:
+      - network-cm-proxy
+    summary: Get resource data for batch of cm handle ids
+    description: This request will be handled asynchronously using messaging to the supplied topic. The rest response will be an acknowledge with a requestId to identify the relevant messages.
+    operationId: getResourceDataForCmHandleBatch
+    parameters:
+      - $ref: 'components.yaml#/components/parameters/datastoreName'
+      - $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
+      - $ref: 'components.yaml#/components/parameters/optionsParamInQuery'
+      - $ref: 'components.yaml#/components/parameters/requiredTopicParamInQuery'
+      - $ref: 'components.yaml#/components/parameters/includeDescendantsOptionInQuery'
+    requestBody:
+      required: true
+      content:
+        application/json:
+          schema:
+            type: object
+    responses:
+      200:
+        description: OK
+        content:
+          application/json:
+            schema:
+              type: object
+      400:
+        $ref: 'components.yaml#/components/responses/BadRequest'
+      401:
+        $ref: 'components.yaml#/components/responses/Unauthorized'
+      403:
+        $ref: 'components.yaml#/components/responses/Forbidden'
+      500:
+        $ref: 'components.yaml#/components/responses/InternalServerError'
+      502:
+        $ref: 'components.yaml#/components/responses/BadGateway'
+
 queryResourceDataForCmHandle:
   get:
     tags:
index ee29366..5b4c0d3 100755 (executable)
@@ -1,5 +1,5 @@
 #  ============LICENSE_START=======================================================
-#  Copyright (C) 2021-2022 Nordix Foundation
+#  Copyright (C) 2021-2023 Nordix Foundation
 #  Modifications Copyright (C) 2021 Pantheon.tech
 #  Modifications Copyright (C) 2021 Bell Canada
 #  ================================================================================
@@ -34,6 +34,9 @@ paths:
   /v1/ch/{cm-handle}/data/ds/{datastore-name}:
     $ref: 'ncmp.yml#/resourceDataForCmHandle'
 
+  /v1/batch/data/ds/{datastore-name}:
+    $ref: 'ncmp.yml#/getResourceDataForCmHandleBatch'
+
   /v1/ch/{cm-handle}/data/ds/{datastore-name}/query:
     $ref: 'ncmp.yml#/queryResourceDataForCmHandle'
 
index 4da251f..a8bc3ae 100755 (executable)
 
 package org.onap.cps.ncmp.rest.controller;
 
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.CREATE;
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.DELETE;
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.PATCH;
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE;
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.CREATE;
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.DELETE;
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.PATCH;
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.UPDATE;
 
 import java.util.Collection;
 import java.util.List;
@@ -74,12 +74,12 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
     /**
      * Get resource data from datastore.
      *
-     * @param datastoreName       name of the datastore
-     * @param cmHandle            cm handle identifier
-     * @param resourceIdentifier  resource identifier
-     * @param optionsParamInQuery options query parameter
-     * @param topicParamInQuery   topic query parameter
-     * @param includeDescendants  whether include descendants
+     * @param datastoreName              name of the datastore
+     * @param cmHandle                   cm handle identifier
+     * @param resourceIdentifier         resource identifier
+     * @param optionsParamInQuery        options query parameter
+     * @param topicParamInQuery          topic query parameter
+     * @param includeDescendantsAsObject whether include descendants
      * @return {@code ResponseEntity} response from dmi plugin
      */
 
@@ -89,25 +89,48 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
                                                              final String resourceIdentifier,
                                                              final String optionsParamInQuery,
                                                              final String topicParamInQuery,
-                                                             final Boolean includeDescendants) {
+                                                             final Boolean includeDescendantsAsObject) {
 
         final NcmpDatastoreRequestHandler ncmpDatastoreRequestHandler =
-                ncmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceRequestHandler(
+                ncmpDatastoreResourceRequestHandlerFactory.getNcmpResourceRequestHandler(
                         DatastoreType.fromDatastoreName(datastoreName));
 
+        final boolean includeDescendants = toPrimitiveFlag(includeDescendantsAsObject);
+
         return ncmpDatastoreRequestHandler.executeRequest(cmHandle, resourceIdentifier,
                 optionsParamInQuery, topicParamInQuery, includeDescendants);
     }
 
+    @Override
+    public ResponseEntity<Object> getResourceDataForCmHandleBatch(final String resourceIdentifier,
+                                                                  final String topicParamInQuery,
+                                                                  final String datastoreName,
+                                                                  final Object requestBody,
+                                                                  final String optionsParamInQuery,
+                                                                  final Boolean includeDescendantsAsObject) {
+
+        final NcmpDatastoreRequestHandler ncmpDatastoreRequestHandler =
+                ncmpDatastoreResourceRequestHandlerFactory.getNcmpResourceRequestHandler(
+                        DatastoreType.fromDatastoreName(datastoreName));
+
+        final List<String> cmHandleIds = jsonObjectMapper.convertJsonString(jsonObjectMapper.asJsonString(requestBody),
+                List.class);
+
+        final boolean includeDescendants = toPrimitiveFlag(includeDescendantsAsObject);
+
+        return ncmpDatastoreRequestHandler.executeRequest(cmHandleIds, resourceIdentifier,
+                optionsParamInQuery, topicParamInQuery, includeDescendants);
+    }
+
     /**
      * Query resource data from datastore.
      *
-     * @param datastoreName       name of the datastore
-     * @param cmHandle            cm handle identifier
-     * @param cpsPath             CPS Path
-     * @param optionsParamInQuery options query parameter
-     * @param topicParamInQuery   topic query parameter
-     * @param includeDescendants  whether include descendants
+     * @param datastoreName              name of the datastore
+     * @param cmHandle                   cm handle identifier
+     * @param cpsPath                    CPS Path
+     * @param optionsParamInQuery        options query parameter
+     * @param topicParamInQuery          topic query parameter
+     * @param includeDescendantsAsObject whether include descendants
      * @return {@code ResponseEntity} response from dmi plugin
      */
 
@@ -117,13 +140,15 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
                                                                final String cpsPath,
                                                                final String optionsParamInQuery,
                                                                final String topicParamInQuery,
-                                                               final Boolean includeDescendants) {
+                                                               final Boolean includeDescendantsAsObject) {
         validateDataStore(DatastoreType.OPERATIONAL, datastoreName);
-        final NcmpDatastoreRequestHandler ncmpDatastoreRequestHandler =
-            ncmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceQueryHandler();
+        final NcmpDatastoreRequestHandler ncmpCachedResourceRequestHandler =
+            ncmpDatastoreResourceRequestHandlerFactory.getNcmpResourceRequestHandler(
+                    DatastoreType.fromDatastoreName(datastoreName));
 
-        return ncmpDatastoreRequestHandler.executeRequest(cmHandle, cpsPath, optionsParamInQuery,
-            topicParamInQuery, includeDescendants);
+        final boolean includeDescendants = toPrimitiveFlag(includeDescendantsAsObject);
+
+        return ncmpCachedResourceRequestHandler.executeRequest(cmHandle, cpsPath, includeDescendants);
     }
 
     /**
@@ -367,5 +392,12 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
             throw new InvalidDatastoreException(requestedDatastoreName + " is not supported");
         }
     }
+
+    private static boolean toPrimitiveFlag(final Boolean includeDescendantsAsObject) {
+        if (includeDescendantsAsObject == null) {
+            return false;
+        }
+        return includeDescendantsAsObject.booleanValue();
+    }
 }
 
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpCachedResourceRequestHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpCachedResourceRequestHandler.java
new file mode 100644 (file)
index 0000000..620f647
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2022-2023 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.ncmp.rest.controller.handlers;
+
+import java.util.function.Supplier;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import org.onap.cps.ncmp.api.NetworkCmProxyQueryService;
+import org.onap.cps.spi.FetchDescendantsOption;
+import org.springframework.stereotype.Component;
+
+@RequiredArgsConstructor
+@Component
+public class NcmpCachedResourceRequestHandler extends NcmpDatastoreRequestHandler {
+
+    @Setter
+    private String dataStoreName;
+    private final NetworkCmProxyQueryService networkCmProxyQueryService;
+
+    @Override
+    public Supplier<Object> getTaskSupplierForGetRequest(final String cmHandleId,
+                                                         final String resourceIdentifier,
+                                                         final String optionsParamInQuery,
+                                                         final String topicParamInQuery,
+                                                         final String requestId,
+                                                         final boolean includeDescendants) {
+
+        final FetchDescendantsOption fetchDescendantsOption =
+                TaskManagementDefaultHandler.getFetchDescendantsOption(includeDescendants);
+
+        return () -> networkCmProxyDataService.getResourceDataForCmHandle(dataStoreName, cmHandleId, resourceIdentifier,
+                fetchDescendantsOption);
+    }
+
+    /**
+     * Gets ncmp datastore query handler.
+     * Note. Currently only ncmp-datastore:operational supports query operations
+     * @return a ncmp datastore query handler.
+     */
+    @Override
+    public Supplier<Object> getTaskSupplierForQueryRequest(final String cmHandleId,
+                                                           final String resourceIdentifier,
+                                                           final boolean includeDescendants) {
+
+        final FetchDescendantsOption fetchDescendantsOption =
+                TaskManagementDefaultHandler.getFetchDescendantsOption(includeDescendants);
+
+        return () -> networkCmProxyQueryService.queryResourceDataOperational(cmHandleId, resourceIdentifier,
+                fetchDescendantsOption);
+    }
+
+}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreOperationalQueryHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreOperationalQueryHandler.java
deleted file mode 100644 (file)
index 0586d42..0000000
+++ /dev/null
@@ -1,56 +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.ncmp.rest.controller.handlers;
-
-import java.util.function.Supplier;
-import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.NetworkCmProxyQueryService;
-import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
-import org.onap.cps.spi.FetchDescendantsOption;
-
-@Slf4j
-public class NcmpDatastoreOperationalQueryHandler extends NcmpDatastoreRequestHandler {
-
-    private final NetworkCmProxyQueryService networkCmProxyQueryService;
-
-    public NcmpDatastoreOperationalQueryHandler(final NetworkCmProxyQueryService networkCmProxyQueryService,
-                                                final CpsNcmpTaskExecutor cpsNcmpTaskExecutor,
-                                                final int timeOutInMilliSeconds,
-                                                final boolean notificationFeatureEnabled) {
-        super(null, cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
-        this.networkCmProxyQueryService = networkCmProxyQueryService;
-    }
-
-    @Override
-    public Supplier<Object> getTaskSupplier(final String cmHandle,
-                                            final String resourceIdentifier,
-                                            final String optionsParamInQuery,
-                                            final String topicParamInQuery,
-                                            final String requestId,
-                                            final Boolean includeDescendant) {
-
-        final FetchDescendantsOption fetchDescendantsOption = getFetchDescendantsOption(includeDescendant);
-
-        return () -> networkCmProxyQueryService.queryResourceDataOperational(cmHandle, resourceIdentifier,
-            fetchDescendantsOption);
-    }
-
-}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreOperationalResourceRequestHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreOperationalResourceRequestHandler.java
deleted file mode 100644 (file)
index a4720b2..0000000
+++ /dev/null
@@ -1,53 +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.ncmp.rest.controller.handlers;
-
-import java.util.function.Supplier;
-import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
-import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
-import org.onap.cps.spi.FetchDescendantsOption;
-
-@Slf4j
-public class NcmpDatastoreOperationalResourceRequestHandler extends NcmpDatastoreRequestHandler {
-
-    public NcmpDatastoreOperationalResourceRequestHandler(final NetworkCmProxyDataService networkCmProxyDataService,
-                                                          final CpsNcmpTaskExecutor cpsNcmpTaskExecutor,
-                                                          final int timeOutInMilliSeconds,
-                                                          final boolean notificationFeatureEnabled) {
-        super(networkCmProxyDataService, cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
-    }
-
-    @Override
-    public Supplier<Object> getTaskSupplier(final String cmHandle,
-                                            final String resourceIdentifier,
-                                            final String optionsParamInQuery,
-                                            final String topicParamInQuery,
-                                            final String requestId,
-                                            final Boolean includeDescendant) {
-
-        final FetchDescendantsOption fetchDescendantsOption = getFetchDescendantsOption(includeDescendant);
-
-        return () -> networkCmProxyDataService.getResourceDataOperational(cmHandle, resourceIdentifier,
-                fetchDescendantsOption);
-    }
-
-}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughOperationalResourceRequestHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughOperationalResourceRequestHandler.java
deleted file mode 100644 (file)
index 1445e3e..0000000
+++ /dev/null
@@ -1,51 +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.ncmp.rest.controller.handlers;
-
-import java.util.function.Supplier;
-import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
-import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
-
-@Slf4j
-public class NcmpDatastorePassthroughOperationalResourceRequestHandler extends NcmpDatastoreRequestHandler {
-
-    public NcmpDatastorePassthroughOperationalResourceRequestHandler(
-            final NetworkCmProxyDataService networkCmProxyDataService,
-            final CpsNcmpTaskExecutor cpsNcmpTaskExecutor,
-            final int timeOutInMilliSeconds,
-            final boolean notificationFeatureEnabled) {
-        super(networkCmProxyDataService, cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
-    }
-
-    @Override
-    public Supplier<Object> getTaskSupplier(final String cmHandle,
-                                            final String resourceIdentifier,
-                                            final String optionsParamInQuery,
-                                            final String topicParamInQuery,
-                                            final String requestId,
-                                            final Boolean includeDescendant) {
-
-        return () -> networkCmProxyDataService.getResourceDataOperationalForCmHandle(
-                cmHandle, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId);
-    }
-
-}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughRunningResourceRequestHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughRunningResourceRequestHandler.java
deleted file mode 100644 (file)
index 8194ec9..0000000
+++ /dev/null
@@ -1,50 +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.ncmp.rest.controller.handlers;
-
-import java.util.function.Supplier;
-import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
-import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
-
-@Slf4j
-public class NcmpDatastorePassthroughRunningResourceRequestHandler extends NcmpDatastoreRequestHandler {
-
-    public NcmpDatastorePassthroughRunningResourceRequestHandler(
-            final NetworkCmProxyDataService networkCmProxyDataService,
-            final CpsNcmpTaskExecutor cpsNcmpTaskExecutor,
-            final int timeOutInMilliSeconds,
-            final boolean notificationFeatureEnabled) {
-        super(networkCmProxyDataService, cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
-    }
-
-    @Override
-    public Supplier<Object> getTaskSupplier(final String cmHandle,
-                                            final String resourceIdentifier,
-                                            final String optionsParamInQuery,
-                                            final String topicParamInQuery,
-                                            final String requestId,
-                                            final Boolean includeDescendant) {
-
-        return () -> networkCmProxyDataService.getResourceDataPassThroughRunningForCmHandle(
-                cmHandle, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId);
-    }
-}
index 8502003..050e724 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2022 Nordix Foundation
+ *  Copyright (C) 2022-2023 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 package org.onap.cps.ncmp.rest.controller.handlers;
 
+import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 import java.util.function.Supplier;
-import lombok.RequiredArgsConstructor;
+import lombok.NoArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
 import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
 import org.onap.cps.ncmp.rest.util.TopicValidator;
-import org.onap.cps.spi.FetchDescendantsOption;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
 
-@RequiredArgsConstructor
+@NoArgsConstructor
 @Slf4j
-public abstract class NcmpDatastoreRequestHandler {
+@Service
+public class NcmpDatastoreRequestHandler implements TaskManagementDefaultHandler {
 
-    private static final String NO_REQUEST_ID = null;
-    private static final String NO_TOPIC = null;
-
-    protected final NetworkCmProxyDataService networkCmProxyDataService;
-    protected final CpsNcmpTaskExecutor cpsNcmpTaskExecutor;
-    protected final int timeOutInMilliSeconds;
-    protected final boolean notificationFeatureEnabled;
-
-    protected abstract Supplier<Object> getTaskSupplier(final String cmHandle,
-                                                        final String resourceIdentifier,
-                                                        final String optionsParamInQuery,
-                                                        final String topicParamInQuery,
-                                                        final String requestId,
-                                                        final Boolean includeDescendant);
+    @Value("${notification.async.executor.time-out-value-in-ms:2000}")
+    protected int timeOutInMilliSeconds;
+    @Value("${notification.enabled:true}")
+    protected boolean notificationFeatureEnabled;
+    @Autowired
+    protected NetworkCmProxyDataService networkCmProxyDataService;
+    @Autowired
+    protected CpsNcmpTaskExecutor cpsNcmpTaskExecutor;
 
     /**
-     * Execute a request on a datastore.
+     * Executes synchronous/asynchronous request for given cm handle.
      *
      * @param cmHandleId          the cm handle
      * @param resourceIdentifier  the resource identifier
@@ -64,25 +63,62 @@ public abstract class NcmpDatastoreRequestHandler {
                                                  final String resourceIdentifier,
                                                  final String optionsParamInQuery,
                                                  final String topicParamInQuery,
-                                                 final Boolean includeDescendants) {
+                                                 final boolean includeDescendants) {
 
         final boolean asyncResponseRequested = topicParamInQuery != null;
         if (asyncResponseRequested && notificationFeatureEnabled) {
-            final String requestId = UUID.randomUUID().toString();
-            final Supplier<Object> taskSupplier = getTaskSupplier(cmHandleId, resourceIdentifier, optionsParamInQuery,
-                topicParamInQuery, requestId, includeDescendants);
-            return executeTaskAsync(topicParamInQuery, requestId, taskSupplier);
+            return executeAsyncTaskAndGetResponseEntity(cmHandleId, resourceIdentifier, optionsParamInQuery,
+                    topicParamInQuery, includeDescendants, false);
         }
 
         if (asyncResponseRequested) {
             log.warn("Asynchronous request is unavailable as notification feature is currently disabled, "
-                + "will use synchronous operation.");
+                    + "will use synchronous operation.");
         }
-        final Supplier<Object> taskSupplier = getTaskSupplier(cmHandleId, resourceIdentifier, optionsParamInQuery,
-            NO_TOPIC, NO_REQUEST_ID, includeDescendants);
+        final Supplier<Object> taskSupplier = getTaskSupplierForGetRequest(cmHandleId,
+                resourceIdentifier, optionsParamInQuery, NO_TOPIC, NO_REQUEST_ID, includeDescendants);
         return executeTaskSync(taskSupplier);
     }
 
+    /**
+     * Executes a synchronous request for given cm handle.
+     * Note. Currently only ncmp-datastore:operational supports query operations.
+     *
+     * @param cmHandleId         the cm handle
+     * @param resourceIdentifier the resource identifier
+     * @param includeDescendants whether include descendants
+     * @return the response entity
+     */
+    public ResponseEntity<Object> executeRequest(final String cmHandleId,
+                                                 final String resourceIdentifier,
+                                                 final boolean includeDescendants) {
+
+        final Supplier<Object> taskSupplier = getTaskSupplierForQueryRequest(cmHandleId, resourceIdentifier,
+                includeDescendants);
+        return executeTaskSync(taskSupplier);
+    }
+
+    /**
+     * Executes synchronous/asynchronous request for batch of cm handles.
+     *
+     * @param cmHandleIds         list of cm handles
+     * @param resourceIdentifier  the resource identifier
+     * @param optionsParamInQuery the options param in query
+     * @param topicParamInQuery   the topic param in query
+     * @param includeDescendants  whether include descendants
+     * @return the response entity
+     */
+    public ResponseEntity<Object> executeRequest(final List<String> cmHandleIds,
+                                                 final String resourceIdentifier,
+                                                 final String optionsParamInQuery,
+                                                 final String topicParamInQuery,
+                                                 final boolean includeDescendants) {
+
+        return executeAsyncTaskAndGetResponseEntity(cmHandleIds, resourceIdentifier, optionsParamInQuery,
+                topicParamInQuery, includeDescendants, true);
+
+    }
+
     protected ResponseEntity<Object> executeTaskAsync(final String topicParamInQuery,
                                                       final String requestId,
                                                       final Supplier<Object> taskSupplier) {
@@ -98,9 +134,25 @@ public abstract class NcmpDatastoreRequestHandler {
         return ResponseEntity.ok(taskSupplier.get());
     }
 
-    protected static FetchDescendantsOption getFetchDescendantsOption(final Boolean includeDescendant) {
-        return Boolean.TRUE.equals(includeDescendant) ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
-            : FetchDescendantsOption.OMIT_DESCENDANTS;
+    private ResponseEntity<Object> executeAsyncTaskAndGetResponseEntity(final Object targetObject,
+                                                                        final String resourceIdentifier,
+                                                                        final String optionsParamInQuery,
+                                                                        final String topicParamInQuery,
+                                                                        final boolean includeDescendants,
+                                                                        final boolean isBulkRequest) {
+        final String requestId = UUID.randomUUID().toString();
+        final Supplier<Object> taskSupplier;
+        if (isBulkRequest) {
+            taskSupplier = getTaskSupplierForBulkRequest((List<String>) targetObject,
+                    resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId, includeDescendants);
+        } else {
+            taskSupplier = getTaskSupplierForGetRequest(targetObject.toString(), resourceIdentifier,
+                    optionsParamInQuery, topicParamInQuery, requestId, includeDescendants);
+        }
+        if (taskSupplier == NO_OBJECT_SUPPLIER) {
+            return new ResponseEntity<>(Map.of("status", "Unable to execute request as "
+                    + "datastore is not implemented."), HttpStatus.NOT_IMPLEMENTED);
+        }
+        return executeTaskAsync(topicParamInQuery, requestId, taskSupplier);
     }
-
 }
index ff7bda6..9a71798 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2022 Nordix Foundation
+ *  Copyright (C) 2022-2023 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 package org.onap.cps.ncmp.rest.controller.handlers;
 
 import lombok.RequiredArgsConstructor;
-import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
-import org.onap.cps.ncmp.api.NetworkCmProxyQueryService;
-import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
 public class NcmpDatastoreResourceRequestHandlerFactory {
-
-    private final NetworkCmProxyDataService networkCmProxyDataService;
-    private final NetworkCmProxyQueryService networkCmProxyQueryService;
-    private final CpsNcmpTaskExecutor cpsNcmpTaskExecutor;
-
-    @Value("${notification.async.executor.time-out-value-in-ms:2000}")
-    private int timeOutInMilliSeconds;
-    @Value("${notification.enabled:true}")
-    private boolean notificationFeatureEnabled;
+    private final NcmpCachedResourceRequestHandler ncmpCachedResourceRequestHandler;
+    private final NcmpPassthroughResourceRequestHandler ncmpPassthroughResourceRequestHandler;
 
     /**
      * Gets ncmp datastore handler.
@@ -46,31 +35,17 @@ public class NcmpDatastoreResourceRequestHandlerFactory {
      * @param datastoreType the datastore type
      * @return the ncmp datastore handler
      */
-    public NcmpDatastoreRequestHandler getNcmpDatastoreResourceRequestHandler(
-            final DatastoreType datastoreType) {
+    public NcmpDatastoreRequestHandler getNcmpResourceRequestHandler(final DatastoreType datastoreType) {
 
         switch (datastoreType) {
             case OPERATIONAL:
-                return new NcmpDatastoreOperationalResourceRequestHandler(networkCmProxyDataService,
-                        cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
+                ncmpCachedResourceRequestHandler.setDataStoreName(datastoreType.getDatastoreName());
+                return ncmpCachedResourceRequestHandler;
             case PASSTHROUGH_RUNNING:
-                return new NcmpDatastorePassthroughRunningResourceRequestHandler(networkCmProxyDataService,
-                        cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
             case PASSTHROUGH_OPERATIONAL:
             default:
-                return new NcmpDatastorePassthroughOperationalResourceRequestHandler(networkCmProxyDataService,
-                        cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
+                ncmpPassthroughResourceRequestHandler.setDataStoreName(datastoreType.getDatastoreName());
+                return ncmpPassthroughResourceRequestHandler;
         }
     }
-
-    /**
-     * Gets ncmp datastore query handler.
-     * Note. Currently only ncmp-datastore:operational supports query operations
-     * @return a ncmp datastore query handler.
-     */
-    public NcmpDatastoreRequestHandler getNcmpDatastoreResourceQueryHandler() {
-        return new NcmpDatastoreOperationalQueryHandler(networkCmProxyQueryService, cpsNcmpTaskExecutor,
-            timeOutInMilliSeconds, notificationFeatureEnabled);
-    }
-
 }
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpPassthroughResourceRequestHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpPassthroughResourceRequestHandler.java
new file mode 100644 (file)
index 0000000..ab5d587
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2022-2023 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.ncmp.rest.controller.handlers;
+
+import java.util.List;
+import java.util.function.Supplier;
+import lombok.Setter;
+import org.springframework.stereotype.Component;
+
+@Component
+public class NcmpPassthroughResourceRequestHandler extends NcmpDatastoreRequestHandler {
+
+    @Setter
+    private String dataStoreName;
+
+    @Override
+    public Supplier<Object> getTaskSupplierForGetRequest(final String cmHandleId,
+                                                         final String resourceIdentifier,
+                                                         final String optionsParamInQuery,
+                                                         final String topicParamInQuery,
+                                                         final String requestId,
+                                                         final boolean includeDescendants) {
+
+        return () -> networkCmProxyDataService.getResourceDataForCmHandle(
+                dataStoreName, cmHandleId, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId);
+    }
+
+    @Override
+    public Supplier<Object> getTaskSupplierForBulkRequest(final List<String> cmHandleIds,
+                                                         final String resourceIdentifier,
+                                                         final String optionsParamInQuery,
+                                                         final String topicParamInQuery,
+                                                         final String requestId,
+                                                         final boolean includeDescendants) {
+
+        return () -> networkCmProxyDataService.getResourceDataForCmHandleBatch(
+                dataStoreName, cmHandleIds, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId);
+    }
+
+}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/TaskManagementDefaultHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/TaskManagementDefaultHandler.java
new file mode 100644 (file)
index 0000000..08e8407
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 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.ncmp.rest.controller.handlers;
+
+import java.util.List;
+import java.util.function.Supplier;
+import org.onap.cps.spi.FetchDescendantsOption;
+
+public interface TaskManagementDefaultHandler {
+
+    String NO_REQUEST_ID = null;
+    String NO_TOPIC = null;
+    Supplier<Object> NO_OBJECT_SUPPLIER = null;
+
+    default Supplier<Object> getTaskSupplierForGetRequest(final String cmHandleId,
+                                                          final String resourceIdentifier,
+                                                          final String optionsParamInQuery,
+                                                          final String topicParamInQuery,
+                                                          final String requestId,
+                                                          final boolean includeDescendant) {
+        return NO_OBJECT_SUPPLIER;
+
+    }
+
+    default Supplier<Object> getTaskSupplierForQueryRequest(final String cmHandleId,
+                                                            final String resourceIdentifier,
+                                                            final boolean includeDescendant) {
+        return NO_OBJECT_SUPPLIER;
+
+    }
+
+    default Supplier<Object> getTaskSupplierForBulkRequest(final List<String> cmHandleIds,
+                                                           final String resourceIdentifier,
+                                                           final String optionsParamInQuery,
+                                                           final String topicParamInQuery,
+                                                           final String requestId,
+                                                           final boolean includeDescendant) {
+        return NO_OBJECT_SUPPLIER;
+    }
+
+    static FetchDescendantsOption getFetchDescendantsOption(final boolean includeDescendants) {
+        return includeDescendants ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
+                : FetchDescendantsOption.OMIT_DESCENDANTS;
+    }
+}
index d67804e..9531101 100644 (file)
@@ -2,7 +2,7 @@
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2021 highstreet technologies GmbH
- *  Modifications Copyright (C) 2021-2022 Nordix Foundation
+ *  Modifications Copyright (C) 2021-2023 Nordix Foundation
  *  Modifications Copyright (C) 2021-2022 Bell Canada.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -33,18 +33,13 @@ import org.onap.cps.ncmp.api.inventory.CompositeState
 import org.onap.cps.ncmp.api.inventory.DataStoreSyncState
 import org.onap.cps.ncmp.api.inventory.LockReasonCategory
 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
-import org.onap.cps.ncmp.rest.controller.handlers.DatastoreType
-import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreOperationalQueryHandler
-import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreOperationalResourceRequestHandler
-import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastorePassthroughOperationalResourceRequestHandler
-import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastorePassthroughRunningResourceRequestHandler
+import org.onap.cps.ncmp.rest.controller.handlers.NcmpCachedResourceRequestHandler
+import org.onap.cps.ncmp.rest.controller.handlers.NcmpPassthroughResourceRequestHandler
 import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreResourceRequestHandlerFactory
-import org.onap.cps.ncmp.rest.exceptions.InvalidDatastoreException
 import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor
 import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper
 import org.onap.cps.ncmp.rest.util.DeprecationHelper
 import org.onap.cps.spi.FetchDescendantsOption
-import org.onap.cps.spi.exceptions.DataValidationException
 import org.onap.cps.spi.model.ModuleDefinition
 import org.onap.cps.spi.model.ModuleReference
 import org.onap.cps.utils.JsonObjectMapper
@@ -55,31 +50,32 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
 import org.springframework.http.HttpStatus
 import org.springframework.http.MediaType
 import org.springframework.test.web.servlet.MockMvc
-import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder
 import spock.lang.Shared
 import spock.lang.Specification
-
 import java.time.OffsetDateTime
 import java.time.ZoneOffset
 import java.time.format.DateTimeFormatter
 
 import static org.onap.cps.ncmp.api.inventory.CompositeState.DataStores
 import static org.onap.cps.ncmp.api.inventory.CompositeState.Operational
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.CREATE
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.PATCH
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.DELETE
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.CREATE
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.UPDATE
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.PATCH
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.DELETE
+import static org.onap.cps.ncmp.rest.controller.handlers.DatastoreType.PASSTHROUGH_OPERATIONAL
+import static org.onap.cps.ncmp.rest.controller.handlers.DatastoreType.PASSTHROUGH_RUNNING
+import static org.onap.cps.ncmp.rest.controller.handlers.DatastoreType.OPERATIONAL
 
 @WebMvcTest(NetworkCmProxyController)
 class NetworkCmProxyControllerSpec extends Specification {
 
-    public static final int TIMEOUT_IN_MS = 2000
-    public static final boolean NOTIFICATION_ENABLED = true
+    private static final int TIMEOUT_IN_MS = 2000
+    private static final boolean NOTIFICATION_ENABLED = true
 
     @Autowired
     MockMvc mvc
@@ -115,6 +111,7 @@ class NetworkCmProxyControllerSpec extends Specification {
     def ncmpBasePathV1
 
     def requestBody = '{"some-key":"some-value"}'
+    def bulkRequestBody = '["testCmHandle"]'
 
     @Shared
     def NO_TOPIC = null
@@ -124,24 +121,15 @@ class NetworkCmProxyControllerSpec extends Specification {
         .format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC))
 
     void setup() {
-        stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceRequestHandler(
-            DatastoreType.OPERATIONAL) >>
-            new NcmpDatastoreOperationalResourceRequestHandler(
-                mockNetworkCmProxyDataService, spiedCpsTaskExecutor, TIMEOUT_IN_MS, NOTIFICATION_ENABLED)
+        stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpResourceRequestHandler(
+            OPERATIONAL) >> getNcmpDatastoreRequestHandler(OPERATIONAL,new NcmpCachedResourceRequestHandler(mockNetworkCmProxyQueryService))
 
-        stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceRequestHandler(
-            DatastoreType.PASSTHROUGH_OPERATIONAL) >>
-            new NcmpDatastorePassthroughOperationalResourceRequestHandler(
-                mockNetworkCmProxyDataService, spiedCpsTaskExecutor, TIMEOUT_IN_MS, NOTIFICATION_ENABLED)
+        stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpResourceRequestHandler(
+            PASSTHROUGH_OPERATIONAL) >> getNcmpDatastoreRequestHandler(PASSTHROUGH_OPERATIONAL,new NcmpPassthroughResourceRequestHandler())
 
-        stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceRequestHandler(
-            DatastoreType.PASSTHROUGH_RUNNING) >>
-            new NcmpDatastorePassthroughRunningResourceRequestHandler(
-                mockNetworkCmProxyDataService, spiedCpsTaskExecutor, TIMEOUT_IN_MS, NOTIFICATION_ENABLED)
+        stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpResourceRequestHandler(
+            PASSTHROUGH_RUNNING) >> getNcmpDatastoreRequestHandler(PASSTHROUGH_RUNNING,new NcmpPassthroughResourceRequestHandler())
 
-        stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceQueryHandler() >>
-            new NcmpDatastoreOperationalQueryHandler(mockNetworkCmProxyQueryService, spiedCpsTaskExecutor,
-                TIMEOUT_IN_MS, NOTIFICATION_ENABLED);
     }
 
     def 'Get Resource Data from pass-through operational.'() {
@@ -154,11 +142,8 @@ class NetworkCmProxyControllerSpec extends Specification {
                     .contentType(MediaType.APPLICATION_JSON)
             ).andReturn().response
         then: 'the NCMP data service is called with getResourceDataOperationalForCmHandle'
-            1 * mockNetworkCmProxyDataService.getResourceDataOperationalForCmHandle('testCmHandle',
-                'parent/child',
-                '(a=1,b=2)',
-                NO_TOPIC,
-                NO_REQUEST_ID)
+            1 * mockNetworkCmProxyDataService.getResourceDataForCmHandle(PASSTHROUGH_OPERATIONAL.datastoreName, 'testCmHandle',
+                'parent/child','(a=1,b=2)', NO_TOPIC, NO_REQUEST_ID)
         and: 'response status is Ok'
             response.status == HttpStatus.OK.value()
     }
@@ -205,6 +190,48 @@ class NetworkCmProxyControllerSpec extends Specification {
             'invalid non-empty topic value in url' | 'passthrough-running'     | '&topic=1_5_*_#'
     }
 
+    def 'Get bulk resource data for #datastoreName from dmi service.'() {
+        given: 'bulk resource data url'
+            def getUrl = "$ncmpBasePathV1/batch/data/ds/${datastoreName}" +
+                    "?resourceIdentifier=parent/child&options=(a=1,b=2)&topic=myTopic"
+        when: 'post data resource request is performed'
+            def response = mvc.perform(
+                    post(getUrl)
+                            .contentType(MediaType.APPLICATION_JSON)
+                            .content(bulkRequestBody)
+            ).andReturn().response
+        then: 'response status is Ok'
+            response.status == HttpStatus.OK.value()
+            // TODO Need to be un-commented as it's failing into onap CICD pipeline
+            //  but passed into nordix and local build.
+            //and: 'the NCMP data service is called with getResourceDataForCmHandleBatch'
+            // 1 * mockNetworkCmProxyDataService.getResourceDataForCmHandleBatch(datastoreName, ['testCmHandle'],
+            //        'parent/child',
+            //       '(a=1,b=2)',
+            //      'myTopic',
+            //     _)
+        and: 'async request id is generated'
+            assert response.contentAsString.contains("requestId")
+        where: 'the following data stores are used'
+            datastoreName << [PASSTHROUGH_RUNNING.datastoreName, PASSTHROUGH_OPERATIONAL.datastoreName]
+    }
+
+    def 'Get bulk resource data for non-supported #datastoreName from dmi service.'() {
+        given: 'bulk resource data url'
+            def getUrl = "$ncmpBasePathV1/batch/data/ds/ncmp-datastore:operational" +
+                    "?resourceIdentifier=parent/child&options=(a=1,b=2)&topic=myTopic"
+        when: 'post data resource request is performed'
+            def response = mvc.perform(
+                    post(getUrl)
+                            .contentType(MediaType.APPLICATION_JSON)
+                            .content(bulkRequestBody)
+            ).andReturn().response
+        then: 'response status code is 501 not implemented'
+            response.status == HttpStatus.NOT_IMPLEMENTED.value()
+        where: 'the following data store is un-supported'
+            datastoreName << [OPERATIONAL.datastoreName]
+    }
+
     def 'Query Resource Data from operational.'() {
         given: 'the query resource data url'
             def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:operational/query" +
@@ -244,11 +271,8 @@ class NetworkCmProxyControllerSpec extends Specification {
             def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
                 "?resourceIdentifier=" + resourceIdentifier + "&options=(a=1,b=2)"
         and: 'ncmp service returns json object'
-            mockNetworkCmProxyDataService.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
-                resourceIdentifier,
-                '(a=1,b=2)',
-                NO_TOPIC,
-                NO_REQUEST_ID) >> '{valid-json}'
+            mockNetworkCmProxyDataService.getResourceDataForCmHandle(PASSTHROUGH_RUNNING.datastoreName, 'testCmHandle',
+                resourceIdentifier,'(a=1,b=2)', NO_TOPIC, NO_REQUEST_ID) >> '{valid-json}'
         when: 'get data resource request is performed'
             def response = mvc.perform(
                 get(getUrl)
@@ -531,9 +555,7 @@ class NetworkCmProxyControllerSpec extends Specification {
                     .contentType(MediaType.APPLICATION_JSON)
             ).andReturn().response
         then: 'the NCMP data service is called with getResourceDataOperational with #descendantsOption'
-            1 * mockNetworkCmProxyDataService.getResourceDataOperational('testCmHandle',
-                'parent/child',
-                descendantsOption)
+            1 * mockNetworkCmProxyDataService.getResourceDataForCmHandle(OPERATIONAL.datastoreName, 'testCmHandle', 'parent/child', descendantsOption)
         and: 'response status is Ok'
             response.status == HttpStatus.OK.value()
         where: 'the following parameters are used'
@@ -626,5 +648,19 @@ class NetworkCmProxyControllerSpec extends Specification {
         return assertContainsAll(response, expectedContent)
     }
 
+    def getNcmpDatastoreRequestHandler(dataStoreType, ncmpDatastoreRequestHandler) {
+        if (ncmpDatastoreRequestHandler instanceof NcmpCachedResourceRequestHandler) {
+            NcmpCachedResourceRequestHandler ncmpCachedResourceRequestHandler = (NcmpCachedResourceRequestHandler) ncmpDatastoreRequestHandler
+            ncmpCachedResourceRequestHandler.dataStoreName = dataStoreType.datastoreName
+        } else {
+            NcmpPassthroughResourceRequestHandler ncmpPassthroughResourceRequestHandler = (NcmpPassthroughResourceRequestHandler) ncmpDatastoreRequestHandler
+            ncmpPassthroughResourceRequestHandler.dataStoreName = dataStoreType.datastoreName
+        }
+        ncmpDatastoreRequestHandler.networkCmProxyDataService = mockNetworkCmProxyDataService
+        ncmpDatastoreRequestHandler.cpsNcmpTaskExecutor = spiedCpsTaskExecutor
+        ncmpDatastoreRequestHandler.notificationFeatureEnabled = NOTIFICATION_ENABLED
+        ncmpDatastoreRequestHandler.timeOutInMilliSeconds = TIMEOUT_IN_MS
+        return ncmpDatastoreRequestHandler
+    }
 }
 
index 7c50498..15b3ee6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2022 Nordix Foundation
+ *  Copyright (C) 2022-2023 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 package org.onap.cps.ncmp.rest.controller.handlers
 
+import org.spockframework.spring.SpringBean
 import spock.lang.Specification
 
 class NcmpDatastoreRequestHandlerFactorySpec extends Specification {
 
-    def objectUnderTest = new NcmpDatastoreResourceRequestHandlerFactory(null, null, null)
+    @SpringBean
+    NcmpCachedResourceRequestHandler mockNcmpCachedResourceRequestHandler = new NcmpCachedResourceRequestHandler(null)
+
+    @SpringBean
+    NcmpPassthroughResourceRequestHandler mockNcmpPassthroughResourceRequestHandler = new NcmpPassthroughResourceRequestHandler()
+
+    def objectUnderTest = new NcmpDatastoreResourceRequestHandlerFactory(mockNcmpCachedResourceRequestHandler, mockNcmpPassthroughResourceRequestHandler)
 
     def 'Creating ncmp datastore request handlers.'() {
         when: 'a ncmp datastore request handler is created for #datastoreType'
-            def result = objectUnderTest.getNcmpDatastoreResourceRequestHandler(datastoreType)
+            def result = objectUnderTest.getNcmpResourceRequestHandler(datastoreType)
         then: 'the result is of the expected class'
             result.class == expectedClass
         where: 'the following type of datastore is used'
             datastoreType                         || expectedClass
-            DatastoreType.OPERATIONAL             || NcmpDatastoreOperationalResourceRequestHandler
-            DatastoreType.PASSTHROUGH_OPERATIONAL || NcmpDatastorePassthroughOperationalResourceRequestHandler
-            DatastoreType.PASSTHROUGH_RUNNING     || NcmpDatastorePassthroughRunningResourceRequestHandler
+            DatastoreType.OPERATIONAL             || NcmpCachedResourceRequestHandler
+            DatastoreType.PASSTHROUGH_OPERATIONAL || NcmpPassthroughResourceRequestHandler
+            DatastoreType.PASSTHROUGH_RUNNING     || NcmpPassthroughResourceRequestHandler
     }
 }
index 128eed3..03737bc 100644 (file)
 
 package org.onap.cps.ncmp.api;
 
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum;
-
 import java.util.Collection;
+import java.util.List;
 import java.util.Map;
+import org.onap.cps.ncmp.api.impl.operations.OperationEnum;
 import org.onap.cps.ncmp.api.inventory.CompositeState;
 import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters;
 import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters;
@@ -51,50 +51,55 @@ public interface NetworkCmProxyDataService {
     DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule(DmiPluginRegistration dmiPluginRegistration);
 
     /**
-     * Get resource data for data store pass-through operational
-     * using dmi.
+     * Get resource data for given data store using dmi.
      *
-     * @param cmHandleId cm handle identifier
-     * @param resourceIdentifier resource identifier
+     * @param dataStoreName       data store name
+     * @param cmHandleId          cm handle identifier
+     * @param resourceIdentifier  resource identifier
      * @param optionsParamInQuery options query
-     * @param topicParamInQuery topic name for (triggering) async responses
-     * @param requestId unique requestId for async request
+     * @param topicParamInQuery   topic name for (triggering) async responses
+     * @param requestId           unique requestId for async request
      * @return {@code Object} resource data
      */
-    Object getResourceDataOperationalForCmHandle(String cmHandleId,
-                                                 String resourceIdentifier,
-                                                 String optionsParamInQuery,
-                                                 String topicParamInQuery,
-                                                 String requestId);
+    Object getResourceDataForCmHandle(String dataStoreName,
+                                      String cmHandleId,
+                                      String resourceIdentifier,
+                                      String optionsParamInQuery,
+                                      String topicParamInQuery,
+                                      String requestId);
 
     /**
      * Get resource data for operational.
      *
+     * @param dataStoreName       data store name
      * @param cmHandleId cm handle identifier
      * @param resourceIdentifier resource identifier
      * @Link FetchDescendantsOption fetch descendants option
      * @return {@code Object} resource data
      */
-    Object getResourceDataOperational(String cmHandleId,
+    Object getResourceDataForCmHandle(String dataStoreName,
+                                      String cmHandleId,
                                       String resourceIdentifier,
                                       FetchDescendantsOption fetchDescendantsOption);
 
     /**
-     * Get resource data for data store pass-through running
-     * using dmi.
+     * Get resource data for given batch of cm handles using dmi.
      *
-     * @param cmHandleId cm handle identifier
-     * @param resourceIdentifier resource identifier
+     * @param dataStoreName       data store name
+     * @param cmHandleIds         cm handle identifiers
+     * @param resourceIdentifier  resource identifier
      * @param optionsParamInQuery options query
-     * @param topicParamInQuery topic name for (triggering) async responses
-     * @param requestId unique requestId for async request
+     * @param topicParamInQuery   topic name for (triggering) async responses
+     * @param requestId           unique requestId for async request
      * @return {@code Object} resource data
      */
-    Object getResourceDataPassThroughRunningForCmHandle(String cmHandleId,
-                                                        String resourceIdentifier,
-                                                        String optionsParamInQuery,
-                                                        String topicParamInQuery,
-                                                        String requestId);
+    Object getResourceDataForCmHandleBatch(String dataStoreName,
+                                       List<String> cmHandleIds,
+                                       String resourceIdentifier,
+                                       String optionsParamInQuery,
+                                       String topicParamInQuery,
+                                       String requestId);
+
 
     /**
      * Write resource data for data store pass-through running
index b3904bd..1b1997f 100755 (executable)
@@ -25,7 +25,6 @@
 package org.onap.cps.ncmp.api.impl;
 
 import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum;
 import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateCmHandleQueryParameters;
 
 import com.google.common.collect.Lists;
@@ -46,7 +45,7 @@ import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService;
 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
 import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler;
 import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations;
-import org.onap.cps.ncmp.api.impl.operations.DmiOperations;
+import org.onap.cps.ncmp.api.impl.operations.OperationEnum;
 import org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions;
 import org.onap.cps.ncmp.api.impl.utils.InventoryQueryConditions;
 import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
@@ -115,38 +114,41 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
     }
 
     @Override
-    public Object getResourceDataOperationalForCmHandle(final String cmHandleId,
-                                                        final String resourceIdentifier,
-                                                        final String optionsParamInQuery,
-                                                        final String topicParamInQuery,
-                                                        final String requestId) {
-        final ResponseEntity<?> responseEntity = dmiDataOperations.getResourceDataFromDmi(cmHandleId,
+    public Object getResourceDataForCmHandle(final String dataStoreName,
+                                             final String cmHandleId,
+                                             final String resourceIdentifier,
+                                             final String optionsParamInQuery,
+                                             final String topicParamInQuery,
+                                             final String requestId) {
+        final ResponseEntity<?> responseEntity = dmiDataOperations.getResourceDataFromDmi(dataStoreName, cmHandleId,
                 resourceIdentifier,
                 optionsParamInQuery,
-                DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL,
-                requestId, topicParamInQuery);
+                topicParamInQuery,
+                requestId);
         return responseEntity.getBody();
     }
 
     @Override
-    public Object getResourceDataOperational(final String cmHandleId,
+    public Object getResourceDataForCmHandle(final String dataStoreName,
+                                             final String cmHandleId,
                                              final String resourceIdentifier,
                                              final FetchDescendantsOption fetchDescendantsOption) {
-        return cpsDataService.getDataNodes(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, resourceIdentifier,
+        return cpsDataService.getDataNodes(dataStoreName, cmHandleId, resourceIdentifier,
                 fetchDescendantsOption).iterator().next();
     }
 
     @Override
-    public Object getResourceDataPassThroughRunningForCmHandle(final String cmHandleId,
-                                                               final String resourceIdentifier,
-                                                               final String optionsParamInQuery,
-                                                               final String topicParamInQuery,
-                                                               final String requestId) {
-        final ResponseEntity<?> responseEntity = dmiDataOperations.getResourceDataFromDmi(cmHandleId,
+    public Object getResourceDataForCmHandleBatch(final String dataStoreName,
+                                                  final List<String> cmHandleIds,
+                                                  final String resourceIdentifier,
+                                                  final String optionsParamInQuery,
+                                                  final String topicParamInQuery,
+                                                  final String requestId) {
+        final ResponseEntity<?> responseEntity = dmiDataOperations.getResourceDataFromDmi(dataStoreName, cmHandleIds,
                 resourceIdentifier,
                 optionsParamInQuery,
-                DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING,
-                requestId, topicParamInQuery);
+                topicParamInQuery,
+                requestId);
         return responseEntity.getBody();
     }
 
index d5b459b..9d08780 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2022 Nordix Foundation
+ *  Copyright (C) 2021-2023 Nordix Foundation
  *  Modifications Copyright (C) 2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,7 +24,7 @@ package org.onap.cps.ncmp.api.impl.client;
 import lombok.AllArgsConstructor;
 import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration.DmiProperties;
 import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException;
-import org.onap.cps.ncmp.api.impl.operations.DmiRequestBody;
+import org.onap.cps.ncmp.api.impl.operations.OperationEnum;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
@@ -43,14 +43,14 @@ public class DmiRestClient {
     /**
      * Sends POST operation to DMI with json body containing module references.
      * @param dmiResourceUrl dmi resource url
-     * @param jsonData json data body
+     * @param requestBodyAsJsonString json data body
      * @param operation the type of operation being executed (for error reporting only)
      * @return response entity of type String
      */
     public ResponseEntity<Object> postOperationWithJsonData(final String dmiResourceUrl,
-                                                            final String jsonData,
-                                                            final DmiRequestBody.OperationEnum operation) {
-        final var httpEntity = new HttpEntity<>(jsonData, configureHttpHeaders(new HttpHeaders()));
+                                                            final String requestBodyAsJsonString,
+                                                            final OperationEnum operation) {
+        final var httpEntity = new HttpEntity<>(requestBodyAsJsonString, configureHttpHeaders(new HttpHeaders()));
         try {
             return restTemplate.postForEntity(dmiResourceUrl, httpEntity, Object.class);
         } catch (final HttpStatusCodeException httpStatusCodeException) {
index c3624b8..1fb72a5 100644 (file)
@@ -22,7 +22,6 @@ package org.onap.cps.ncmp.api.impl.events.avcsubscription;
 
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -30,7 +29,7 @@ import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.impl.events.EventsPublisher;
-import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService;
+import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer;
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
 import org.onap.cps.ncmp.api.inventory.InventoryPersistence;
 import org.onap.cps.ncmp.event.model.SubscriptionEvent;
@@ -45,7 +44,6 @@ public class SubscriptionEventForwarder {
 
     private final InventoryPersistence inventoryPersistence;
     private final EventsPublisher<SubscriptionEvent> eventsPublisher;
-
     private static final String DMI_AVC_SUBSCRIPTION_TOPIC_PREFIX = "ncmp-dmi-cm-avc-subscription-";
 
     /**
@@ -56,38 +54,24 @@ public class SubscriptionEventForwarder {
     public void forwardCreateSubscriptionEvent(final SubscriptionEvent subscriptionEvent) {
         final List<Object> cmHandleTargets = subscriptionEvent.getEvent().getPredicates().getTargets();
         if (cmHandleTargets == null || cmHandleTargets.isEmpty()
-            || cmHandleTargets.stream().anyMatch(id -> ((String) id).contains("*"))) {
+                || cmHandleTargets.stream().anyMatch(id -> ((String) id).contains("*"))) {
             throw new OperationNotYetSupportedException(
-                "CMHandle targets are required. \"Wildcard\" operations are not yet supported");
+                    "CMHandle targets are required. \"Wildcard\" operations are not yet supported");
         }
         final List<String> cmHandleTargetsAsStrings = cmHandleTargets.stream().map(
-            Objects::toString).collect(Collectors.toList());
+                Objects::toString).collect(Collectors.toList());
         final Collection<YangModelCmHandle> yangModelCmHandles =
-            inventoryPersistence.getYangModelCmHandles(cmHandleTargetsAsStrings);
-        final Map<String, Map<String, Map<String, String>>> dmiNameCmHandleMap =
-            organizeByDmiName(yangModelCmHandles);
-        dmiNameCmHandleMap.forEach((dmiName, cmHandlePropertiesMap) -> {
-            subscriptionEvent.getEvent().getPredicates().setTargets(Collections.singletonList(cmHandlePropertiesMap));
-            final String eventKey = createEventKey(subscriptionEvent, dmiName);
-            eventsPublisher.publishEvent(DMI_AVC_SUBSCRIPTION_TOPIC_PREFIX + dmiName, eventKey, subscriptionEvent);
-        });
-    }
+                inventoryPersistence.getYangModelCmHandles(cmHandleTargetsAsStrings);
 
-    private Map<String, Map<String, Map<String, String>>> organizeByDmiName(
-        final Collection<YangModelCmHandle> yangModelCmHandles) {
-        final Map<String, Map<String, Map<String, String>>> dmiNameCmHandlePropertiesMap = new HashMap<>();
-        yangModelCmHandles.forEach(cmHandle -> {
-            final String dmiName = cmHandle.resolveDmiServiceName(RequiredDmiService.DATA);
-            if (!dmiNameCmHandlePropertiesMap.containsKey(dmiName)) {
-                final Map<String, Map<String, String>> cmHandleDmiPropertiesMap = new HashMap<>();
-                cmHandleDmiPropertiesMap.put(cmHandle.getId(), dmiPropertiesAsMap(cmHandle));
-                dmiNameCmHandlePropertiesMap.put(cmHandle.getDmiDataServiceName(), cmHandleDmiPropertiesMap);
-            } else {
-                dmiNameCmHandlePropertiesMap.get(cmHandle.getDmiDataServiceName())
-                    .put(cmHandle.getId(), dmiPropertiesAsMap(cmHandle));
-            }
+        final Map<String, Map<String, Map<String, String>>> dmiPropertiesPerCmHandleIdPerServiceName
+                = DmiServiceNameOrganizer.getDmiPropertiesPerCmHandleIdPerServiceName(yangModelCmHandles);
+        dmiPropertiesPerCmHandleIdPerServiceName.forEach((dmiServiceName, cmHandlePropertiesMap) -> {
+            subscriptionEvent.getEvent().getPredicates().setTargets(Collections
+                    .singletonList(cmHandlePropertiesMap));
+            final String eventKey = createEventKey(subscriptionEvent, dmiServiceName);
+            eventsPublisher.publishEvent(DMI_AVC_SUBSCRIPTION_TOPIC_PREFIX + dmiServiceName, eventKey,
+                    subscriptionEvent);
         });
-        return dmiNameCmHandlePropertiesMap;
     }
 
     private String createEventKey(final SubscriptionEvent subscriptionEvent, final String dmiName) {
@@ -98,9 +82,4 @@ public class SubscriptionEventForwarder {
             + dmiName;
     }
 
-    public Map<String, String> dmiPropertiesAsMap(final YangModelCmHandle yangModelCmHandle) {
-        return yangModelCmHandle.getDmiProperties().stream().collect(
-            Collectors.toMap(YangModelCmHandle.Property::getName, YangModelCmHandle.Property::getValue));
-    }
-
 }
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/executor/TaskExecutor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/executor/TaskExecutor.java
new file mode 100644 (file)
index 0000000..192062f
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 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.ncmp.api.impl.executor;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Supplier;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class TaskExecutor {
+
+    /**
+     * Execute task asynchronously.
+     *
+     * @param taskSupplier    functional method is get() task need to executed asynchronously
+     * @param timeOutInMillis the timeout value in milliseconds
+     */
+    public static CompletableFuture<Object> executeTask(final Supplier<Object> taskSupplier,
+                                                        final long timeOutInMillis) {
+        return CompletableFuture.supplyAsync(taskSupplier::get)
+                .orTimeout(timeOutInMillis, MILLISECONDS);
+    }
+}
+
+
+
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DataStoreEnum.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DataStoreEnum.java
new file mode 100644 (file)
index 0000000..24edc73
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 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.ncmp.api.impl.operations;
+
+import lombok.Getter;
+
+@Getter
+public enum DataStoreEnum {
+    PASSTHROUGH_OPERATIONAL("ncmp-datastore:passthrough-operational"),
+    PASSTHROUGH_RUNNING("ncmp-datastore:passthrough-running");
+    private final String value;
+
+    DataStoreEnum(final String value) {
+        this.value = value;
+    }
+}
index 83faa00..d648352 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2022 Nordix Foundation
+ *  Copyright (C) 2021-2023 Nordix Foundation
  *  Modifications Copyright (C) 2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
 
 package org.onap.cps.ncmp.api.impl.operations;
 
-import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING;
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum;
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.READ;
+import static org.onap.cps.ncmp.api.impl.operations.DataStoreEnum.PASSTHROUGH_RUNNING;
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.READ;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
 import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
+import org.onap.cps.ncmp.api.impl.executor.TaskExecutor;
+import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer;
 import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder;
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
 import org.onap.cps.ncmp.api.inventory.CmHandleState;
 import org.onap.cps.ncmp.api.inventory.InventoryPersistence;
 import org.onap.cps.spi.exceptions.CpsException;
 import org.onap.cps.utils.JsonObjectMapper;
+import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
 
@@ -44,15 +49,14 @@ import org.springframework.stereotype.Component;
 @Slf4j
 public class DmiDataOperations extends DmiOperations {
 
-    /**
-     * Constructor for {@code DmiOperations}. This method also manipulates url properties.
-     *
-     * @param dmiRestClient {@code DmiRestClient}
-     */
+    private static final long DEFAULT_ASYNC_TASK_EXECUTOR_TIMEOUT_IN_MILLISECONDS = 30000L;
+    private static final String NO_CM_HANDLE_ID = "";
+
     public DmiDataOperations(final InventoryPersistence inventoryPersistence,
                              final JsonObjectMapper jsonObjectMapper,
                              final NcmpConfiguration.DmiProperties dmiProperties,
-                             final DmiRestClient dmiRestClient, final DmiServiceUrlBuilder dmiServiceUrlBuilder) {
+                             final DmiRestClient dmiRestClient,
+                             final DmiServiceUrlBuilder dmiServiceUrlBuilder) {
         super(inventoryPersistence, jsonObjectMapper, dmiProperties, dmiRestClient, dmiServiceUrlBuilder);
     }
 
@@ -60,48 +64,78 @@ public class DmiDataOperations extends DmiOperations {
      * This method fetches the resource data from operational data store for given cm handle
      * identifier on given resource using dmi client.
      *
-     * @param cmHandleId    network resource identifier
-     * @param resourceId  resource identifier
+     * @param dataStoreName       name of data store
+     * @param cmHandleId          network resource identifier
+     * @param resourceId          resource identifier
      * @param optionsParamInQuery options query
-     * @param dataStore           data store enum
-     * @param requestId           requestId for async responses
      * @param topicParamInQuery   topic name for (triggering) async responses
+     * @param requestId           requestId for async responses
      * @return {@code ResponseEntity} response entity
      */
-    public ResponseEntity<Object> getResourceDataFromDmi(final String cmHandleId,
+    public ResponseEntity<Object> getResourceDataFromDmi(final String dataStoreName,
+                                                         final String cmHandleId,
                                                          final String resourceId,
                                                          final String optionsParamInQuery,
-                                                         final DataStoreEnum dataStore,
-                                                         final String requestId,
-                                                         final String topicParamInQuery) {
+                                                         final String topicParamInQuery,
+                                                         final String requestId) {
         final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId);
-        final String jsonBody = getDmiRequestBody(READ, requestId, null, null, yangModelCmHandle);
-        final String dmiResourceDataUrl = getDmiRequestUrl(cmHandleId, resourceId, optionsParamInQuery, dataStore,
-                topicParamInQuery, yangModelCmHandle);
         final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
-        isCmHandleStateReady(yangModelCmHandle, cmHandleState);
-        return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonBody, READ);
+        validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
+        final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null,
+                yangModelCmHandle);
+        final String dmiResourceDataUrl = getDmiRequestUrl(dataStoreName, cmHandleId, resourceId, optionsParamInQuery,
+                topicParamInQuery, yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA));
+        return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ);
+    }
+
+    /**
+     * This method fetches the resource data by data store for given list of cm handles using dmi client.
+     *
+     * @param dataStoreName           data store name
+     * @param cmHandleIds         list of cm handles
+     * @param resourceId          resource identifier
+     * @param optionsParamInQuery options query
+     * @param topicParamInQuery   topic name for (triggering) async responses
+     * @param requestId           requestId for async responses
+     * @return {@code ResponseEntity} response entity
+     */
+    public ResponseEntity<Object> getResourceDataFromDmi(final String dataStoreName,
+                                                         final List<String> cmHandleIds,
+                                                         final String resourceId,
+                                                         final String optionsParamInQuery,
+                                                         final String topicParamInQuery,
+                                                         final String requestId) {
+        final Collection<YangModelCmHandle> yangModelCmHandles
+                = inventoryPersistence.getYangModelCmHandles(cmHandleIds);
+        final Map<String, Map<String, Map<String, String>>> dmiServiceNameCmHandlePropertiesMap =
+                DmiServiceNameOrganizer.getDmiPropertiesPerCmHandleIdPerServiceName(yangModelCmHandles);
+
+        buildBulkResourceDataRequestAndSend(dataStoreName, resourceId, optionsParamInQuery,
+                topicParamInQuery, requestId, dmiServiceNameCmHandlePropertiesMap);
+        return new ResponseEntity<>(HttpStatus.ACCEPTED);
     }
 
     /**
      * This method fetches all the resource data from operational data store for given cm handle
      * identifier using dmi client.
      *
+     * @param dataStoreName  data store name
      * @param cmHandleId network resource identifier
-     * @param dataStore  data store enum
      * @param requestId  requestId for async responses
      * @return {@code ResponseEntity} response entity
      */
-    public ResponseEntity<Object> getResourceDataFromDmi(final String cmHandleId,
-                                                         final DataStoreEnum dataStore,
+    public ResponseEntity<Object> getResourceDataFromDmi(final String dataStoreName,
+                                                         final String cmHandleId,
                                                          final String requestId) {
         final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId);
-        final String jsonBody = getDmiRequestBody(READ, requestId, null, null, yangModelCmHandle);
-        final String dmiResourceDataUrl = getDmiRequestUrl(cmHandleId, "/", null, dataStore,
-                null, yangModelCmHandle);
+        final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null,
+                yangModelCmHandle);
+        final String dmiResourceDataUrl = getDmiRequestUrl(dataStoreName, cmHandleId, "/", null,
+                null, yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA));
         final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
-        isCmHandleStateReady(yangModelCmHandle, cmHandleState);
-        return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonBody, READ);
+        validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
+        return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody,
+                READ);
     }
 
     /**
@@ -121,12 +155,14 @@ public class DmiDataOperations extends DmiOperations {
                                                                              final String requestData,
                                                                              final String dataType) {
         final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId);
-        final String jsonBody = getDmiRequestBody(operation, null, requestData, dataType, yangModelCmHandle);
-        final String dmiUrl = getDmiRequestUrl(cmHandleId, resourceId, null, PASSTHROUGH_RUNNING,
-                null, yangModelCmHandle);
+        final String jsonRequestBody = getDmiRequestBody(operation, null, requestData, dataType,
+                yangModelCmHandle);
+        final String dmiUrl = getDmiRequestUrl(PASSTHROUGH_RUNNING.getValue(), cmHandleId, resourceId,
+                null, null,
+                yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA));
         final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
-        isCmHandleStateReady(yangModelCmHandle, cmHandleState);
-        return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonBody, operation);
+        validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
+        return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, operation);
     }
 
     private YangModelCmHandle getYangModelCmHandle(final String cmHandleId) {
@@ -145,24 +181,80 @@ public class DmiDataOperations extends DmiOperations {
         return jsonObjectMapper.asJsonString(dmiRequestBody);
     }
 
-    private String getDmiRequestUrl(final String cmHandleId,
-                                      final String resourceId,
-                                      final String optionsParamInQuery,
-                                      final DataStoreEnum dataStore,
-                                      final String topicParamInQuery,
-                                      final YangModelCmHandle yangModelCmHandle) {
+    private String getDmiBulkRequestBody(final OperationEnum operation,
+                                         final String requestId,
+                                         final String requestData) {
+        final DmiRequestBody dmiBulkRequestBody = DmiRequestBody.builder()
+                .operation(operation)
+                .requestId(requestId)
+                .data(requestData)
+                .build();
+        return jsonObjectMapper.asJsonString(dmiBulkRequestBody);
+    }
+
+    private String getDmiRequestUrl(final String dataStoreName,
+                                    final String cmHandleId,
+                                    final String resourceId,
+                                    final String optionsParamInQuery,
+                                    final String topicParamInQuery,
+                                    final String dmiServiceName) {
         return dmiServiceUrlBuilder.getDmiDatastoreUrl(
                 dmiServiceUrlBuilder.populateQueryParams(resourceId, optionsParamInQuery,
-                        topicParamInQuery), dmiServiceUrlBuilder.populateUriVariables(
-                        yangModelCmHandle, cmHandleId, dataStore));
+                        topicParamInQuery), dmiServiceUrlBuilder.populateUriVariables(dataStoreName, dmiServiceName,
+                        cmHandleId));
     }
 
-    private void isCmHandleStateReady(final YangModelCmHandle yangModelCmHandle, final CmHandleState cmHandleState) {
+    private String getDmiServiceBulkRequestUrl(final String dataStoreName,
+                                               final String resourceId,
+                                               final String optionsParamInQuery,
+                                               final String topicParamInQuery,
+                                               final String dmiServiceName) {
+        return dmiServiceUrlBuilder.getBulkRequestUrl(
+                dmiServiceUrlBuilder.populateQueryParams(resourceId, optionsParamInQuery,
+                        topicParamInQuery), dmiServiceUrlBuilder.populateUriVariables(dataStoreName, dmiServiceName,
+                        NO_CM_HANDLE_ID));
+    }
+
+    private void validateIfCmHandleStateReady(final YangModelCmHandle yangModelCmHandle,
+                                              final CmHandleState cmHandleState) {
         if (cmHandleState != CmHandleState.READY) {
             throw new CpsException("State mismatch exception.", "Cm-Handle not in READY state. "
-                + "cm handle state is "
-                + yangModelCmHandle.getCompositeState().getCmHandleState());
+                    + "cm handle state is "
+                    + yangModelCmHandle.getCompositeState().getCmHandleState());
         }
     }
 
+    private void buildBulkResourceDataRequestAndSend(final String dataStoreName,
+                                                     final String resourceId,
+                                                     final String optionsParamInQuery,
+                                                     final String topicParamInQuery,
+                                                     final String requestId,
+                                                     final Map<String, Map<String, Map<String, String>>>
+                                                             dmiServiceNameCmHandlePropertiesMap) {
+        dmiServiceNameCmHandlePropertiesMap.entrySet().parallelStream().forEach(
+                dmiServiceNameCmHandlePropertiesEntry -> {
+                    final String dmiBulkResourceDataUrl = getDmiServiceBulkRequestUrl(dataStoreName, resourceId,
+                            optionsParamInQuery, topicParamInQuery, dmiServiceNameCmHandlePropertiesEntry.getKey());
+                    final String jsonRequestBodyAsJsonString =
+                            jsonObjectMapper.asJsonString(dmiServiceNameCmHandlePropertiesEntry.getValue());
+                    final String jsonRequestBody
+                            = getDmiBulkRequestBody(READ, requestId, jsonRequestBodyAsJsonString);
+                    sendDmiResourceDataRequestToDmiService(dmiBulkResourceDataUrl, jsonRequestBody);
+                });
+    }
+
+    private void sendDmiResourceDataRequestToDmiService(final String dmiBulkResourceDataUrl,
+                                                        final String dmiResourceDataRequestAsJsonString) {
+        TaskExecutor.executeTask(() ->
+                                dmiRestClient.postOperationWithJsonData(dmiBulkResourceDataUrl,
+                                        dmiResourceDataRequestAsJsonString, READ),
+                        DEFAULT_ASYNC_TASK_EXECUTOR_TIMEOUT_IN_MILLISECONDS)
+                .whenCompleteAsync(this::handleTaskCompletion);
+    }
+
+    private void handleTaskCompletion(final Object response, final Throwable throwable) {
+        // TODO Need to publish an error response to client given topic.
+        //  Code should be implemented into https://jira.onap.org/browse/CPS-1558 (
+        //  NCMP : Handle non responding DMI-Plugin)
+    }
 }
index d8d0304..392e9c1 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2022 Nordix Foundation
+ *  Copyright (C) 2021-2023 Nordix Foundation
  *  Modifications Copyright (C) 2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -98,17 +98,18 @@ public class DmiModelOperations extends DmiOperations {
      * Get resources from DMI for modules.
      *
      * @param dmiServiceName dmi service name
-     * @param jsonData module names and revisions as JSON
+     * @param jsonRequestBody module names and revisions as JSON
      * @param cmHandle cmHandle
      * @param resourceName name of the resource(s)
      * @return {@code ResponseEntity} response entity
      */
     private ResponseEntity<Object> getResourceFromDmiWithJsonData(final String dmiServiceName,
-                                                                  final String jsonData,
+                                                                  final String jsonRequestBody,
                                                                   final String cmHandle,
                                                                   final String resourceName) {
         final String dmiResourceDataUrl = getDmiResourceUrl(dmiServiceName, cmHandle, resourceName);
-        return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonData, DmiRequestBody.OperationEnum.READ);
+        return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody,
+                OperationEnum.READ);
     }
 
     private static String getRequestBodyToFetchYangResources(final Collection<ModuleReference> newModuleReferences,
index e26ffef..7e9079e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2022 Nordix Foundation
+ *  Copyright (C) 2021-2023 Nordix Foundation
  *  Modifications Copyright (C) 2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,7 +21,6 @@
 
 package org.onap.cps.ncmp.api.impl.operations;
 
-import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
 import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
@@ -34,17 +33,6 @@ import org.springframework.stereotype.Service;
 @Service
 public class DmiOperations {
 
-    @Getter
-    public enum DataStoreEnum {
-        PASSTHROUGH_OPERATIONAL("ncmp-datastore:passthrough-operational"),
-        PASSTHROUGH_RUNNING("ncmp-datastore:passthrough-running");
-        private final String value;
-
-        DataStoreEnum(final String value) {
-            this.value = value;
-        }
-    }
-
     protected final InventoryPersistence inventoryPersistence;
     protected final JsonObjectMapper jsonObjectMapper;
     protected final NcmpConfiguration.DmiProperties dmiProperties;
@@ -52,7 +40,7 @@ public class DmiOperations {
     protected final DmiServiceUrlBuilder dmiServiceUrlBuilder;
 
     String getDmiResourceUrl(final String dmiServiceName, final String cmHandle, final String resourceName) {
-        return dmiServiceUrlBuilder.getCmHandleUrl()
+        return dmiServiceUrlBuilder.getResourceDataBasePathUriBuilder()
                 .pathSegment("{resourceName}")
                 .buildAndExpand(dmiServiceName, dmiProperties.getDmiBasePath(), cmHandle, resourceName).toUriString();
     }
index c84e4cb..3aa6366 100644 (file)
@@ -22,7 +22,6 @@ package org.onap.cps.ncmp.api.impl.operations;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonValue;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -34,24 +33,6 @@ import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
 @Getter
 @Builder
 public class DmiRequestBody {
-    public enum OperationEnum {
-        READ("read"),
-        CREATE("create"),
-        UPDATE("update"),
-        PATCH("patch"),
-        DELETE("delete");
-        private final String value;
-
-        OperationEnum(final String value) {
-            this.value = value;
-        }
-
-        @Override
-        @JsonValue
-        public String toString() {
-            return String.valueOf(value);
-        }
-    }
 
     private OperationEnum operation;
     private String dataType;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationEnum.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationEnum.java
new file mode 100644 (file)
index 0000000..796cef2
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 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.ncmp.api.impl.operations;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+public enum OperationEnum {
+
+    READ("read"),
+    CREATE("create"),
+    UPDATE("update"),
+    PATCH("patch"),
+    DELETE("delete");
+    private final String value;
+
+    OperationEnum(final String value) {
+        this.value = value;
+    }
+
+    @Override
+    @JsonValue
+    public String toString() {
+        return String.valueOf(value);
+    }
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java
new file mode 100644 (file)
index 0000000..26e9486
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 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.ncmp.api.impl.utils;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService;
+import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class DmiServiceNameOrganizer {
+
+    /**
+     * organizes a map with dmi service name as key for cm handle with its properties.
+     *
+     * @param yangModelCmHandles list of cm handle model
+     */
+    public static Map<String, Map<String, Map<String, String>>> getDmiPropertiesPerCmHandleIdPerServiceName(
+            final Collection<YangModelCmHandle> yangModelCmHandles) {
+        final Map<String, Map<String, Map<String, String>>> dmiPropertiesPerCmHandleIdPerServiceName
+                = new HashMap<>();
+        yangModelCmHandles.forEach(yangModelCmHandle -> {
+            final String dmiServiceName = yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA);
+            if (!dmiPropertiesPerCmHandleIdPerServiceName.containsKey(dmiServiceName)) {
+                final Map<String, Map<String, String>> cmHandleDmiPropertiesMap = new HashMap<>();
+                cmHandleDmiPropertiesMap.put(yangModelCmHandle.getId(),
+                        dmiPropertiesAsMap(yangModelCmHandle.getDmiProperties()));
+                dmiPropertiesPerCmHandleIdPerServiceName.put(dmiServiceName, cmHandleDmiPropertiesMap);
+            } else {
+                dmiPropertiesPerCmHandleIdPerServiceName.get(dmiServiceName)
+                        .put(yangModelCmHandle.getId(), dmiPropertiesAsMap(yangModelCmHandle.getDmiProperties()));
+            }
+        });
+        return dmiPropertiesPerCmHandleIdPerServiceName;
+    }
+
+    private static Map<String, String> dmiPropertiesAsMap(final List<YangModelCmHandle.Property> dmiProperties) {
+        return dmiProperties.stream().collect(
+                Collectors.toMap(YangModelCmHandle.Property::getName, YangModelCmHandle.Property::getValue));
+    }
+}
index 5f4a654..bba8f48 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2022 Nordix Foundation
+ *  Copyright (C) 2022-2023 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 package org.onap.cps.ncmp.api.impl.utils;
 
-import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.DATA;
-
 import java.util.HashMap;
 import java.util.Map;
 import lombok.RequiredArgsConstructor;
 import org.apache.logging.log4j.util.Strings;
 import org.apache.logging.log4j.util.TriConsumer;
 import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
-import org.onap.cps.ncmp.api.impl.operations.DmiOperations;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
 import org.onap.cps.spi.utils.CpsValidator;
 import org.springframework.stereotype.Component;
 import org.springframework.util.LinkedMultiValueMap;
@@ -52,13 +48,21 @@ public class DmiServiceUrlBuilder {
      */
     public String getDmiDatastoreUrl(final MultiValueMap<String, String> queryParams,
                                      final Map<String, Object> uriVariables) {
-        final UriComponentsBuilder uriComponentsBuilder = getCmHandleUrl()
-                .pathSegment("data")
-                .pathSegment("ds")
-                .pathSegment("{dataStore}")
-                .queryParams(queryParams)
-                .uriVariables(uriVariables);
-        return uriComponentsBuilder.buildAndExpand().toUriString();
+        return getUriComponentsBuilder(getResourceDataBasePathUriBuilder(), queryParams, uriVariables)
+                .buildAndExpand().toUriString();
+    }
+
+    /**
+     * This method creates the dmi service url for bulk request.
+     *
+     * @param queryParams  query param map as key,value pair
+     * @param uriVariables uri param map as key (placeholder),value pair
+     * @return {@code String} dmi service url as string
+     */
+    public String getBulkRequestUrl(final MultiValueMap<String, String> queryParams,
+                                    final Map<String, Object> uriVariables) {
+        return getUriComponentsBuilder(getBulkResourceDataBasePathUriBuilder(), queryParams, uriVariables)
+                .buildAndExpand().toUriString();
     }
 
     /**
@@ -66,7 +70,7 @@ public class DmiServiceUrlBuilder {
      *
      * @return {@code UriComponentsBuilder} dmi service url builder object
      */
-    public UriComponentsBuilder getCmHandleUrl() {
+    public UriComponentsBuilder getResourceDataBasePathUriBuilder() {
         return UriComponentsBuilder.newInstance()
                 .path("{dmiServiceName}")
                 .pathSegment("{dmiBasePath}")
@@ -75,24 +79,37 @@ public class DmiServiceUrlBuilder {
                 .pathSegment("{cmHandleId}");
     }
 
+    /**
+     * This method creates the dmi service url builder object with path variables for batch of cm handles.
+     *
+     * @return {@code UriComponentsBuilder} dmi service url builder object
+     */
+    public UriComponentsBuilder getBulkResourceDataBasePathUriBuilder() {
+        return UriComponentsBuilder.newInstance()
+                .path("{dmiServiceName}")
+                .pathSegment("{dmiBasePath}")
+                .pathSegment("v1")
+                .pathSegment("batch");
+    }
+
     /**
      * This method populates uri variables.
      *
-     * @param yangModelCmHandle get dmi service name
+     * @param dataStoreName data store name 
+     * @param dmiServiceName dmi service name
      * @param cmHandleId        cm handle id for dmi registration
      * @return {@code String} dmi service url as string
      */
-    public Map<String, Object> populateUriVariables(final YangModelCmHandle yangModelCmHandle,
-                                                    final String cmHandleId,
-                                                    final DmiOperations.DataStoreEnum dataStore) {
+    public Map<String, Object> populateUriVariables(final String dataStoreName,
+                                                    final String dmiServiceName,
+                                                    final String cmHandleId) {
         cpsValidator.validateNameCharacters(cmHandleId);
         final Map<String, Object> uriVariables = new HashMap<>();
         final String dmiBasePath = dmiProperties.getDmiBasePath();
-        uriVariables.put("dmiServiceName",
-                yangModelCmHandle.resolveDmiServiceName(DATA));
+        uriVariables.put("dmiServiceName", dmiServiceName);
         uriVariables.put("dmiBasePath", dmiBasePath);
         uriVariables.put("cmHandleId", cmHandleId);
-        uriVariables.put("dataStore", dataStore.getValue());
+        uriVariables.put("dataStore", dataStoreName);
         return uriVariables;
     }
 
@@ -124,4 +141,15 @@ public class DmiServiceUrlBuilder {
             }
         };
     }
+
+    private UriComponentsBuilder getUriComponentsBuilder(final UriComponentsBuilder uriComponentsBuilder,
+                                                         final MultiValueMap<String, String> queryParams,
+                                                         final Map<String, Object> uriVariables) {
+        return uriComponentsBuilder
+                .pathSegment("data")
+                .pathSegment("ds")
+                .pathSegment("{dataStore}")
+                .queryParams(queryParams)
+                .uriVariables(uriVariables);
+    }
 }
index 537f501..b9cecfb 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2022 Nordix Foundation
+ *  Copyright (C) 2022-2023 Nordix Foundation
  *  Modifications Copyright (C) 2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,6 +21,8 @@
 
 package org.onap.cps.ncmp.api.inventory.sync;
 
+import static org.onap.cps.ncmp.api.impl.operations.DataStoreEnum.PASSTHROUGH_OPERATIONAL;
+
 import com.fasterxml.jackson.databind.JsonNode;
 import java.time.Duration;
 import java.time.OffsetDateTime;
@@ -37,7 +39,6 @@ import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations;
-import org.onap.cps.ncmp.api.impl.operations.DmiOperations;
 import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
 import org.onap.cps.ncmp.api.inventory.CmHandleQueries;
@@ -167,7 +168,8 @@ public class SyncUtils {
      */
     public String getResourceData(final String cmHandleId) {
         final ResponseEntity<Object> resourceDataResponseEntity = dmiDataOperations.getResourceDataFromDmi(
-                cmHandleId, DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL,
+                PASSTHROUGH_OPERATIONAL.getValue(),
+                cmHandleId,
                 UUID.randomUUID().toString());
         if (resourceDataResponseEntity.getStatusCode().is2xxSuccessful()) {
             return getFirstResource(resourceDataResponseEntity.getBody());
index 871af84..5b49e04 100644 (file)
@@ -52,10 +52,10 @@ import org.springframework.http.HttpStatus
 import org.springframework.http.ResponseEntity
 import spock.lang.Specification
 
-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
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE
+import static org.onap.cps.ncmp.api.impl.operations.DataStoreEnum.PASSTHROUGH_OPERATIONAL
+import static org.onap.cps.ncmp.api.impl.operations.DataStoreEnum.PASSTHROUGH_RUNNING
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.CREATE
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.UPDATE
 
 class NetworkCmProxyDataServiceImplSpec extends Specification {
 
@@ -94,61 +94,64 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
 
     def 'Write resource data for pass-through running from DMI using POST.'() {
         given: 'cpsDataService returns valid datanode'
-            mockCpsDataService.getDataNodes('NCMP-Admin', 'ncmp-dmi-registry',
-                cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
+            mockDataNode()
         when: 'write resource data is called'
             objectUnderTest.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
                 'testResourceId', CREATE,
                 '{some-json}', 'application/json')
         then: 'DMI called with correct data'
             1 * mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi('testCmHandle', 'testResourceId',
-                CREATE, '{some-json}', 'application/json')
+                    CREATE, '{some-json}', 'application/json')
                 >> { new ResponseEntity<>(HttpStatus.CREATED) }
     }
 
     def 'Get resource data for pass-through operational from DMI.'() {
         given: 'get data node is called'
-            mockCpsDataService.getDataNodes('NCMP-Admin', 'ncmp-dmi-registry',
-                cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
+            mockDataNode()
         and: 'get resource data from DMI is called'
-            mockDmiDataOperations.getResourceDataFromDmi(
-                'testCmHandle',
-                'testResourceId',
-                OPTIONS_PARAM,
-                PASSTHROUGH_OPERATIONAL,
-                NO_REQUEST_ID,
-                NO_TOPIC) >> new ResponseEntity<>('dmi-response', HttpStatus.OK)
+            mockDmiDataOperations.getResourceDataFromDmi(PASSTHROUGH_OPERATIONAL.value,'testCmHandle',
+                    'testResourceId', OPTIONS_PARAM, NO_TOPIC, NO_REQUEST_ID) >>
+                    new ResponseEntity<>('dmi-response', HttpStatus.OK)
         when: 'get resource data operational for cm-handle is called'
-            def response = objectUnderTest.getResourceDataOperationalForCmHandle('testCmHandle',
-                'testResourceId',
-                OPTIONS_PARAM,
-                NO_TOPIC,
-                NO_REQUEST_ID)
+            def response = objectUnderTest.getResourceDataForCmHandle(PASSTHROUGH_OPERATIONAL.value, 'testCmHandle',
+                    'testResourceId', OPTIONS_PARAM, NO_TOPIC, NO_REQUEST_ID)
         then: 'DMI returns a json response'
             response == 'dmi-response'
     }
 
     def 'Get resource data for pass-through running from DMI.'() {
         given: 'cpsDataService returns valid data node'
-            mockCpsDataService.getDataNodes('NCMP-Admin', 'ncmp-dmi-registry',
-                cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
+            mockDataNode()
         and: 'DMI returns valid response and data'
-            mockDmiDataOperations.getResourceDataFromDmi('testCmHandle',
-                'testResourceId',
-                OPTIONS_PARAM,
-                PASSTHROUGH_RUNNING,
-                NO_REQUEST_ID,
-                NO_TOPIC) >> new ResponseEntity<>('{dmi-response}', HttpStatus.OK)
+            mockDmiDataOperations.getResourceDataFromDmi(PASSTHROUGH_RUNNING.value, 'testCmHandle',
+                    'testResourceId', OPTIONS_PARAM, NO_TOPIC, NO_REQUEST_ID) >>
+                    new ResponseEntity<>('{dmi-response}', HttpStatus.OK)
         when: 'get resource data is called'
-            def response = objectUnderTest.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
-                'testResourceId',
-                OPTIONS_PARAM,
-                NO_TOPIC,
-                NO_REQUEST_ID)
+            def response = objectUnderTest.getResourceDataForCmHandle(PASSTHROUGH_RUNNING.value, 'testCmHandle',
+                    'testResourceId', OPTIONS_PARAM, NO_TOPIC, NO_REQUEST_ID)
         then: 'get resource data returns expected response'
             response == '{dmi-response}'
     }
 
+    def 'Get bulk resource data for #datastoreName from DMI.'() {
+        given: 'cpsDataService returns valid data node'
+            mockDataNode()
+        and: 'DMI returns valid response and data'
+            mockDmiDataOperations.getResourceDataFromDmi(datastoreName, ['testCmHandle'],
+                    'testResourceId', OPTIONS_PARAM,'some topic','requestId') >>
+                    new ResponseEntity<>('{dmi-bulk-response}', HttpStatus.OK)
+        when: 'get batch resource data is called'
+            def response = objectUnderTest.getResourceDataForCmHandleBatch(datastoreName, ['testCmHandle'],
+                    'testResourceId',
+                    OPTIONS_PARAM,
+                    'some topic',
+                    'requestId')
+        then: 'get bulk resource data returns expected response'
+            response == '{dmi-bulk-response}'
+        where: 'the following data stores are used'
+            datastoreName << [PASSTHROUGH_RUNNING.value, PASSTHROUGH_OPERATIONAL.value]
+    }
+
     def 'Getting Yang Resources.'() {
         when: 'yang resources is called'
             objectUnderTest.getYangResourcesModuleReferences('some-cm-handle')
@@ -242,7 +245,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
                 '{some-json}', 'application/json')
         then: 'DMI called with correct data'
             1 * mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi('testCmHandle', 'testResourceId',
-                UPDATE, '{some-json}', 'application/json')
+                    UPDATE, '{some-json}', 'application/json')
                 >> { new ResponseEntity<>(HttpStatus.OK) }
     }
 
@@ -365,4 +368,9 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
                 .dataStoreSyncState(DataStoreSyncState.NONE_REQUESTED)
                 .lastSyncTime('some-timestamp').build()).build()
     }
+
+    def mockDataNode() {
+        mockCpsDataService.getDataNodes('NCMP-Admin', 'ncmp-dmi-registry',
+                cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
+    }
 }
index 90839f8..b38ca10 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2022 Nordix Foundation
+ *  Copyright (C) 2021-2023 Nordix Foundation
  *  Modifications Copyright (C) 2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -34,10 +34,9 @@ import org.springframework.web.client.HttpServerErrorException
 import org.springframework.web.client.RestTemplate
 import spock.lang.Specification
 
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.READ
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.PATCH
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.CREATE
-
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.READ
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.PATCH
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.CREATE
 
 @SpringBootTest
 @ContextConfiguration(classes = [NcmpConfiguration.DmiProperties, DmiRestClient])
index 03825c2..89b3a2f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2022 Nordix Foundation
+ *  Copyright (C) 2021-2023 Nordix Foundation
  *  Modifications Copyright (C) 2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,14 +30,14 @@ import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.test.context.SpringBootTest
 import org.springframework.http.ResponseEntity
 import org.springframework.test.context.ContextConfiguration
+import org.springframework.http.HttpStatus
 import spock.lang.Shared
 
-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
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.READ
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE
-import org.springframework.http.HttpStatus
+import static org.onap.cps.ncmp.api.impl.operations.DataStoreEnum.PASSTHROUGH_OPERATIONAL
+import static org.onap.cps.ncmp.api.impl.operations.DataStoreEnum.PASSTHROUGH_RUNNING
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.CREATE
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.READ
+import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.UPDATE
 
 @SpringBootTest
 @ContextConfiguration(classes = [NcmpConfiguration.DmiProperties, DmiDataOperations])
@@ -50,6 +50,8 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
     def NO_REQUEST_ID = null
     @Shared
     def OPTIONS_PARAM = '(a=1,b=2)'
+    @Shared
+    def expectedBulkRequestAsJson = '{"operation": "read","data": {"fe1c1f1a070c4ce5bbfda7198592a0d3": {"neType": "RadioNode"},"b8e42eed0d9541ed8d8839e8eb86b3e0": {"neType": "RadioNode"}},"requestId": "bbb67474-f705-410a-93d1-b2844e7f45fd"}'
 
     @SpringBean
     JsonObjectMapper spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
@@ -66,8 +68,8 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
             mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson, READ) >> responseFromDmi
             dmiServiceUrlBuilder.getDmiDatastoreUrl(_, _) >> expectedUrl
         when: 'get resource data is invoked'
-            def result = objectUnderTest.getResourceDataFromDmi(cmHandleId, resourceIdentifier,
-                    options, dataStore, NO_REQUEST_ID, NO_TOPIC)
+            def result = objectUnderTest.getResourceDataFromDmi(dataStore.value, cmHandleId, resourceIdentifier,
+                    options, NO_TOPIC, NO_REQUEST_ID)
         then: 'the result is the response from the DMI service'
             assert result == responseFromDmi
         where: 'the following parameters are used'
@@ -80,6 +82,25 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
             'datastore running with properties'    | [yangModelCmHandleProperty] | PASSTHROUGH_RUNNING     | OPTIONS_PARAM || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-running'     | '&options=(a=1,b=2)'
     }
 
+    def 'call get bulk resource data for #dataStore from DMI service with topic #scenario.'() {
+        given: 'collection of yang model cm Handles'
+            mockYangModelCmHandleCollectionRetrieval([yangModelCmHandleProperty])
+        and: 'a positive response from DMI service when it is called with the expected parameters'
+            def responseFromDmi = new ResponseEntity<Object>(HttpStatus.ACCEPTED)
+            def expectedDmiBulkResourceDataUrl = "ncmp/v1/batch/data/ds/${dataStore}?resourceIdentifier=parent/child%26options=(a=1,b=2)&topic=my-topic-name&options=(fields=schemas/schema)"
+            mockDmiRestClient.postOperationWithJsonData(expectedDmiBulkResourceDataUrl, expectedBulkRequestAsJson, READ) >> responseFromDmi
+            dmiServiceUrlBuilder.getBulkRequestUrl(_, _) >> expectedDmiBulkResourceDataUrl
+        when: 'get resource data for bulk cm handle is invoked'
+            def result = objectUnderTest.getResourceDataFromDmi( dataStore.value, [cmHandleId], resourceIdentifier,
+                    OPTIONS_PARAM,  'some-topic','requestId')
+        then: 'the result is the response from the DMI service'
+            assert result == responseFromDmi
+        where: 'the following parameters are used'
+            scenario                | dataStore
+            'datastore operational' | PASSTHROUGH_OPERATIONAL
+            'datastore running'     | PASSTHROUGH_RUNNING
+    }
+
     def 'call get all resource data.'() {
         given: 'the system returns a cm handle with a sample property'
             mockYangModelCmHandleRetrieval([yangModelCmHandleProperty])
@@ -89,7 +110,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
             mockDmiRestClient.postOperationWithJsonData(expectedUrl, '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}', READ) >> responseFromDmi
             dmiServiceUrlBuilder.getDmiDatastoreUrl(_, _) >> expectedUrl
         when: 'get resource data is invoked'
-            def result = objectUnderTest.getResourceDataFromDmi(cmHandleId, PASSTHROUGH_OPERATIONAL, NO_REQUEST_ID)
+            def result = objectUnderTest.getResourceDataFromDmi( PASSTHROUGH_OPERATIONAL.value, cmHandleId, NO_REQUEST_ID)
         then: 'the result is the response from the DMI service'
             assert result == responseFromDmi
     }
index ed8f086..ed74ad3 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2022 Nordix Foundation
+ *  Copyright (C) 2021-2023 Nordix Foundation
  *  Modifications Copyright (C) 2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,6 +24,8 @@ package org.onap.cps.ncmp.api.impl.operations
 import com.fasterxml.jackson.core.JsonProcessingException
 import com.fasterxml.jackson.databind.ObjectMapper
 import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
+import org.onap.cps.ncmp.api.impl.executor.TaskExecutor
+import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer
 import org.onap.cps.spi.model.ModuleReference
 import org.onap.cps.utils.JsonObjectMapper
 import org.spockframework.spring.SpringBean
@@ -34,7 +36,7 @@ import org.springframework.http.ResponseEntity
 import org.springframework.test.context.ContextConfiguration
 import spock.lang.Shared
 
-import static  org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.READ
+import static  org.onap.cps.ncmp.api.impl.operations.OperationEnum.READ
 
 @SpringBootTest
 @ContextConfiguration(classes = [NcmpConfiguration.DmiProperties, DmiModelOperations])
@@ -49,6 +51,12 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
     @SpringBean
     JsonObjectMapper spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
 
+    @SpringBean
+    TaskExecutor stubbedTaskExecutor = Stub()
+
+    @SpringBean
+    DmiServiceNameOrganizer stubbedDmiServiceNameOrganizer = Stub()
+
     def 'Retrieving module references.'() {
         given: 'a cm handle'
             mockYangModelCmHandleRetrieval([])
@@ -89,7 +97,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
         and: 'a positive response from DMI service when it is called with tha expected parameters'
             def responseFromDmi = new ResponseEntity<String>(HttpStatus.OK)
             mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules",
-                '{"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}', READ) >> responseFromDmi
+                    '{"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}', READ) >> responseFromDmi
         when: 'a get module references is called'
             def result = objectUnderTest.getModuleReferences(yangModelCmHandle)
         then: 'the result is the response from DMI service'
@@ -108,7 +116,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
                                                       [moduleName: 'mod2', revision: 'C', yangSource: 'other yang source']], HttpStatus.OK)
             def expectedModuleReferencesInRequest = '{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}'
             mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
-                '{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":{}}', READ) >> responseFromDmi
+                    '{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":{}}', READ) >> responseFromDmi
         when: 'get new yang resources from DMI service'
             def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, newModuleReferences)
         then: 'the result has the 2 expected yang (re)sources (order is not guaranteed)'
@@ -140,7 +148,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
         and: 'a positive response from DMI service when it is called with the expected parameters'
             def responseFromDmi = new ResponseEntity<>([[moduleName: 'mod1', revision: 'A', yangSource: 'some yang source']], HttpStatus.OK)
             mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
-                '{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}', READ) >> responseFromDmi
+                    '{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}', READ) >> responseFromDmi
         when: 'get new yang resources from DMI service'
             def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, unknownModuleReferences)
         then: 'the result is the response from DMI service'
index c4d0020..1b2c50a 100644 (file)
@@ -58,12 +58,21 @@ abstract class DmiOperationsBaseSpec extends Specification {
     def static resourceIdentifier = 'parent/child'
 
     def mockYangModelCmHandleRetrieval(dmiProperties) {
+        populateYangModelCmHandle(dmiProperties)
+        mockInventoryPersistence.getYangModelCmHandle(cmHandleId) >> yangModelCmHandle
+    }
+
+    def mockYangModelCmHandleCollectionRetrieval(dmiProperties) {
+        populateYangModelCmHandle(dmiProperties)
+        mockInventoryPersistence.getYangModelCmHandles(_) >> [yangModelCmHandle]
+    }
+
+    def populateYangModelCmHandle(dmiProperties) {
         yangModelCmHandle.dmiDataServiceName = dmiServiceName
         yangModelCmHandle.dmiServiceName = dmiServiceName
         yangModelCmHandle.dmiProperties = dmiProperties
         yangModelCmHandle.id = cmHandleId
         yangModelCmHandle.compositeState = new CompositeState()
         yangModelCmHandle.compositeState.cmHandleState = CmHandleState.READY
-        mockInventoryPersistence.getYangModelCmHandle(cmHandleId) >> yangModelCmHandle
     }
 }
index 0156988..6ca3105 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2022 Nordix Foundation
+ *  Copyright (C) 2022-2023 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 package org.onap.cps.ncmp.api.impl.utils
 
+import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService
 import org.onap.cps.spi.utils.CpsValidator
 
-import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING
+import static org.onap.cps.ncmp.api.impl.operations.DataStoreEnum.PASSTHROUGH_RUNNING
 
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
 import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
@@ -45,8 +46,8 @@ class DmiServiceUrlBuilderSpec extends Specification {
     def 'Create the dmi service url with #scenario.'() {
         given: 'uri variables'
             dmiProperties.dmiBasePath = 'dmi'
-            def uriVars = objectUnderTest.populateUriVariables(yangModelCmHandle,
-                    "cmHandle", PASSTHROUGH_RUNNING)
+            def uriVars = objectUnderTest.populateUriVariables(PASSTHROUGH_RUNNING.value, yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA),
+                    "cmHandle")
         and: 'query params'
                             def uriQueries = objectUnderTest.populateQueryParams(resourceId,
                     'optionsParamInQuery', topic)
@@ -65,8 +66,8 @@ class DmiServiceUrlBuilderSpec extends Specification {
     def 'Populate dmi data store url #scenario.'() {
         given: 'uri variables are created'
             dmiProperties.dmiBasePath = dmiBasePath
-            def uriVars = objectUnderTest.populateUriVariables(yangModelCmHandle,
-                    "cmHandle", PASSTHROUGH_RUNNING)
+            def uriVars = objectUnderTest.populateUriVariables(PASSTHROUGH_RUNNING.value, yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA),
+                    "cmHandle")
         and: 'null query params'
             def uriQueries = objectUnderTest.populateQueryParams(null,
                     null, null)
index f4176d6..8164dcf 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2022 Nordix Foundation
+ *  Copyright (C) 2022-2023 Nordix Foundation
  *  Modifications Copyright (C) 2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
 
 package org.onap.cps.ncmp.api.inventory.sync
 
+import static org.onap.cps.ncmp.api.impl.operations.DataStoreEnum.PASSTHROUGH_OPERATIONAL
+
 import com.fasterxml.jackson.databind.JsonNode
 import com.fasterxml.jackson.databind.ObjectMapper
 import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations
-import org.onap.cps.ncmp.api.impl.operations.DmiOperations
 import org.onap.cps.ncmp.api.inventory.CmHandleQueries
 import org.onap.cps.ncmp.api.inventory.CmHandleState
 import org.onap.cps.ncmp.api.inventory.CompositeState
@@ -38,7 +39,6 @@ import org.springframework.http.HttpStatus
 import org.springframework.http.ResponseEntity
 import spock.lang.Shared
 import spock.lang.Specification
-
 import java.time.OffsetDateTime
 import java.time.format.DateTimeFormatter
 import java.util.stream.Collectors
@@ -137,7 +137,7 @@ class SyncUtilsSpec extends Specification{
             def jsonString = '{"stores:bookstore":{"categories":[{"code":"01"}]}}'
             JsonNode jsonNode = jsonObjectMapper.convertToJsonNode(jsonString);
             def responseEntity = new ResponseEntity<>(jsonNode, HttpStatus.OK)
-            mockDmiDataOperations.getResourceDataFromDmi('cm-handle-123', DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL, _) >> responseEntity
+            mockDmiDataOperations.getResourceDataFromDmi(PASSTHROUGH_OPERATIONAL.value, 'cm-handle-123', _) >> responseEntity
         when: 'get resource data is called'
             def result = objectUnderTest.getResourceData('cm-handle-123')
         then: 'the returned data is correct'
index 2018516..5f290cd 100644 (file)
@@ -1,7 +1,7 @@
 {
   "request": {
     "method": "POST",
-    "urlPattern": "/dmi/v1/ch/batch/data/ds/.*"
+    "urlPattern": "/dmi/v1/batch/data/ds/.*"
   },
   "response": {
     "status": 200,