Implement merging all ncmp datastore endpoints into one 46/130246/35
authorbmiklos <miklos.baranyak@est.tech>
Thu, 25 Aug 2022 16:28:16 +0000 (18:28 +0200)
committerbmiklos <miklos.baranyak@est.tech>
Thu, 1 Sep 2022 14:56:05 +0000 (16:56 +0200)
- Merging all endpoints
under /v1/ch/{cm-handle}/data/ds/ncmp-datastore:*
to /v1/ch/{cm-handle}/data/ds/{ncmp-datastore-name}

- Implementing missing tests from parent
- Introducing abstract class to keep the common code and just pass in
  the supplier to be executed in sync or async manner
- Removed the existing get endpoints for passthrough-running,
  passthrough-operational and operational and merged them into a common
  get endpoint

Issue-ID: CPS-1178
Issue-ID: CPS-1001
Change-Id: I6956c81d5acfa8fb11217bcc16cb795b62070fa3
Signed-off-by: bmiklos <miklos.baranyak@est.tech>
23 files changed:
cps-ncmp-rest-stub/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java
cps-ncmp-rest/docs/openapi/components.yaml
cps-ncmp-rest/docs/openapi/ncmp.yml
cps-ncmp-rest/docs/openapi/openapi.yml
cps-ncmp-rest/pom.xml
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/DatastoreType.java [new file with mode: 0644]
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreOperationalResourceRequestHandler.java [new file with mode: 0644]
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughOperationalResourceRequestHandler.java [new file with mode: 0644]
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughRunningResourceRequestHandler.java [new file with mode: 0644]
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandler.java [new file with mode: 0644]
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactory.java [new file with mode: 0644]
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/InvalidTopicException.java [moved from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidTopicException.java with 96% similarity]
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/TopicValidator.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/NcmpDatastoreResourceRequestHandlerFactorySpec.groovy [new file with mode: 0644]
cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy
cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/util/TopicValidatorSpec.groovy [new file with mode: 0644]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
cps-service/src/main/java/org/onap/cps/utils/CpsValidator.java
cps-service/src/test/groovy/org/onap/cps/utils/CpsValidatorSpec.groovy

index 67af6f1..ac5337d 100644 (file)
@@ -30,10 +30,9 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
-import javax.validation.Valid;
-import javax.validation.constraints.NotNull;
 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;
@@ -58,20 +57,53 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
     private String pathToResponseFiles;
 
     @Override
-    public ResponseEntity<Void> createResourceDataRunningForCmHandle(@NotNull @Valid final String resourceIdentifier,
-        final String cmHandleId, @Valid final Object body, final String contentType) {
+    public ResponseEntity<Object> getResourceDataForCmHandle(final String dataStoreType,
+                                                             final String cmHandle,
+                                                             final String resourceIdentifier,
+                                                             final String optionsParamInQuery,
+                                                             final String topicParamInQuery,
+                                                             final Boolean includeDescendants) {
+        if (DatastoreType.PASSTHROUGH_OPERATIONAL == DatastoreType.fromDatastoreName(dataStoreType)) {
+            final ResponseEntity<Map<String, Object>> asyncResponse = populateAsyncResponse(topicParamInQuery);
+            final Map<String, Object> asyncResponseData = asyncResponse.getBody();
+            Object responseObject = null;
+            // read JSON file and map/convert to java POJO
+            final ClassPathResource resource =
+                    new ClassPathResource(pathToResponseFiles + "passthrough-operational-example.json");
+            try (InputStream inputStream = resource.getInputStream()) {
+                final String string = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
+                final ObjectMapper mapper = new ObjectMapper();
+                responseObject = mapper.readValue(string, Object.class);
+            } catch (final IOException exception) {
+                log.error("Error reading the file.", exception);
+                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
+            }
+            if (asyncResponseData == null) {
+                return ResponseEntity.ok(responseObject);
+            }
+            return ResponseEntity.ok(asyncResponse);
+        }
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+    }
+
+    @Override
+    public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String resourceIdentifier,
+                                                                     final String cmHandleId,
+                                                                     final Object body,
+                                                                     final String contentType) {
         return new ResponseEntity<>(HttpStatus.CREATED);
     }
 
     @Override
     public ResponseEntity<Void> deleteResourceDataRunningForCmHandle(final String cmHandleId,
-        @NotNull @Valid final String resourceIdentifier, final String contentType) {
+                                                                     final String resourceIdentifier,
+                                                                     final String contentType) {
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
 
     @Override
     public ResponseEntity<List<RestOutputCmHandle>> searchCmHandles(
-        final CmHandleQueryParameters cmHandleQueryParameters) {
+            final CmHandleQueryParameters cmHandleQueryParameters) {
         List<RestOutputCmHandle> restOutputCmHandles = null;
         // read JSON file and map/convert to java POJO
         final ClassPathResource resource = new ClassPathResource(pathToResponseFiles + "cmHandlesSearch.json");
@@ -88,19 +120,19 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
 
     @Override
     public ResponseEntity<Object> setDataSyncEnabledFlagForCmHandle(final String cmHandleId,
-                                                                final Boolean dataSyncEnabled) {
+                                                                    final Boolean dataSyncEnabled) {
         return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
     }
 
     @Override
     public ResponseEntity<List<String>> searchCmHandleIds(
-        final CmHandleQueryParameters cmHandleQueryParameters) {
+            final CmHandleQueryParameters cmHandleQueryParameters) {
         return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
     }
 
     @Override
     public ResponseEntity<RestOutputCmHandlePublicProperties> getCmHandlePublicPropertiesByCmHandleId(
-        final String cmHandleId) {
+            final String cmHandleId) {
         return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
     }
 
@@ -119,48 +151,11 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
         return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
     }
 
-    /**
-     * Get resource data from operational datastore.
-     *
-     * @param cmHandleId cm handle identifier
-     * @param resourceIdentifier resource identifier
-     * @param optionsParamInQuery options query parameter
-     * @param topicParamInQuery topic query parameter
-     * @return {@code ResponseEntity} response from dmi plugin
-     */
-    @Override
-    public ResponseEntity<Object> getResourceDataOperationalForCmHandle(final String cmHandleId,
-        final String resourceIdentifier, final String optionsParamInQuery, final String topicParamInQuery) {
-        final ResponseEntity<Map<String, Object>> asyncResponse = populateAsyncResponse(topicParamInQuery);
-        final Map<String, Object> asyncResponseData = asyncResponse.getBody();
-        Object responseObject = null;
-        // read JSON file and map/convert to java POJO
-        final ClassPathResource resource = new ClassPathResource(pathToResponseFiles
-            + "passthrough-operational-example.json");
-        try (InputStream inputStream = resource.getInputStream()) {
-            final String string = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
-            final ObjectMapper mapper = new ObjectMapper();
-            responseObject = mapper.readValue(string, Object.class);
-        } catch (final IOException exception) {
-            log.error("Error reading the file.", exception);
-            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
-        }
-        if (asyncResponseData == null) {
-            return ResponseEntity.ok(responseObject);
-        }
-        return ResponseEntity.ok(asyncResponse);
-
-    }
-
-    @Override
-    public ResponseEntity<Object> getResourceDataRunningForCmHandle(final String cmHandleId,
-        final String resourceIdentifier, final String options, final String topic) {
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
     @Override
     public ResponseEntity<Object> patchResourceDataRunningForCmHandle(final String resourceIdentifier,
-        final String cmHandleId, final Object body, final String contentType) {
+                                                                      final String cmHandleId,
+                                                                      final Object body,
+                                                                      final String contentType) {
         return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
     }
 
@@ -170,8 +165,10 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
     }
 
     @Override
-    public ResponseEntity<Object> updateResourceDataRunningForCmHandle(@NotNull @Valid final String resourceIdentifier,
-        final String cmHandleId, @Valid final Object body, final String contentType) {
+    public ResponseEntity<Object> updateResourceDataRunningForCmHandle(final String resourceIdentifier,
+                                                                       final String cmHandleId,
+                                                                       final Object body,
+                                                                       final String contentType) {
         return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
     }
 
index 427f083..7ca09ce 100644 (file)
@@ -86,7 +86,7 @@ components:
           type: array
           items:
             type: string
-          example: [my-cm-handle1, my-cm-handle2, my-cm-handle3]
+          example: [ my-cm-handle1, my-cm-handle2, my-cm-handle3 ]
     DmiPluginRegistrationErrorResponse:
       type: object
       properties:
@@ -124,14 +124,14 @@ components:
           type: string
           example: my-cm-handle
         cmHandleProperties:
-            $ref: '#/components/schemas/RestCmHandleProperties'
+          $ref: '#/components/schemas/RestCmHandleProperties'
         publicCmHandleProperties:
-            $ref: '#/components/schemas/RestCmHandleProperties'
+          $ref: '#/components/schemas/RestCmHandleProperties'
     RestCmHandleProperties:
-        type: object
-        additionalProperties:
-            type: string
-            example: my-property
+      type: object
+      additionalProperties:
+        type: string
+        example: my-property
 
     #Response Schemas
     RestModuleReference:
@@ -288,21 +288,21 @@ components:
 
   examples:
     dataSampleRequest:
-        summary: Sample request
-        description: Sample request body
-        value:
-          test:bookstore:
-            bookstore-name: Chapters
-            categories:
-              - code: '01'
-                name: SciFi
-                books:
+      summary: Sample request
+      description: Sample request body
+      value:
+        test:bookstore:
+          bookstore-name: Chapters
+          categories:
+            - code: '01'
+              name: SciFi
+              books:
                 - authors:
                     - Iain M. Banks
                     - Ursula K. Le Guin
-              - code: '02'
-                name: kids
-                books:
+            - code: '02'
+              name: kids
+              books:
                 - authors:
                     - Philip Pullman
 
@@ -351,22 +351,22 @@ components:
                             - Philip Pullman
 
     dataSampleResponse:
-        summary: Sample response
-        description: Sample response for selecting 'sample 1'.
-        value:
-          bookstore:
-            categories:
-              - code: '01'
-                books:
-                  - authors:
-                      - Iain M. Banks
-                      - Ursula K. Le Guin
-                name: SciFi
-              - code: '02'
-                books:
-                  - authors:
-                      - Philip Pullman
-                name: kids
+      summary: Sample response
+      description: Sample response for selecting 'sample 1'.
+      value:
+        bookstore:
+          categories:
+            - code: '01'
+              books:
+                - authors:
+                    - Iain M. Banks
+                    - Ursula K. Le Guin
+              name: SciFi
+            - code: '02'
+              books:
+                - authors:
+                    - Philip Pullman
+              name: kids
 
     allCmHandleQueryParameters:
       value:
@@ -448,7 +448,7 @@ components:
     includeDescendantsOptionInQuery:
       name: include-descendants
       in: query
-      description: include-descendants
+      description: Determines if descendants are included in response
       required: false
       schema:
         type: boolean
@@ -526,6 +526,14 @@ components:
         type: string
         default: application/json
         example: application/yang-data+json
+    datastoreName:
+      name: ncmp-datastore-name
+      in: path
+      description: The type of the requested data
+      required: true
+      schema:
+        type: string
+        example: ncmp-datastore:operational
 
   responses:
     NotFound:
@@ -555,9 +563,9 @@ components:
           schema:
             $ref: '#/components/schemas/ErrorMessage'
           example:
-           status: 403
-           message: Forbidden error message
-           details: Forbidden error details
+            status: 403
+            message: Forbidden error message
+            details: Forbidden error details
     BadRequest:
       description: Bad Request
       content:
@@ -565,9 +573,9 @@ components:
           schema:
             $ref: '#/components/schemas/ErrorMessage'
           example:
-           status: 400 BAD_REQUEST
-           message: Bad request error message
-           details: Bad request error details
+            status: 400 BAD_REQUEST
+            message: Bad request error message
+            details: Bad request error details
     Conflict:
       description: Conflict
       content:
@@ -575,9 +583,9 @@ components:
           schema:
             $ref: '#/components/schemas/ErrorMessage'
           example:
-           status: 409 CONFLICT
-           message: Conflict error message
-           details: Conflict error details
+            status: 409 CONFLICT
+            message: Conflict error message
+            details: Conflict error details
     NotImplemented:
       description: The given path has not been implemented
       content:
@@ -585,9 +593,9 @@ components:
           schema:
             $ref: '#/components/schemas/ErrorMessage'
           example:
-           status: 501
-           message: Not implemented error message
-           details: Not implemented error details
+            status: 501
+            message: Not implemented error message
+            details: Not implemented error details
     Ok:
       description: OK
       content:
@@ -596,10 +604,10 @@ components:
             type: object
     Created:
       description: Created
-      content: {}
+      content: { }
     NoContent:
       description: No Content
-      content: {}
+      content: { }
     InternalServerError:
       description: Internal Server Error
       content:
index 4266fc4..5e22f77 100755 (executable)
 #
 #  SPDX-License-Identifier: Apache-2.0
 #  ============LICENSE_END=========================================================
-getResourceDataForPassthroughOperational:
+
+getResourceDataForCmHandle:
   get:
     tags:
       - network-cm-proxy
-    summary: Get resource data from pass-through operational for cm handle
-    description: Get resource data from pass-through operational for given cm handle
-    operationId: getResourceDataOperationalForCmHandle
+    summary: Get resource data for cm handle
+    description: Get resource data for given cm handle
+    operationId: getResourceDataForCmHandle
     parameters:
+      - $ref: 'components.yaml#/components/parameters/datastoreName'
       - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
       - $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
       - $ref: 'components.yaml#/components/parameters/optionsParamInQuery'
       - $ref: 'components.yaml#/components/parameters/topicParamInQuery'
+      - $ref: 'components.yaml#/components/parameters/includeDescendantsOptionInQuery'
     responses:
       200:
         description: OK
@@ -51,37 +54,6 @@ getResourceDataForPassthroughOperational:
         $ref: 'components.yaml#/components/responses/BadGateway'
 
 resourceDataForPassthroughRunning:
-  get:
-    tags:
-      - network-cm-proxy
-    summary: Get resource data from pass-through running for cm handle
-    description: Get resource data from pass-through running for given cm handle
-    operationId: getResourceDataRunningForCmHandle
-    parameters:
-      - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
-      - $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
-      - $ref: 'components.yaml#/components/parameters/optionsParamInQuery'
-      - $ref: 'components.yaml#/components/parameters/topicParamInQuery'
-    responses:
-      200:
-        description: OK
-        content:
-          application/json:
-            schema:
-              type: object
-            examples:
-              dataSampleResponse:
-                $ref: 'components.yaml#/components/examples/dataSampleResponse'
-      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'
   post:
     tags:
       - network-cm-proxy
index 8e02066..ed15fcd 100755 (executable)
@@ -26,8 +26,8 @@ info:
 servers:
   - url: /ncmp
 paths:
-  /v1/ch/{cm-handle}/data/ds/ncmp-datastore:passthrough-operational:
-    $ref: 'ncmp.yml#/getResourceDataForPassthroughOperational'
+  /v1/ch/{cm-handle}/data/ds/{ncmp-datastore-name}:
+    $ref: 'ncmp.yml#/getResourceDataForCmHandle'
 
   /v1/ch/{cm-handle}/data/ds/ncmp-datastore:passthrough-running:
     $ref: 'ncmp.yml#/resourceDataForPassthroughRunning'
index 6a700c3..b3021d2 100644 (file)
                             <goal>copy-resources</goal>
                         </goals>
                         <configuration>
-                            <outputDirectory>${project.basedir}/target/classes/static/api-docs/cps-ncmp</outputDirectory>
+                            <outputDirectory>${project.basedir}/target/classes/static/api-docs/cps-ncmp
+                            </outputDirectory>
                             <resources>
                                 <resource>
                                     <directory>${project.basedir}/target/generated-sources/swagger/</directory>
index d2ed393..9aa8263 100755 (executable)
@@ -29,21 +29,18 @@ import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum
 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE;
 
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
-import java.util.UUID;
 import java.util.stream.Collectors;
-import javax.validation.Valid;
-import javax.validation.constraints.NotNull;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
-import org.onap.cps.ncmp.api.impl.exception.InvalidTopicException;
 import org.onap.cps.ncmp.api.inventory.CompositeState;
 import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters;
 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
 import org.onap.cps.ncmp.rest.api.NetworkCmProxyApi;
-import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
+import org.onap.cps.ncmp.rest.controller.handlers.DatastoreType;
+import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreResourceRequestHandler;
+import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreResourceRequestHandlerFactory;
 import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper;
 import org.onap.cps.ncmp.rest.model.CmHandlePublicProperties;
 import org.onap.cps.ncmp.rest.model.CmHandleQueryParameters;
@@ -53,9 +50,7 @@ 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.util.DeprecationHelper;
-import org.onap.cps.utils.CpsValidator;
 import org.onap.cps.utils.JsonObjectMapper;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -68,94 +63,50 @@ import org.springframework.web.bind.annotation.RestController;
 public class NetworkCmProxyController implements NetworkCmProxyApi {
 
     private static final String NO_BODY = null;
-    private static final String NO_REQUEST_ID = null;
-    private static final String NO_TOPIC = null;
     private final NetworkCmProxyDataService networkCmProxyDataService;
     private final JsonObjectMapper jsonObjectMapper;
-
     private final DeprecationHelper deprecationHelper;
     private final NcmpRestInputMapper ncmpRestInputMapper;
     private final CmHandleStateMapper cmHandleStateMapper;
-    private final CpsNcmpTaskExecutor cpsNcmpTaskExecutor;
-    @Value("${notification.async.executor.time-out-value-in-ms:2000}")
-    private int timeOutInMilliSeconds;
-    @Value("${notification.enabled:true}")
-    private boolean asyncEnabled;
+    private final NcmpDatastoreResourceRequestHandlerFactory ncmpDatastoreResourceRequestHandlerFactory;
 
     /**
-     * Get resource data from operational datastore.
+     * Get resource data from datastore.
      *
-     * @param cmHandle cm handle identifier
-     * @param resourceIdentifier resource identifier
+     * @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 topicParamInQuery   topic query parameter
+     * @param includeDescendants  whether include descendants
      * @return {@code ResponseEntity} response from dmi plugin
      */
-    @Override
-    public ResponseEntity<Object> getResourceDataOperationalForCmHandle(final String cmHandle,
-                                                                        final @NotNull @Valid String resourceIdentifier,
-                                                                        final @Valid String optionsParamInQuery,
-                                                                        final @Valid String topicParamInQuery) {
-        if (asyncEnabled && isValidTopic(topicParamInQuery)) {
-            final String requestId = UUID.randomUUID().toString();
-            log.info("Received Async passthrough-operational request with id {}", requestId);
-            cpsNcmpTaskExecutor.executeTask(() ->
-                    networkCmProxyDataService.getResourceDataOperationalForCmHandle(
-                        cmHandle, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId
-                    ), timeOutInMilliSeconds
-            );
-            return ResponseEntity.ok(Map.of("requestId", requestId));
-        } else {
-            log.warn("Asynchronous messaging is currently disabled for passthrough-operational."
-                + " Will use synchronous operation.");
-        }
 
-        final Object responseObject = networkCmProxyDataService.getResourceDataOperationalForCmHandle(
-            cmHandle, resourceIdentifier, optionsParamInQuery, NO_TOPIC, NO_REQUEST_ID);
-
-        return ResponseEntity.ok(responseObject);
-    }
-
-    /**
-     * Get resource data from pass-through running datastore.
-     *
-     * @param cmHandle cm handle identifier
-     * @param resourceIdentifier resource identifier
-     * @param optionsParamInQuery options query parameter
-     * @param topicParamInQuery topic query parameter
-     * @return {@code ResponseEntity} response from dmi plugin
-     */
     @Override
-    public ResponseEntity<Object> getResourceDataRunningForCmHandle(final String cmHandle,
-                                                                    final @NotNull @Valid String resourceIdentifier,
-                                                                    final @Valid String optionsParamInQuery,
-                                                                    final @Valid String topicParamInQuery) {
-        if (asyncEnabled && isValidTopic(topicParamInQuery)) {
-            final String requestId = UUID.randomUUID().toString();
-            log.info("Received Async passthrough-running request with id {}", requestId);
-            cpsNcmpTaskExecutor.executeTask(() ->
-                networkCmProxyDataService.getResourceDataPassThroughRunningForCmHandle(
-                    cmHandle, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId
-                ), timeOutInMilliSeconds
-            );
-            return ResponseEntity.ok(Map.of("requestId", requestId));
-        } else {
-            log.warn("Asynchronous messaging is currently disabled for passthrough-running."
-                + " Will use synchronous operation.");
-        }
+    public ResponseEntity<Object> getResourceDataForCmHandle(final String datastoreName,
+                                                             final String cmHandle,
+                                                             final String resourceIdentifier,
+                                                             final String optionsParamInQuery,
+                                                             final String topicParamInQuery,
+                                                             final Boolean includeDescendants) {
 
-        final Object responseObject = networkCmProxyDataService.getResourceDataPassThroughRunningForCmHandle(
-            cmHandle, resourceIdentifier, optionsParamInQuery, NO_TOPIC, NO_REQUEST_ID);
+        final NcmpDatastoreResourceRequestHandler ncmpDatastoreResourceRequestHandler =
+                ncmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceRequestHandler(
+                        DatastoreType.fromDatastoreName(datastoreName));
 
-        return ResponseEntity.ok(responseObject);
+        return ncmpDatastoreResourceRequestHandler.getResourceData(cmHandle, resourceIdentifier,
+                optionsParamInQuery, topicParamInQuery, includeDescendants);
     }
 
     @Override
     public ResponseEntity<Object> patchResourceDataRunningForCmHandle(final String resourceIdentifier,
-        final String cmHandle,
-        final Object requestBody, final String contentType) {
-        final Object responseObject = networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
-            resourceIdentifier, PATCH, jsonObjectMapper.asJsonString(requestBody), contentType);
+                                                                      final String cmHandle,
+                                                                      final Object requestBody,
+                                                                      final String contentType) {
+        final Object responseObject = networkCmProxyDataService
+                .writeResourceDataPassThroughRunningForCmHandle(
+                        cmHandle, resourceIdentifier, PATCH,
+                        jsonObjectMapper.asJsonString(requestBody), contentType);
         return ResponseEntity.ok(responseObject);
     }
 
@@ -163,14 +114,16 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
      * Create resource data in datastore pass-through running for given cm-handle.
      *
      * @param resourceIdentifier resource identifier
-     * @param cmHandle cm handle identifier
-     * @param requestBody the request body
-     * @param contentType content type of body
+     * @param cmHandle           cm handle identifier
+     * @param requestBody        the request body
+     * @param contentType        content type of body
      * @return {@code ResponseEntity} response from dmi plugin
      */
     @Override
     public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String resourceIdentifier,
-        final String cmHandle, final Object requestBody, final String contentType) {
+                                                                     final String cmHandle,
+                                                                     final Object requestBody,
+                                                                     final String contentType) {
         networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
                 resourceIdentifier, CREATE, jsonObjectMapper.asJsonString(requestBody), contentType);
         return new ResponseEntity<>(HttpStatus.CREATED);
@@ -180,9 +133,9 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
      * Update resource data in datastore pass-through running for given cm-handle.
      *
      * @param resourceIdentifier resource identifier
-     * @param cmHandle cm handle identifier
-     * @param requestBody the request body
-     * @param contentType content type of the body
+     * @param cmHandle           cm handle identifier
+     * @param requestBody        the request body
+     * @param contentType        content type of the body
      * @return response entity
      */
     @Override
@@ -197,11 +150,11 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
 
 
     /**
-     *  Delete resource data in datastore pass-through running for a given cm-handle.
+     * Delete resource data in datastore pass-through running for a given cm-handle.
      *
      * @param resourceIdentifier resource identifier
-     * @param cmHandle cm handle identifier
-     * @param contentType content type of the body
+     * @param cmHandle           cm handle identifier
+     * @param contentType        content type of the body
      * @return response entity no content if request is successful
      */
     @Override
@@ -209,7 +162,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
                                                                      final String resourceIdentifier,
                                                                      final String contentType) {
         networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
-            resourceIdentifier, DELETE, NO_BODY, contentType);
+                resourceIdentifier, DELETE, NO_BODY, contentType);
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
 
@@ -240,7 +193,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
      */
     @Override
     public ResponseEntity<List<String>> searchCmHandleIds(
-        final CmHandleQueryParameters cmHandleQueryParameters) {
+            final CmHandleQueryParameters cmHandleQueryParameters) {
         final CmHandleQueryApiParameters cmHandleQueryApiParameters =
                 jsonObjectMapper.convertToValueType(cmHandleQueryParameters, CmHandleQueryApiParameters.class);
         final Set<String> cmHandleIds = networkCmProxyDataService.executeCmHandleIdSearch(cmHandleQueryApiParameters);
@@ -249,6 +202,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
 
     /**
      * Search for Cm Handle and Properties by Name.
+     *
      * @param cmHandleId cm-handle identifier
      * @return cm handle and its properties
      */
@@ -261,33 +215,35 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
 
     /**
      * Get Cm Handle Properties by Cm Handle Id.
+     *
      * @param cmHandleId cm-handle identifier
      * @return cm handle properties
      */
     @Override
     public ResponseEntity<RestOutputCmHandlePublicProperties> getCmHandlePublicPropertiesByCmHandleId(
-        final String cmHandleId) {
+            final String cmHandleId) {
         final CmHandlePublicProperties cmHandlePublicProperties = new CmHandlePublicProperties();
         cmHandlePublicProperties.add(networkCmProxyDataService.getCmHandlePublicProperties(cmHandleId));
         final RestOutputCmHandlePublicProperties restOutputCmHandlePublicProperties =
-            new RestOutputCmHandlePublicProperties();
+                new RestOutputCmHandlePublicProperties();
         restOutputCmHandlePublicProperties.setPublicCmHandleProperties(cmHandlePublicProperties);
         return ResponseEntity.ok(restOutputCmHandlePublicProperties);
     }
 
     /**
      * Get Cm Handle State by Cm Handle Id.
+     *
      * @param cmHandleId cm-handle identifier
      * @return cm handle state
      */
     @Override
     public ResponseEntity<RestOutputCmHandleCompositeState> getCmHandleStateByCmHandleId(
-        final String cmHandleId) {
+            final String cmHandleId) {
         final CompositeState cmHandleState = networkCmProxyDataService.getCmHandleCompositeState(cmHandleId);
         final RestOutputCmHandleCompositeState restOutputCmHandleCompositeState =
-            new RestOutputCmHandleCompositeState();
+                new RestOutputCmHandleCompositeState();
         restOutputCmHandleCompositeState.setState(
-            cmHandleStateMapper.toCmHandleCompositeStateExternalLockReason(cmHandleState));
+                cmHandleStateMapper.toCmHandleCompositeStateExternalLockReason(cmHandleState));
         return ResponseEntity.ok(restOutputCmHandleCompositeState);
     }
 
@@ -314,22 +270,22 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
      */
     public ResponseEntity<List<RestModuleReference>> getModuleReferencesByCmHandle(final String cmHandle) {
         final List<RestModuleReference> restModuleReferences =
-            networkCmProxyDataService.getYangResourcesModuleReferences(cmHandle).stream()
-            .map(ncmpRestInputMapper::toRestModuleReference)
-                .collect(Collectors.toList());
+                networkCmProxyDataService.getYangResourcesModuleReferences(cmHandle).stream()
+                        .map(ncmpRestInputMapper::toRestModuleReference)
+                        .collect(Collectors.toList());
         return new ResponseEntity<>(restModuleReferences, HttpStatus.OK);
     }
 
     /**
      * Set the data sync enabled flag, along with the data sync state for the specified cm handle.
      *
-     * @param cmHandleId cm handle id
+     * @param cmHandleId          cm handle id
      * @param dataSyncEnabledFlag data sync enabled flag
      * @return response entity ok if request is successful
      */
     @Override
     public ResponseEntity<Object> setDataSyncEnabledFlagForCmHandle(final String cmHandleId,
-                                                                final Boolean dataSyncEnabledFlag) {
+                                                                    final Boolean dataSyncEnabledFlag) {
         networkCmProxyDataService.setDataSyncEnabled(cmHandleId, dataSyncEnabledFlag);
         return new ResponseEntity<>(HttpStatus.OK);
     }
@@ -345,15 +301,6 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
         return restOutputCmHandle;
     }
 
-    private static boolean isValidTopic(final String topicName) {
-        if (topicName == null) {
-            return false;
-        }
-        if (CpsValidator.validateTopicName(topicName)) {
-            return true;
-        }
-        throw new InvalidTopicException("Topic name " + topicName + " is invalid", "invalid topic");
-    }
 
 }
 
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/DatastoreType.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/DatastoreType.java
new file mode 100644 (file)
index 0000000..959c85d
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  ============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.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import lombok.Getter;
+
+@Getter
+public enum DatastoreType {
+
+    OPERATIONAL("ncmp-datastore:operational"),
+    PASSTHROUGH_RUNNING("ncmp-datastore:passthrough-running"),
+    PASSTHROUGH_OPERATIONAL("ncmp-datastore:passthrough-operational");
+
+    DatastoreType(final String datastoreName) {
+        this.datastoreName = datastoreName;
+    }
+
+    private final String datastoreName;
+    private static final Map<String, DatastoreType> datastoreNameToDatastoreType = new HashMap<>();
+
+    static {
+        Arrays.stream(DatastoreType.values()).forEach(
+                type -> datastoreNameToDatastoreType.put(type.getDatastoreName(), type));
+    }
+
+    public static DatastoreType fromDatastoreName(final String datastoreName) {
+        return datastoreNameToDatastoreType.get(datastoreName);
+    }
+
+}
+
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
new file mode 100644 (file)
index 0000000..6ed9b8c
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *  ============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 NcmpDatastoreResourceRequestHandler {
+
+    public NcmpDatastoreOperationalResourceRequestHandler(final NetworkCmProxyDataService networkCmProxyDataService,
+                                                          final CpsNcmpTaskExecutor cpsNcmpTaskExecutor,
+                                                          final int timeOutInMilliSeconds,
+                                                          final boolean notificationFeatureEnabled) {
+        super(networkCmProxyDataService, cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
+    }
+
+    @Override
+    public Supplier<Object> getTask(final String cmHandle,
+                                    final String resourceIdentifier,
+                                    final String optionsParamInQuery,
+                                    final String topicParamInQuery,
+                                    final String requestId,
+                                    final Boolean includeDescendant) {
+
+        final FetchDescendantsOption fetchDescendantsOption =
+                Boolean.TRUE.equals(includeDescendant) ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
+                        : FetchDescendantsOption.OMIT_DESCENDANTS;
+
+        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
new file mode 100644 (file)
index 0000000..196e5bd
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  ============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 NcmpDatastoreResourceRequestHandler {
+
+    public NcmpDatastorePassthroughOperationalResourceRequestHandler(
+            final NetworkCmProxyDataService networkCmProxyDataService,
+            final CpsNcmpTaskExecutor cpsNcmpTaskExecutor,
+            final int timeOutInMilliSeconds,
+            final boolean notificationFeatureEnabled) {
+        super(networkCmProxyDataService, cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
+    }
+
+    @Override
+    public Supplier<Object> getTask(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
new file mode 100644 (file)
index 0000000..5bf16b7
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  ============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 NcmpDatastoreResourceRequestHandler {
+
+    public NcmpDatastorePassthroughRunningResourceRequestHandler(
+            final NetworkCmProxyDataService networkCmProxyDataService,
+            final CpsNcmpTaskExecutor cpsNcmpTaskExecutor,
+            final int timeOutInMilliSeconds,
+            final boolean notificationFeatureEnabled) {
+        super(networkCmProxyDataService, cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
+    }
+
+    @Override
+    public Supplier<Object> getTask(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);
+    }
+}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandler.java
new file mode 100644 (file)
index 0000000..a6d313b
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ *  ============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.Map;
+import java.util.UUID;
+import java.util.function.Supplier;
+import lombok.RequiredArgsConstructor;
+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.springframework.http.ResponseEntity;
+
+@RequiredArgsConstructor
+@Slf4j
+public abstract class NcmpDatastoreResourceRequestHandler {
+
+    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> getTask(final String cmHandle,
+                                                final String resourceIdentifier,
+                                                final String optionsParamInQuery,
+                                                final String topicParamInQuery,
+                                                final String requestId,
+                                                final Boolean includeDescendant);
+
+
+    /**
+     * Get resource data from datastore.
+     *
+     * @param cmHandleId          the cm handle
+     * @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> getResourceData(final String cmHandleId,
+                                                  final String resourceIdentifier,
+                                                  final String optionsParamInQuery,
+                                                  final String topicParamInQuery,
+                                                  final Boolean includeDescendants) {
+
+        final String requestId = UUID.randomUUID().toString();
+        final boolean asyncResponseRequested = topicParamInQuery != null;
+
+        if (asyncResponseRequested && notificationFeatureEnabled) {
+            TopicValidator.validateTopicName(topicParamInQuery);
+            log.debug("Received Async request with id {}", requestId);
+            cpsNcmpTaskExecutor.executeTask(
+                    getTask(cmHandleId, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId,
+                            includeDescendants), timeOutInMilliSeconds);
+
+            return ResponseEntity.ok(Map.of("requestId", requestId));
+        }
+
+        if (asyncResponseRequested) {
+            log.warn("Asynchronous messaging is currently disabled, will use synchronous operation.");
+        }
+        
+        final Object responseObject =
+                getTask(cmHandleId, resourceIdentifier, optionsParamInQuery, NO_TOPIC, NO_REQUEST_ID,
+                        includeDescendants).get();
+
+        return ResponseEntity.ok(responseObject);
+    }
+}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactory.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactory.java
new file mode 100644 (file)
index 0000000..35bd578
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  ============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 lombok.RequiredArgsConstructor;
+import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
+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 CpsNcmpTaskExecutor cpsNcmpTaskExecutor;
+
+    @Value("${notification.async.executor.time-out-value-in-ms:2000}")
+    private int timeOutInMilliSeconds;
+    @Value("${notification.enabled:true}")
+    private boolean notificationFeatureEnabled;
+
+    /**
+     * Gets ncmp datastore handler.
+     *
+     * @param datastoreType the datastore type
+     * @return the ncmp datastore handler
+     */
+    public NcmpDatastoreResourceRequestHandler getNcmpDatastoreResourceRequestHandler(
+            final DatastoreType datastoreType) {
+
+        switch (datastoreType) {
+            case OPERATIONAL:
+                return new NcmpDatastoreOperationalResourceRequestHandler(networkCmProxyDataService,
+                        cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
+            case PASSTHROUGH_RUNNING:
+                return new NcmpDatastorePassthroughRunningResourceRequestHandler(networkCmProxyDataService,
+                        cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
+            case PASSTHROUGH_OPERATIONAL:
+                return new NcmpDatastorePassthroughOperationalResourceRequestHandler(networkCmProxyDataService,
+                        cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
+            default:
+                return null;
+        }
+    }
+}
index c723733..98d7f6f 100755 (executable)
@@ -25,7 +25,6 @@ import lombok.NoArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.impl.exception.DmiRequestException;
 import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException;
-import org.onap.cps.ncmp.api.impl.exception.InvalidTopicException;
 import org.onap.cps.ncmp.api.impl.exception.NcmpException;
 import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException;
 import org.onap.cps.ncmp.rest.controller.NetworkCmProxyController;
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/TopicValidator.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/TopicValidator.java
new file mode 100644 (file)
index 0000000..313e7bc
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *  ============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.util;
+
+import java.util.regex.Pattern;
+import org.onap.cps.ncmp.rest.exceptions.InvalidTopicException;
+
+public class TopicValidator {
+
+    private static final Pattern TOPIC_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9]([._-](?![._-])|"
+        + "[a-zA-Z0-9]){0,120}[a-zA-Z0-9]$");
+
+    /**
+     * Validate kafka topic name pattern.
+     *
+     * @param topicName name of the topic to be validated
+     *
+     * @throws InvalidTopicException if the topic is not valid
+     */
+    public static void validateTopicName(final String topicName) {
+        if (!TOPIC_NAME_PATTERN.matcher(topicName).matches()) {
+            throw new InvalidTopicException("Topic name " + topicName + " is invalid", "invalid topic");
+        }
+    }
+
+}
index d568a5a..6e461fa 100644 (file)
 
 package org.onap.cps.ncmp.rest.controller
 
+import com.fasterxml.jackson.databind.ObjectMapper
 import org.mapstruct.factory.Mappers
+import org.onap.cps.TestUtils
+import org.onap.cps.ncmp.api.NetworkCmProxyDataService
 import org.onap.cps.ncmp.api.inventory.CmHandleState
 import org.onap.cps.ncmp.api.inventory.CompositeState
-import org.onap.cps.ncmp.api.inventory.LockReasonCategory
 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.mapper.CmHandleStateMapper
+import org.onap.cps.ncmp.rest.controller.handlers.DatastoreType
+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.NcmpDatastoreResourceRequestHandlerFactory
 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.model.ModuleDefinition
+import org.onap.cps.spi.model.ModuleReference
+import org.onap.cps.utils.JsonObjectMapper
+import org.spockframework.spring.SpringBean
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.beans.factory.annotation.Value
+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 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.impl.operations.DmiRequestBody.OperationEnum.PATCH
 import static org.onap.cps.ncmp.api.inventory.CompositeState.DataStores
 import static org.onap.cps.ncmp.api.inventory.CompositeState.Operational
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put
 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 com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.TestUtils
-import org.onap.cps.spi.model.ModuleReference
-import org.onap.cps.utils.JsonObjectMapper
-import org.onap.cps.ncmp.api.NetworkCmProxyDataService
-import org.spockframework.spring.SpringBean
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.beans.factory.annotation.Value
-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 spock.lang.Specification
+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
 
 @WebMvcTest(NetworkCmProxyController)
 class NetworkCmProxyControllerSpec extends Specification {
 
+    public static final int TIMEOUT_IN_MS = 2000
+    public static final boolean NOTIFICATION_ENABLED = true
+
     @Autowired
     MockMvc mvc
 
@@ -92,6 +100,9 @@ class NetworkCmProxyControllerSpec extends Specification {
     @SpringBean
     DeprecationHelper stubbedDeprecationHelper = Stub()
 
+    @SpringBean
+    NcmpDatastoreResourceRequestHandlerFactory stubbedNcmpDatastoreResourceRequestHandlerFactory = Stub()
+
     @Value('${rest.api.ncmp-base-path}/v1')
     def ncmpBasePathV1
 
@@ -104,21 +115,38 @@ class NetworkCmProxyControllerSpec extends Specification {
     def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
         .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.getNcmpDatastoreResourceRequestHandler(
+            DatastoreType.PASSTHROUGH_OPERATIONAL) >>
+            new NcmpDatastorePassthroughOperationalResourceRequestHandler(
+                mockNetworkCmProxyDataService, spiedCpsTaskExecutor, TIMEOUT_IN_MS, NOTIFICATION_ENABLED)
+
+        stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceRequestHandler(
+            DatastoreType.PASSTHROUGH_RUNNING) >>
+            new NcmpDatastorePassthroughRunningResourceRequestHandler(
+                mockNetworkCmProxyDataService, spiedCpsTaskExecutor, TIMEOUT_IN_MS, NOTIFICATION_ENABLED)
+    }
+
     def 'Get Resource Data from pass-through operational.'() {
         given: 'resource data url'
             def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-operational" +
-                    "?resourceIdentifier=parent/child&options=(a=1,b=2)"
+                "?resourceIdentifier=parent/child&options=(a=1,b=2)"
         when: 'get data resource request is performed'
             def response = mvc.perform(
-                    get(getUrl)
-                            .contentType(MediaType.APPLICATION_JSON)
+                get(getUrl)
+                    .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)
+                'parent/child',
+                '(a=1,b=2)',
+                NO_TOPIC,
+                NO_REQUEST_ID)
         and: 'response status is Ok'
             response.status == HttpStatus.OK.value()
     }
@@ -126,22 +154,22 @@ class NetworkCmProxyControllerSpec extends Specification {
     def 'Get Resource Data from #datastoreInUrl with #scenario.'() {
         given: 'resource data url'
             def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:${datastoreInUrl}" +
-                    "?resourceIdentifier=parent/child&options=(a=1,b=2)${topicQueryParam}"
+                "?resourceIdentifier=parent/child&options=(a=1,b=2)${topicQueryParam}"
         when: 'get data resource request is performed'
             def response = mvc.perform(
-                    get(getUrl).contentType(MediaType.APPLICATION_JSON)).andReturn().response
+                get(getUrl).contentType(MediaType.APPLICATION_JSON)).andReturn().response
         then: 'task executor is called appropriate number of times'
-            expectedNumberOfExecutorExecutions * spiedCpsTaskExecutor.executeTask(_, 2000)
+            expectedNumberOfExecutorExecutions * spiedCpsTaskExecutor.executeTask(_, TIMEOUT_IN_MS)
         and: 'response status is expected'
             response.status == HttpStatus.OK.value()
         where: 'the following parameters are used'
-            scenario                               | datastoreInUrl            | topicQueryParam        || expectedTopicName | expectedNumberOfExecutorExecutions
-            'url with valid topic'                 | 'passthrough-operational' | '&topic=my-topic-name' || 'my-topic-name'   | 1
-            'no topic in url'                      | 'passthrough-operational' | ''                     || NO_TOPIC          | 0
-            'null topic in url'                    | 'passthrough-operational' | '&topic=null'          || 'null'            | 1
-            'url with valid topic'                 | 'passthrough-running'     | '&topic=my-topic-name' || 'my-topic-name'   | 1
-            'no topic in url'                      | 'passthrough-running'     | ''                     || NO_TOPIC          | 0
-            'null topic in url'                    | 'passthrough-running'     | '&topic=null'          || 'null'            | 1
+            scenario               | datastoreInUrl            | topicQueryParam        || expectedTopicName | expectedNumberOfExecutorExecutions
+            'url with valid topic' | 'passthrough-operational' | '&topic=my-topic-name' || 'my-topic-name'   | 1
+            'no topic in url'      | 'passthrough-operational' | ''                     || NO_TOPIC          | 0
+            'null topic in url'    | 'passthrough-operational' | '&topic=null'          || 'null'            | 1
+            'url with valid topic' | 'passthrough-running'     | '&topic=my-topic-name' || 'my-topic-name'   | 1
+            'no topic in url'      | 'passthrough-running'     | ''                     || NO_TOPIC          | 0
+            'null topic in url'    | 'passthrough-running'     | '&topic=null'          || 'null'            | 1
     }
 
     def 'Fail to get Resource Data from #datastoreInUrl when #scenario.'() {
@@ -168,17 +196,17 @@ class NetworkCmProxyControllerSpec extends Specification {
     def 'Get Resource Data from pass-through running with #scenario value in resource identifier param.'() {
         given: 'resource data url'
             def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
-                    "?resourceIdentifier=" + resourceIdentifier + "&options=(a=1,b=2)"
+                "?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}'
+                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)
-                            .contentType(MediaType.APPLICATION_JSON)
+                get(getUrl)
+                    .contentType(MediaType.APPLICATION_JSON)
             ).andReturn().response
         then: 'response status is Ok'
             response.status == HttpStatus.OK.value()
@@ -194,7 +222,7 @@ class NetworkCmProxyControllerSpec extends Specification {
             '? needs to be encoded as %3F' | 'idWith%3F'
     }
 
-    def 'Update resource data from pass-through running.' () {
+    def 'Update resource data from pass-through running.'() {
         given: 'update resource data url'
             def updateUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
                 "?resourceIdentifier=parent/child"
@@ -210,15 +238,15 @@ class NetworkCmProxyControllerSpec extends Specification {
             response.status == HttpStatus.OK.value()
     }
 
-    def 'Create Resource Data from pass-through running with #scenario.' () {
+    def 'Create Resource Data from pass-through running with #scenario.'() {
         given: 'resource data url'
             def url = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
-                    "?resourceIdentifier=parent/child"
+                "?resourceIdentifier=parent/child"
             def requestBody = '{"some-key":"some-value"}'
         when: 'create resource request is performed'
             def response = mvc.perform(
-                    post(url)
-                            .contentType(MediaType.APPLICATION_JSON_VALUE).content(requestBody)
+                post(url)
+                    .contentType(MediaType.APPLICATION_JSON_VALUE).content(requestBody)
             ).andReturn().response
         then: 'ncmp service method to create resource called'
             1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
@@ -227,14 +255,14 @@ class NetworkCmProxyControllerSpec extends Specification {
             response.status == HttpStatus.CREATED.value()
     }
 
-    def 'Get module references for the given dataspace and cm handle.' () {
+    def 'Get module references for the given dataspace and cm handle.'() {
         given: 'get module references url'
             def getUrl = "$ncmpBasePathV1/ch/some-cmhandle/modules"
         when: 'get module resource request is performed'
-            def response =mvc.perform(get(getUrl)).andReturn().response
+            def response = mvc.perform(get(getUrl)).andReturn().response
         then: 'ncmp service method to get yang resource module references is called'
             mockNetworkCmProxyDataService.getYangResourcesModuleReferences('some-cmhandle')
-                    >> [new ModuleReference(moduleName: 'some-name1',revision: '2021-10-03')]
+                >> [new ModuleReference(moduleName: 'some-name1', revision: '2021-10-03')]
         and: 'response contains an array with the module name and revision'
             response.getContentAsString() == '[{"moduleName":"some-name1","revision":"2021-10-03"}]'
         and: 'response returns an OK http code'
@@ -248,15 +276,15 @@ class NetworkCmProxyControllerSpec extends Specification {
         and: 'the service method is invoked with module names and returns two cm handles'
             def cmHandle1 = new NcmpServiceCmHandle()
             cmHandle1.cmHandleId = 'some-cmhandle-id1'
-            cmHandle1.publicProperties = [color:'yellow']
+            cmHandle1.publicProperties = [color: 'yellow']
             def cmHandle2 = new NcmpServiceCmHandle()
             cmHandle2.cmHandleId = 'some-cmhandle-id2'
-            cmHandle2.publicProperties = [color:'green']
+            cmHandle2.publicProperties = [color: 'green']
             mockNetworkCmProxyDataService.executeCmHandleSearch(_) >> [cmHandle1, cmHandle2]
         when: 'the searches api is invoked'
             def response = mvc.perform(post(searchesEndpoint)
-                    .contentType(MediaType.APPLICATION_JSON)
-                    .content(jsonString)).andReturn().response
+                .contentType(MediaType.APPLICATION_JSON)
+                .content(jsonString)).andReturn().response
         then: 'response status returns OK'
             response.status == HttpStatus.OK.value()
         and: 'the expected response content is returned'
@@ -268,14 +296,15 @@ class NetworkCmProxyControllerSpec extends Specification {
             def cmHandleDetailsEndpoint = "$ncmpBasePathV1/ch/some-cm-handle"
         and: 'an existing ncmp service cm handle'
             def cmHandleId = 'some-cm-handle'
-            def dmiProperties = [ prop:'some DMI property' ]
-            def publicProperties = [ "public prop":'some public property' ]
+            def dmiProperties = [prop: 'some DMI property']
+            def publicProperties = ["public prop": 'some public property']
             def compositeState = compositeStateTestObject()
             def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState)
         and: 'the service method is invoked with the cm handle id'
             1 * mockNetworkCmProxyDataService.getNcmpServiceCmHandle('some-cm-handle') >> ncmpServiceCmHandle
         when: 'the cm handle details api is invoked'
-            def response = mvc.perform(get(cmHandleDetailsEndpoint)).andReturn().response
+            def response = mvc.perform(
+                get(cmHandleDetailsEndpoint)).andReturn().response
         then: 'the correct response is returned'
             response.status == HttpStatus.OK.value()
         and: 'the response contains the public properties'
@@ -286,30 +315,34 @@ class NetworkCmProxyControllerSpec extends Specification {
             !response.contentAsString.contains("some DMI property")
     }
 
-    def 'Get Cm Handle public properties by Cm Handle id.' () {
+    def 'Get Cm Handle public properties by Cm Handle id.'() {
         given: 'a cm handle properties endpoint'
             def cmHandlePropertiesEndpoint = "$ncmpBasePathV1/ch/some-cm-handle/properties"
         and: 'some cm handle public properties'
-            def publicProperties =  [ 'public prop':'some public property' ]
+            def publicProperties = ['public prop': 'some public property']
         and: 'the service method is invoked with the cm handle id returning the cm handle public properties'
-            1 * mockNetworkCmProxyDataService.getCmHandlePublicProperties('some-cm-handle') >> publicProperties
+            1 * mockNetworkCmProxyDataService
+                .getCmHandlePublicProperties('some-cm-handle') >> publicProperties
         when: 'the cm handle properties api is invoked'
-            def response = mvc.perform(get(cmHandlePropertiesEndpoint)).andReturn().response
+            def response = mvc.perform(
+                get(cmHandlePropertiesEndpoint)).andReturn().response
         then: 'the correct response is returned'
             response.status == HttpStatus.OK.value()
         and: 'the response contains the public properties'
             assertContainsPublicProperties(response)
     }
 
-    def 'Get Cm Handle composite state by Cm Handle id.' () {
+    def 'Get Cm Handle composite state by Cm Handle id.'() {
         given: 'a cm handle state endpoint'
             def cmHandlePropertiesEndpoint = "$ncmpBasePathV1/ch/some-cm-handle/state"
         and: 'some cm handle composite state'
             def compositeState = compositeStateTestObject()
         and: 'the service method is invoked with the cm handle id returning the cm handle composite state'
-            1 * mockNetworkCmProxyDataService.getCmHandleCompositeState('some-cm-handle') >> compositeState
+            1 * mockNetworkCmProxyDataService
+                .getCmHandleCompositeState('some-cm-handle') >> compositeState
         when: 'the cm handle state api is invoked'
-            def response = mvc.perform(get(cmHandlePropertiesEndpoint)).andReturn().response
+            def response = mvc.perform(
+                get(cmHandlePropertiesEndpoint)).andReturn().response
         then: 'the correct response is returned'
             response.status == HttpStatus.OK.value()
         and: 'the response contains the cm handle state'
@@ -323,13 +356,14 @@ class NetworkCmProxyControllerSpec extends Specification {
         and: 'the service method is invoked with module names and returns two cm handles'
             def cmHandel1 = new NcmpServiceCmHandle()
             cmHandel1.cmHandleId = 'some-cmhandle-id1'
-            cmHandel1.publicProperties = [color:'yellow']
+            cmHandel1.publicProperties = [color: 'yellow']
             def cmHandel2 = new NcmpServiceCmHandle()
             cmHandel2.cmHandleId = 'some-cmhandle-id2'
-            cmHandel2.publicProperties = [color:'green']
+            cmHandel2.publicProperties = [color: 'green']
             mockNetworkCmProxyDataService.executeCmHandleSearch(_) >> [cmHandel1, cmHandel2]
         when: 'the searches api is invoked'
-            def response = mvc.perform(post(searchesEndpoint)
+            def response = mvc.perform(
+                post(searchesEndpoint)
                     .contentType(MediaType.APPLICATION_JSON)
                     .content(jsonString)).andReturn().response
         then: 'an empty cm handle identifier is returned'
@@ -342,9 +376,10 @@ class NetworkCmProxyControllerSpec extends Specification {
         and: 'the service method is invoked with module names and returns cm handle ids'
             1 * mockNetworkCmProxyDataService.executeCmHandleIdSearch(_) >> ['some-cmhandle-id1', 'some-cmhandle-id2']
         when: 'the searches api is invoked'
-            def response = mvc.perform(post(searchesEndpoint)
-                .contentType(MediaType.APPLICATION_JSON)
-                .content('{}')).andReturn().response
+            def response = mvc.perform(
+                post(searchesEndpoint)
+                    .contentType(MediaType.APPLICATION_JSON)
+                    .content('{}')).andReturn().response
         then: 'cm handle ids are returned'
             response.contentAsString == '["some-cmhandle-id1","some-cmhandle-id2"]'
     }
@@ -353,37 +388,39 @@ class NetworkCmProxyControllerSpec extends Specification {
         when: 'the searches api is invoked'
             def searchesEndpoint = "$ncmpBasePathV1/ch/id-searches"
             def invalidInputData = '{invalidJson}'
-            def response = mvc.perform(post(searchesEndpoint)
+            def response = mvc.perform(
+                post(searchesEndpoint)
                     .contentType(MediaType.APPLICATION_JSON)
                     .content(invalidInputData)).andReturn().response
         then: 'BAD_REQUEST is returned'
             response.getStatus() == 400
     }
 
-    def 'Patch resource data in pass-through running datastore.' () {
+    def 'Patch resource data in pass-through running datastore.'() {
         given: 'patch resource data url'
             def url = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
-                    "?resourceIdentifier=parent/child"
+                "?resourceIdentifier=parent/child"
         when: 'patch data resource request is performed'
             def response = mvc.perform(
-                    patch(url)
-                            .contentType(MediaType.APPLICATION_JSON)
-                            .accept(MediaType.APPLICATION_JSON).content(requestBody)
+                patch(url)
+                    .contentType(MediaType.APPLICATION_JSON)
+                    .accept(MediaType.APPLICATION_JSON).content(requestBody)
             ).andReturn().response
         then: 'ncmp service method to update resource is called'
             1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
-                    'parent/child', PATCH, requestBody, 'application/json;charset=UTF-8')
+                'parent/child', PATCH, requestBody, 'application/json;charset=UTF-8')
         and: 'the response status is OK'
             response.status == HttpStatus.OK.value()
     }
 
-    def 'Delete resource data in pass-through running datastore.' () {
+    def 'Delete resource data in pass-through running datastore.'() {
         given: 'delete resource data url'
             def url = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
-                     "?resourceIdentifier=parent/child"
+                "?resourceIdentifier=parent/child"
         when: 'delete data resource request is performed'
             def response = mvc.perform(
-                delete(url).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)).andReturn().response
+                delete(url)
+                    .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)).andReturn().response
         then: 'the ncmp service method to delete resource is called (with null as body)'
             1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
                 'parent/child', DELETE, null, 'application/json;charset=UTF-8')
@@ -394,12 +431,12 @@ class NetworkCmProxyControllerSpec extends Specification {
     def 'Get resource data from DMI with valid topic i.e. async request for #scenario'() {
         given: 'resource data url'
             def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:${datastoreInUrl}" +
-                    "?resourceIdentifier=parent/child&options=(a=1,b=2)&topic=my-topic-name"
+                "?resourceIdentifier=parent/child&options=(a=1,b=2)&topic=my-topic-name"
         when: 'get data resource request is performed'
             def response = mvc.perform(
-                    get(getUrl)
-                            .contentType(MediaType.APPLICATION_JSON)
-                            .accept(MediaType.APPLICATION_JSON_VALUE)
+                get(getUrl)
+                    .contentType(MediaType.APPLICATION_JSON)
+                    .accept(MediaType.APPLICATION_JSON_VALUE)
             ).andReturn().response
         then: 'async request id is generated'
             assert response.contentAsString.contains("requestId")
@@ -409,32 +446,68 @@ class NetworkCmProxyControllerSpec extends Specification {
             ':passthrough-running'     | 'passthrough-running'
     }
 
-    def 'Get module definitions based on cmHandleId.' () {
+    def 'Get module definitions based on cmHandleId.'() {
         when: 'get module definition request is performed'
-            def response = mvc.perform(get("$ncmpBasePathV1/ch/some-cmhandle/modules/definitions"))
-                    .andReturn().response
+            def response = mvc.perform(
+                get("$ncmpBasePathV1/ch/some-cmhandle/modules/definitions"))
+                .andReturn().response
         then: 'ncmp service method to get module definitions is called'
             mockNetworkCmProxyDataService.getModuleDefinitionsByCmHandleId('some-cmhandle')
-                    >> [new ModuleDefinition('sampleModuleName', '2021-10-03',
-                    'module sampleModuleName{ sample module content }')]
+                >> [new ModuleDefinition('sampleModuleName', '2021-10-03',
+                'module sampleModuleName{ sample module content }')]
         and: 'response contains an array with the module name, revision and content'
             response.getContentAsString() == '[{"moduleName":"sampleModuleName","revision":"2021-10-03","content":"module sampleModuleName{ sample module content }"}]'
         and: 'response returns an OK http code'
             response.status == HttpStatus.OK.value()
     }
 
-    def 'Set the data sync enabled based on the cm handle id and the data sync flag is #scenario' () {
+    def 'Set the data sync enabled based on the cm handle id and the data sync flag is #scenario'() {
         when: 'the set data sync enabled request is invoked'
-            def response = mvc.perform(put("$ncmpBasePathV1/ch/some-cm-handle-id/data-sync?dataSyncEnabled=" + dataSyncEnabledFlag))
-                    .andReturn().response
+            def response = mvc.perform(
+                put("$ncmpBasePathV1/ch/some-cm-handle-id/data-sync?dataSyncEnabled=" + dataSyncEnabledFlag))
+                .andReturn().response
         then: 'method to set data sync enabled is called'
             1 * mockNetworkCmProxyDataService.setDataSyncEnabled('some-cm-handle-id', dataSyncEnabledFlag)
         and: 'the response returns an OK http code'
             response.status == HttpStatus.OK.value()
         where: 'the following parameters are used'
-        scenario     |  dataSyncEnabledFlag
-        'enabled'    |  true
-        'disabled'   |  false
+            scenario   | dataSyncEnabledFlag
+            'enabled'  | true
+            'disabled' | false
+    }
+
+    def 'Get Resource Data from operational without descendants.'() {
+        given: 'resource data url'
+            def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:operational" +
+                "?resourceIdentifier=parent/child&include-descendants=false"
+        when: 'get data resource request is performed'
+            def response = mvc.perform(
+                get(getUrl)
+                    .contentType(MediaType.APPLICATION_JSON)
+            ).andReturn().response
+        then: 'the NCMP data service is called with getResourceDataOperational'
+            1 * mockNetworkCmProxyDataService.getResourceDataOperational('testCmHandle',
+                'parent/child',
+                FetchDescendantsOption.OMIT_DESCENDANTS)
+        and: 'response status is Ok'
+            response.status == HttpStatus.OK.value()
+    }
+
+    def 'Get Resource Data from operational including descendants.'() {
+        given: 'resource data url'
+            def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:operational" +
+                "?resourceIdentifier=parent/child&include-descendants=true"
+        when: 'get data resource request is performed'
+            def response = mvc.perform(
+                get(getUrl)
+                    .contentType(MediaType.APPLICATION_JSON)
+            ).andReturn().response
+        then: 'the NCMP data service is called with getResourceDataOperational'
+            1 * mockNetworkCmProxyDataService.getResourceDataOperational('testCmHandle',
+                'parent/child',
+                FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
+        and: 'response status is Ok'
+            response.status == HttpStatus.OK.value()
     }
 
     def dataStores() {
@@ -453,7 +526,7 @@ class NetworkCmProxyControllerSpec extends Specification {
     }
 
     def assertContainsAll(response, assertContent) {
-        assertContent.forEach( string -> { assert(response.contentAsString.contains(string)) })
+        assertContent.forEach(string -> { assert (response.contentAsString.contains(string)) })
         return void
     }
 
@@ -476,8 +549,8 @@ class NetworkCmProxyControllerSpec extends Specification {
 
     def assertContainsPublicProperties(response) {
         def expectedContent = [
-            '"publicCmHandleProperties":' ,
-            '"public prop"' ,
+            '"publicCmHandleProperties":',
+            '"public prop"',
             '"some public property"'
         ]
         return assertContainsAll(response, expectedContent)
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactorySpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactorySpec.groovy
new file mode 100644 (file)
index 0000000..3f7a8a5
--- /dev/null
@@ -0,0 +1,20 @@
+package org.onap.cps.ncmp.rest.controller.handlers
+
+import spock.lang.Specification
+
+class NcmpDatastoreResourceRequestHandlerFactorySpec extends Specification {
+
+    def objectUnderTest = new NcmpDatastoreResourceRequestHandlerFactory(null, null)
+
+    def 'Creating ncmp datastore request handlers.'() {
+        when: 'a ncmp datastore request handler is created for #datastoreType'
+            def result = objectUnderTest.getNcmpDatastoreResourceRequestHandler(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
+    }
+}
\ No newline at end of file
index ce908e7..b8b7fe3 100644 (file)
@@ -29,8 +29,9 @@ import org.onap.cps.ncmp.api.impl.exception.DmiRequestException
 import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException
 import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException
 import org.onap.cps.ncmp.rest.controller.NcmpRestInputMapper
-import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper
+import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreResourceRequestHandlerFactory
 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.exceptions.CpsException
 import org.onap.cps.spi.exceptions.DataNodeNotFoundException
@@ -48,9 +49,7 @@ import spock.lang.Specification
 
 import static org.onap.cps.ncmp.rest.exceptions.NetworkCmProxyRestExceptionHandlerSpec.ApiType.NCMP
 import static org.onap.cps.ncmp.rest.exceptions.NetworkCmProxyRestExceptionHandlerSpec.ApiType.NCMPINVENTORY
-import static org.springframework.http.HttpStatus.BAD_REQUEST
-import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR
-import static org.springframework.http.HttpStatus.NOT_FOUND
+import static org.springframework.http.HttpStatus.*
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
 
@@ -78,6 +77,9 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification {
     @SpringBean
     DeprecationHelper stubbedDeprecationHelper = Stub()
 
+    @SpringBean
+    NcmpDatastoreResourceRequestHandlerFactory mockedNcmpDatastoreResourceRequestHandlerFactory = Mock()
+
     @Value('${rest.api.ncmp-base-path}')
     def basePathNcmp
 
@@ -125,7 +127,7 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification {
 
     def 'Failing DMI Request - passthrough scenario'() {
         given: 'failing DMI request'
-            setupTestException(new HttpClientRequestException('Error Message Details NCMP', 'Bad Request from DMI', 400) , NCMP)
+            setupTestException(new HttpClientRequestException('Error Message Details NCMP', 'Bad Request from DMI', 400), NCMP)
         when: 'the DMI request is executed'
             def response = performTestRequest(NCMP)
         then: 'NCMP service responds with 502 Bad Gateway status'
@@ -150,7 +152,7 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification {
         return mvc.perform(post("$dataNodeBaseEndpointNcmpInventory/ch").contentType(MediaType.APPLICATION_JSON).content(jsonData)).andReturn().response
     }
 
-    static void assertTestResponse(response, expectedStatus , expectedErrorMessage , expectedErrorDetails) {
+    static void assertTestResponse(response, expectedStatus, expectedErrorMessage, expectedErrorDetails) {
         assert response.status == expectedStatus.value()
         def content = new JsonSlurper().parseText(response.contentAsString)
         assert content['status'].toString().contains(expectedStatus.toString())
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/util/TopicValidatorSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/util/TopicValidatorSpec.groovy
new file mode 100644 (file)
index 0000000..e626e15
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *  ============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.util
+
+import org.onap.cps.ncmp.rest.exceptions.InvalidTopicException
+import spock.lang.Specification
+
+class TopicValidatorSpec extends Specification {
+
+    def 'Valid topic name validation.'() {
+        when: 'a valid topic name is validated'
+            TopicValidator.validateTopicName('my-valid-topic')
+        then: 'no exception is thrown'
+            noExceptionThrown()
+    }
+
+    def 'Validating invalid topic names.'() {
+        when: 'the invalid topic name is validated'
+            TopicValidator.validateTopicName(topicName)
+        then: 'boolean response will be returned for #scenario'
+            thrown(InvalidTopicException)
+        where: 'the following names are used'
+            scenario                  | topicName
+            'empty topic'             | ''
+            'blank topic'             | ' '
+            'invalid non empty topic' | '1_5_*_#'
+    }
+
+}
index 45dba21..0ea0674 100644 (file)
@@ -33,6 +33,7 @@ import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters;
 import org.onap.cps.ncmp.api.models.DmiPluginRegistration;
 import org.onap.cps.ncmp.api.models.DmiPluginRegistrationResponse;
 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
+import org.onap.cps.spi.FetchDescendantsOption;
 import org.onap.cps.spi.model.ModuleDefinition;
 import org.onap.cps.spi.model.ModuleReference;
 
@@ -66,6 +67,18 @@ public interface NetworkCmProxyDataService {
                                                  String topicParamInQuery,
                                                  String requestId);
 
+    /**
+     * Get resource data for operational.
+     *
+     * @param cmHandleId cm handle identifier
+     * @param resourceIdentifier resource identifier
+     * @Link FetchDescendantsOption fetch descendants option
+     * @return {@code Object} resource data
+     */
+    Object getResourceDataOperational(String cmHandleId,
+                                      String resourceIdentifier,
+                                      FetchDescendantsOption fetchDescendantsOption);
+
     /**
      * Get resource data for data store pass-through running
      * using dmi.
index 5b072f3..c21c74b 100755 (executable)
@@ -23,6 +23,7 @@
 
 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.utils.CmHandleQueryRestParametersValidator.validateCmHandleQueryParameters;
 
@@ -57,6 +58,7 @@ import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationErr
 import org.onap.cps.ncmp.api.models.DmiPluginRegistration;
 import org.onap.cps.ncmp.api.models.DmiPluginRegistrationResponse;
 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
+import org.onap.cps.spi.FetchDescendantsOption;
 import org.onap.cps.spi.exceptions.AlreadyDefinedException;
 import org.onap.cps.spi.exceptions.CpsException;
 import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
@@ -116,13 +118,21 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
                                                         final String topicParamInQuery,
                                                         final String requestId) {
         final ResponseEntity<?> responseEntity = dmiDataOperations.getResourceDataFromDmi(cmHandleId,
-            resourceIdentifier,
-            optionsParamInQuery,
-            DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL,
-            requestId, topicParamInQuery);
+                resourceIdentifier,
+                optionsParamInQuery,
+                DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL,
+                requestId, topicParamInQuery);
         return responseEntity.getBody();
     }
 
+    @Override
+    public Object getResourceDataOperational(final String cmHandleId,
+                                             final String resourceIdentifier,
+                                             final FetchDescendantsOption fetchDescendantsOption) {
+        return cpsDataService.getDataNode(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, resourceIdentifier,
+                fetchDescendantsOption);
+    }
+
     @Override
     public Object getResourceDataPassThroughRunningForCmHandle(final String cmHandleId,
                                                                final String resourceIdentifier,
@@ -130,10 +140,10 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
                                                                final String topicParamInQuery,
                                                                final String requestId) {
         final ResponseEntity<?> responseEntity = dmiDataOperations.getResourceDataFromDmi(cmHandleId,
-            resourceIdentifier,
-            optionsParamInQuery,
-            DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING,
-            requestId, topicParamInQuery);
+                resourceIdentifier,
+                optionsParamInQuery,
+                DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING,
+                requestId, topicParamInQuery);
         return responseEntity.getBody();
     }
 
@@ -145,7 +155,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
                                                                  final String dataType) {
         CpsValidator.validateNameCharacters(cmHandleId);
         return dmiDataOperations.writeResourceDataPassThroughRunningFromDmi(cmHandleId, resourceIdentifier, operation,
-            requestData, dataType);
+                requestData, dataType);
     }
 
     @Override
@@ -196,29 +206,29 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
      * Set the data sync enabled flag, along with the data sync state
      * based on the data sync enabled boolean for the cm handle id provided.
      *
-     * @param cmHandleId cm handle id
+     * @param cmHandleId      cm handle id
      * @param dataSyncEnabled data sync enabled flag
      */
     @Override
     public void setDataSyncEnabled(final String cmHandleId, final boolean dataSyncEnabled) {
         CpsValidator.validateNameCharacters(cmHandleId);
         final CompositeState compositeState = inventoryPersistence
-            .getCmHandleState(cmHandleId);
+                .getCmHandleState(cmHandleId);
         if (compositeState.getDataSyncEnabled().equals(dataSyncEnabled)) {
             log.info("Data-Sync Enabled flag is already: {} ", dataSyncEnabled);
         } else if (compositeState.getCmHandleState() != CmHandleState.READY) {
             throw new CpsException("State mismatch exception.", "Cm-Handle not in READY state. Cm handle state is: "
-                + compositeState.getCmHandleState());
+                    + compositeState.getCmHandleState());
         } else {
             final DataStoreSyncState dataStoreSyncState = compositeState.getDataStores()
-                .getOperationalDataStore().getDataStoreSyncState();
+                    .getOperationalDataStore().getDataStoreSyncState();
             if (!dataSyncEnabled && dataStoreSyncState == DataStoreSyncState.SYNCHRONIZED) {
-                cpsDataService.deleteDataNode("NFP-Operational", cmHandleId,
-                    "/netconf-state", OffsetDateTime.now());
+                cpsDataService.deleteDataNode(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId,
+                        "/netconf-state", OffsetDateTime.now());
             }
             CompositeStateUtils.setDataSyncEnabledFlagWithDataSyncState(dataSyncEnabled, compositeState);
             inventoryPersistence.saveCmHandleState(cmHandleId,
-                compositeState);
+                    compositeState);
         }
     }
 
@@ -262,7 +272,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
     public Map<String, String> getCmHandlePublicProperties(final String cmHandleId) {
         CpsValidator.validateNameCharacters(cmHandleId);
         final YangModelCmHandle yangModelCmHandle =
-            inventoryPersistence.getYangModelCmHandle(cmHandleId);
+                inventoryPersistence.getYangModelCmHandle(cmHandleId);
         final List<YangModelCmHandle.Property> yangModelPublicProperties = yangModelCmHandle.getPublicProperties();
         final Map<String, String> cmHandlePublicProperties = new HashMap<>();
         YangDataConverter.asPropertiesMap(yangModelPublicProperties, cmHandlePublicProperties);
@@ -292,12 +302,12 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
         List<CmHandleRegistrationResponse> cmHandleRegistrationResponses = new ArrayList<>();
         try {
             cmHandleRegistrationResponses = dmiPluginRegistration.getCreatedCmHandles().stream()
-                .map(cmHandle ->
-                    YangModelCmHandle.toYangModelCmHandle(
-                        dmiPluginRegistration.getDmiPlugin(),
-                        dmiPluginRegistration.getDmiDataPlugin(),
-                        dmiPluginRegistration.getDmiModelPlugin(),
-                        cmHandle)).map(this::registerNewCmHandle).collect(Collectors.toList());
+                    .map(cmHandle ->
+                            YangModelCmHandle.toYangModelCmHandle(
+                                    dmiPluginRegistration.getDmiPlugin(),
+                                    dmiPluginRegistration.getDmiDataPlugin(),
+                                    dmiPluginRegistration.getDmiModelPlugin(),
+                                    cmHandle)).map(this::registerNewCmHandle).collect(Collectors.toList());
         } catch (final DataValidationException dataValidationException) {
             cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createFailureResponse(dmiPluginRegistration
                             .getCreatedCmHandles().stream()
index 28b49c9..f3774d9 100644 (file)
@@ -22,7 +22,6 @@ package org.onap.cps.utils;
 
 import com.google.common.collect.Lists;
 import java.util.Collection;
-import java.util.regex.Pattern;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -33,30 +32,25 @@ import org.onap.cps.spi.exceptions.DataValidationException;
 public final class CpsValidator {
 
     private static final char[] UNSUPPORTED_NAME_CHARACTERS = "!\" #$%&'()*+,./\\:;<=>?@[]^`{|}~".toCharArray();
-    private static final Pattern TOPIC_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9]([._-](?![._-])|"
-            + "[a-zA-Z0-9]){0,120}[a-zA-Z0-9]$");
 
     /**
      * Validate characters in names within cps.
+     *
      * @param names names of data to be validated
      */
     public static void validateNameCharacters(final String... names) {
         for (final String name : names) {
-            final  Collection<Character> charactersOfName = Lists.charactersOf(name);
+            final Collection<Character> charactersOfName = Lists.charactersOf(name);
             for (final char unsupportedCharacter : UNSUPPORTED_NAME_CHARACTERS) {
                 if (charactersOfName.contains(unsupportedCharacter)) {
                     throw new DataValidationException("Name or ID Validation Error.",
-                        name + " invalid token encountered at position " + (name.indexOf(unsupportedCharacter) + 1));
+                            name + " invalid token encountered at position "
+                                    + (name.indexOf(unsupportedCharacter) + 1));
                 }
             }
         }
     }
 
-    /**
-     * Validate kafka topic name pattern.
-     * @param topicName name of the topic to be validated
-     */
-    public static boolean validateTopicName(final String topicName) {
-        return topicName != null && TOPIC_NAME_PATTERN.matcher(topicName).matches();
-    }
+
+
 }
index ce728ef..ea7a5d6 100644 (file)
@@ -25,7 +25,6 @@ import spock.lang.Specification
 
 class CpsValidatorSpec extends Specification {
 
-
     def 'Validating a valid string.'() {
         when: 'the string is validated using a valid name'
             CpsValidator.validateNameCharacters('name-with-no-spaces')
@@ -46,17 +45,4 @@ class CpsValidatorSpec extends Specification {
             'position 9' | 'nameWith Space'   || 'nameWith Space invalid token encountered at position 9'
     }
 
-    def 'Validating topic names.'() {
-        when: 'the topic name is validated'
-            def isValidTopicName = CpsValidator.validateTopicName(topicName)
-        then: 'boolean response will be returned for #scenario'
-            assert isValidTopicName == booleanResponse
-        where: 'the following names are used'
-            scenario                  | topicName       || booleanResponse
-            'valid topic'             | 'my-topic-name' || true
-            'empty topic'             | ''              || false
-            'blank topic'             | ' '             || false
-            'null topic'              | null            || false
-            'invalid non empty topic' | '1_5_*_#'       || false
-    }
 }