Define response objects(schemas) in cps-ncmp

Issue-ID: CPS-559
Signed-off-by: puthuparambil.aditya <aditya.puthuparambil@bell.ca>
Change-Id: Id181f2a1b9554118f5e7464c95e873f09fc908eb
diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml
index 719282b..d9bd49a 100644
--- a/cps-ncmp-rest/docs/openapi/components.yaml
+++ b/cps-ncmp-rest/docs/openapi/components.yaml
@@ -48,7 +48,6 @@
           type: array
           items:
             $ref: '#/components/schemas/RestCmHandle'
-          example: [my-cm-handle1, my-cm-handle2, my-cm-handle3]
         updatedCmHandles:
           type: array
           items:
@@ -121,6 +120,17 @@
           type: string
           example: my-cm-handle-id
 
+    ModuleReference:
+      type: object
+      title: Module reference details
+      properties:
+        moduleName:
+          type: string
+          example: my-module-name
+        revision:
+          type: string
+          example: my-module-revision
+
   examples:
     dataSampleRequest:
         summary: Sample request
@@ -134,7 +144,6 @@
                 books:
                 - authors:
                     - Iain M. Banks
-                - authors:
                     - Ursula K. Le Guin
               - code: '02'
                 name: kids
@@ -150,14 +159,15 @@
             categories:
               - code: '01'
                 books:
-                  - {}
-                  - {}
+                  - authors:
+                      - Iain M. Banks
+                      - Ursula K. Le Guin
                 name: SciFi
               - code: '02'
                 books:
-                  - {}
+                  - authors:
+                      - Philip Pullman
                 name: kids
-            bookstore-name: Chapters
 
   parameters:
     cmHandleInPath:
diff --git a/cps-ncmp-rest/docs/openapi/ncmp.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml
index 673eb0b..ece3c3a 100755
--- a/cps-ncmp-rest/docs/openapi/ncmp.yml
+++ b/cps-ncmp-rest/docs/openapi/ncmp.yml
@@ -82,7 +82,10 @@
       content:
         application/json:
           schema:
-            type: string
+            type: object
+          examples:
+            dataSampleRequest:
+              $ref: 'components.yaml#/components/examples/dataSampleRequest'
     responses:
       201:
         $ref: 'components.yaml#/components/responses/Created'
@@ -110,7 +113,10 @@
       content:
         application/json:
           schema:
-            type: string
+            type: object
+          examples:
+            dataSampleRequest:
+              $ref: 'components.yaml#/components/examples/dataSampleRequest'
     responses:
       200:
         $ref: 'components.yaml#/components/responses/Ok'
@@ -138,7 +144,10 @@
       content:
         application/json:
           schema:
-            type: string
+            type: object
+          examples:
+            dataSampleRequest:
+              $ref: 'components.yaml#/components/examples/dataSampleRequest'
     responses:
       200:
         $ref: 'components.yaml#/components/responses/Ok'
@@ -167,7 +176,10 @@
       content:
         application/json:
           schema:
-            type: string
+            type: object
+          examples:
+            dataSampleRequest:
+              $ref: 'components.yaml#/components/examples/dataSampleRequest'
     responses:
       201:
         $ref: 'components.yaml#/components/responses/Created'
@@ -256,13 +268,16 @@
       content:
         application/json:
           schema:
-            type: string
+            type: object
           examples:
             dataSampleRequest:
               $ref: 'components.yaml#/components/examples/dataSampleRequest'
         application/yang-data+json:
           schema:
-            type: string
+            type: object
+          examples:
+            dataSampleRequest:
+              $ref: 'components.yaml#/components/examples/dataSampleRequest'
     responses:
       201:
         $ref: 'components.yaml#/components/responses/Created'
@@ -290,13 +305,16 @@
       content:
         application/json:
           schema:
-            type: string
+            type: object
           examples:
             dataSampleRequest:
               $ref: 'components.yaml#/components/examples/dataSampleRequest'
         application/yang-data+json:
           schema:
-            type: string
+            type: object
+          examples:
+            dataSampleRequest:
+              $ref: 'components.yaml#/components/examples/dataSampleRequest'
     responses:
       200:
         $ref: 'components.yaml#/components/responses/Ok'
@@ -325,6 +343,9 @@
         application/json:
           schema:
             type: object
+          examples:
+            dataSampleRequest:
+              $ref: 'components.yaml#/components/examples/dataSampleRequest'
     responses:
       200:
         $ref: 'components.yaml#/components/responses/Ok'
@@ -352,7 +373,10 @@
       content:
         application/json:
           schema:
-            type: string
+            type: object
+          examples:
+            dataSampleRequest:
+              $ref: 'components.yaml#/components/examples/dataSampleRequest'
     responses:
       204:
         $ref: 'components.yaml#/components/responses/NoContent'
@@ -381,15 +405,9 @@
         content:
           application/json:
             schema:
-              type: object
-            examples:
-              moduleReferencesResponse:
-                summary: Sample response
-                value:
-                  - moduleName: my-module-name
-                    revision: yyyy-mm-dd
-                  - moduleName: my-module-name-2
-                    revision: yyyy-mm-dd
+              type: array
+              items:
+                $ref: 'components.yaml#/components/schemas/ModuleReference'
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
       401:
diff --git a/cps-ncmp-rest/pom.xml b/cps-ncmp-rest/pom.xml
index 0300538..93ee680 100644
--- a/cps-ncmp-rest/pom.xml
+++ b/cps-ncmp-rest/pom.xml
@@ -61,6 +61,10 @@
             <groupId>io.swagger.core.v3</groupId>
             <artifactId>swagger-annotations</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.modelmapper</groupId>
+            <artifactId>modelmapper</artifactId>
+        </dependency>
         <!-- T E S T   D E P E N D E N C I E S -->
         <dependency>
             <groupId>org.codehaus.groovy</groupId>
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
index 3b44b80..28bb28c 100755
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
@@ -37,6 +37,7 @@
 import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
 import lombok.extern.slf4j.Slf4j;
+import org.modelmapper.ModelMapper;
 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
 import org.onap.cps.ncmp.rest.api.NetworkCmProxyApi;
 import org.onap.cps.ncmp.rest.model.CmHandleProperties;
@@ -46,9 +47,9 @@
 import org.onap.cps.ncmp.rest.model.Conditions;
 import org.onap.cps.ncmp.rest.model.ModuleNameAsJsonObject;
 import org.onap.cps.ncmp.rest.model.ModuleNamesAsJsonArray;
+import org.onap.cps.ncmp.rest.model.ModuleReference;
 import org.onap.cps.spi.FetchDescendantsOption;
 import org.onap.cps.spi.model.DataNode;
-import org.onap.cps.spi.model.ModuleReference;
 import org.onap.cps.utils.DataMapUtils;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
@@ -62,6 +63,7 @@
 
     private static final Gson GSON = new GsonBuilder().create();
 
+    private final ModelMapper modelMapper = new ModelMapper();
     private final NetworkCmProxyDataService networkCmProxyDataService;
 
     /**
@@ -78,9 +80,9 @@
      */
     @Override
     @Deprecated(forRemoval = false)
-    public ResponseEntity<Void> createNode(final String cmHandle, @Valid final String jsonData,
+    public ResponseEntity<Void> createNode(final String cmHandle, @Valid final Object jsonData,
         @Valid final String parentNodeXpath) {
-        networkCmProxyDataService.createDataNode(cmHandle, parentNodeXpath, jsonData);
+        networkCmProxyDataService.createDataNode(cmHandle, parentNodeXpath, GSON.toJson(jsonData));
         return new ResponseEntity<>(HttpStatus.CREATED);
     }
 
@@ -91,8 +93,8 @@
     @Override
     @Deprecated(forRemoval = false)
     public ResponseEntity<Void> addListNodeElements(@NotNull @Valid final String parentNodeXpath,
-        final String cmHandle, @Valid final String jsonData) {
-        networkCmProxyDataService.addListNodeElements(cmHandle, parentNodeXpath, jsonData);
+        final String cmHandle, @Valid final Object jsonData) {
+        networkCmProxyDataService.addListNodeElements(cmHandle, parentNodeXpath, GSON.toJson(jsonData));
         return new ResponseEntity<>(HttpStatus.CREATED);
     }
 
@@ -131,9 +133,9 @@
      */
     @Override
     @Deprecated(forRemoval = false)
-    public ResponseEntity<Object> replaceNode(final String cmHandle, @Valid final String jsonData,
+    public ResponseEntity<Object> replaceNode(final String cmHandle, @Valid final Object jsonData,
         @Valid final String parentNodeXpath) {
-        networkCmProxyDataService.replaceNodeTree(cmHandle, parentNodeXpath, jsonData);
+        networkCmProxyDataService.replaceNodeTree(cmHandle, parentNodeXpath, GSON.toJson(jsonData));
         return new ResponseEntity<>(HttpStatus.OK);
     }
 
@@ -143,9 +145,9 @@
      */
     @Override
     @Deprecated(forRemoval = false)
-    public ResponseEntity<Object> updateNodeLeaves(final String cmHandle, @Valid final String jsonData,
+    public ResponseEntity<Object> updateNodeLeaves(final String cmHandle, @Valid final Object jsonData,
         @Valid final String parentNodeXpath) {
-        networkCmProxyDataService.updateNodeLeaves(cmHandle, parentNodeXpath, jsonData);
+        networkCmProxyDataService.updateNodeLeaves(cmHandle, parentNodeXpath, GSON.toJson(jsonData));
         return new ResponseEntity<>(HttpStatus.OK);
     }
 
@@ -196,7 +198,7 @@
         final String cmHandle,
         final Object requestBody, final String contentType) {
         networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
-            resourceIdentifier, PATCH, requestBody.toString(), contentType);
+            resourceIdentifier, PATCH, GSON.toJson(requestBody), contentType);
         return new ResponseEntity<>(HttpStatus.OK);
     }
 
@@ -211,11 +213,9 @@
      */
     @Override
     public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String resourceIdentifier,
-                                                                     final String cmHandle,
-                                                                     final String requestBody,
-                                                                     final String contentType) {
+        final String cmHandle, final Object requestBody, final String contentType) {
         networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
-                resourceIdentifier, CREATE, requestBody, contentType);
+                resourceIdentifier, CREATE, GSON.toJson(requestBody), contentType);
         return new ResponseEntity<>(HttpStatus.CREATED);
     }
 
@@ -231,10 +231,10 @@
     @Override
     public ResponseEntity<Object> updateResourceDataRunningForCmHandle(final String resourceIdentifier,
                                                                        final String cmHandle,
-                                                                       final String requestBody,
+                                                                       final Object requestBody,
                                                                        final String contentType) {
         networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
-            resourceIdentifier, UPDATE, requestBody, contentType);
+            resourceIdentifier, UPDATE, GSON.toJson(requestBody), contentType);
         return new ResponseEntity<>(HttpStatus.OK);
     }
 
@@ -251,11 +251,11 @@
     @Override
     public ResponseEntity<Void> deleteResourceDataRunningForCmHandle(final String resourceIdentifier,
                                                                      final String cmHandle,
-                                                                     final String requestBody,
+                                                                     final Object requestBody,
                                                                      final String contentType) {
 
         networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
-            resourceIdentifier, DELETE, requestBody, contentType);
+            resourceIdentifier, DELETE, GSON.toJson(requestBody), contentType);
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
 
@@ -280,11 +280,12 @@
      * @param cmHandle the cm handle
      * @return module references for cm handle
      */
-    @Override
-    public ResponseEntity<Object> getModuleReferencesByCmHandle(final String cmHandle) {
-        final Collection<ModuleReference>
-            moduleReferences = networkCmProxyDataService.getYangResourcesModuleReferences(cmHandle);
-        return new ResponseEntity<>(new Gson().toJson(moduleReferences), HttpStatus.OK);
+    public ResponseEntity<List<ModuleReference>> getModuleReferencesByCmHandle(final String cmHandle) {
+        final List<ModuleReference> moduleReferences =
+            networkCmProxyDataService.getYangResourcesModuleReferences(cmHandle).stream()
+            .map(moduleReference -> modelMapper.map(moduleReference, ModuleReference.class))
+                .collect(Collectors.toList());
+        return new ResponseEntity<>(moduleReferences, HttpStatus.OK);
     }
 
     private Collection<String> processConditions(final List<ConditionProperties> conditionProperties) {
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
index 530ce4e..c75418c 100644
--- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
+++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
@@ -63,6 +63,7 @@
 
     def cmHandle = 'some handle'
     def xpath = 'some xpath'
+    def jsonString = '{"some-key":"some-value"}'
 
     def 'Query data node by cps path for the given cm handle with #scenario.'() {
         given: 'service method returns a list containing a data node'
@@ -88,17 +89,15 @@
     }
 
     def 'Create data node: #scenario.'() {
-        given: 'json data'
-            def jsonData = 'json data'
         when: 'post request is performed'
             def response = mvc.perform(
                     post("$ncmpBasePathV1/cm-handles/$cmHandle/nodes")
                             .contentType(MediaType.APPLICATION_JSON)
-                            .content(jsonData)
+                            .content(jsonString)
                             .param('xpath', reqXpath)
             ).andReturn().response
         then: 'the service method is invoked once with expected parameters'
-            1 * mockNetworkCmProxyDataService.createDataNode(cmHandle, usedXpath, jsonData)
+            1 * mockNetworkCmProxyDataService.createDataNode(cmHandle, usedXpath, jsonString)
         and: 'response status indicates success'
             response.status == HttpStatus.CREATED.value()
         where: 'following parameters were used'
@@ -109,54 +108,49 @@
     }
 
     def 'Add list-node elements.'() {
-        given: 'json data and parent node xpath'
-            def jsonData = 'json data'
+        given: ' parent node xpath'
             def parentNodeXpath = 'parent node xpath'
         when: 'post request is performed'
             def response = mvc.perform(
                     post("$ncmpBasePathV1/cm-handles/$cmHandle/list-node")
                             .contentType(MediaType.APPLICATION_JSON)
-                            .content(jsonData)
+                            .content(jsonString)
                             .param('xpath', parentNodeXpath)
             ).andReturn().response
         then: 'the service method is invoked once with expected parameters'
-            1 * mockNetworkCmProxyDataService.addListNodeElements(cmHandle, parentNodeXpath, jsonData)
+            1 * mockNetworkCmProxyDataService.addListNodeElements(cmHandle, parentNodeXpath, jsonString)
         and: 'response status indicates success'
             response.status == HttpStatus.CREATED.value()
     }
 
     def 'Update data node leaves.'() {
-        given: 'json data'
-            def jsonData = 'json data'
-        and: 'the query endpoint'
+        given: 'the query endpoint'
             def endpoint = "$ncmpBasePathV1/cm-handles/$cmHandle/nodes"
         when: 'patch request is performed'
             def response = mvc.perform(
                     patch(endpoint)
                             .contentType(MediaType.APPLICATION_JSON)
-                            .content(jsonData)
+                            .content(jsonString)
                             .param('xpath', xpath)
             ).andReturn().response
         then: 'the service method is invoked once with expected parameters'
-            1 * mockNetworkCmProxyDataService.updateNodeLeaves(cmHandle, xpath, jsonData)
+            1 * mockNetworkCmProxyDataService.updateNodeLeaves(cmHandle, xpath, jsonString)
         and: 'response status indicates success'
             response.status == HttpStatus.OK.value()
     }
 
     def 'Replace data node tree.'() {
-        given: 'json data'
-            def jsonData = 'json data'
-        and: 'the query endpoint'
+        given: 'the query endpoint'
             def endpoint = "$ncmpBasePathV1/cm-handles/$cmHandle/nodes"
         when: 'put request is performed'
             def response = mvc.perform(
                     put(endpoint)
                             .contentType(MediaType.APPLICATION_JSON)
-                            .content(jsonData)
+                            .content(jsonString)
                             .param('xpath', xpath)
             ).andReturn().response
         then: 'the service method is invoked once with expected parameters'
-            1 * mockNetworkCmProxyDataService.replaceNodeTree(cmHandle, xpath, jsonData)
+            1 * mockNetworkCmProxyDataService.replaceNodeTree(cmHandle, xpath, jsonString)
         and: 'response status indicates success'
             response.status == HttpStatus.OK.value()
     }
@@ -232,11 +226,11 @@
             def response = mvc.perform(
                 put(updateUrl)
                     .contentType(MediaType.APPLICATION_JSON_VALUE)
-                    .accept(MediaType.APPLICATION_JSON_VALUE).content('some-request-body')
+                    .accept(MediaType.APPLICATION_JSON_VALUE).content(jsonString)
             ).andReturn().response
         then: 'ncmp service method to update resource is called'
             1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
-                'parent/child', UPDATE,'some-request-body', 'application/json;charset=UTF-8')
+                'parent/child', UPDATE, jsonString, 'application/json;charset=UTF-8')
         and: 'the response status is OK'
             response.status == HttpStatus.OK.value()
     }
@@ -245,6 +239,7 @@
         given: 'resource data url'
             def url = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
                     "?resourceIdentifier=parent/child"
+            def requestBody = '{"some-key":"some-value"}'
         when: 'create resource request is performed'
             def response = mvc.perform(
                     post(url)
@@ -256,10 +251,6 @@
                 'parent/child', CREATE, requestBody, 'application/json;charset=UTF-8')
         and: 'resource is created'
             response.status == HttpStatus.CREATED.value()
-        where: 'given request body'
-            scenario                        |  requestBody
-            'body contains " and new line'  |  'body with " quote and \n new line'
-            'body contains normal string'   |  'normal request body'
     }
 
     def 'Get module references for the given dataspace and cm handle.' () {
@@ -269,9 +260,9 @@
             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: 'some-revision1')]
+                    >> [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":"some-revision1"}]'
+            response.getContentAsString() == '[{"moduleName":"some-name1","revision":"2021-10-03"}]'
         and: 'response returns an OK http code'
             response.status == HttpStatus.OK.value()
     }
@@ -279,13 +270,13 @@
     def 'Retrieve cm handles.'() {
         given: 'an endpoint and json data'
             def searchesEndpoint = "$ncmpBasePathV1/ch/searches"
-            String jsonData = TestUtils.getResourceFileContent('cmhandle-search.json')
+            String jsonString = TestUtils.getResourceFileContent('cmhandle-search.json')
         and: 'the service method is invoked with module names and returns two cm handle ids'
             mockNetworkCmProxyDataService.executeCmHandleHasAllModulesSearch(['module1', 'module2']) >> ['some-cmhandle-id1', 'some-cmhandle-id2']
         when: 'the searches api is invoked'
             def response = mvc.perform(post(searchesEndpoint)
                     .contentType(MediaType.APPLICATION_JSON)
-                    .content(jsonData)).andReturn().response
+                    .content(jsonString)).andReturn().response
         then: 'response status returns OK'
             response.status == HttpStatus.OK.value()
         and: 'the expected response content is returned'
@@ -295,11 +286,11 @@
     def 'Call execute cm handle searches with unrecognized condition name.'() {
         given: 'an endpoint and json data'
             def searchesEndpoint = "$ncmpBasePathV1/ch/searches"
-            String jsonData = TestUtils.getResourceFileContent('invalid-cmhandle-search.json')
+            String jsonString = TestUtils.getResourceFileContent('invalid-cmhandle-search.json')
         when: 'the searches api is invoked'
             def response = mvc.perform(post(searchesEndpoint)
                     .contentType(MediaType.APPLICATION_JSON)
-                    .content(jsonData)).andReturn().response
+                    .content(jsonString)).andReturn().response
         then: 'an empty cm handle identifier is returned'
             response.contentAsString == '{"cmHandles":[]}'
     }
@@ -312,11 +303,11 @@
             def response = mvc.perform(
                     patch(url)
                             .contentType(MediaType.APPLICATION_JSON)
-                            .accept(MediaType.APPLICATION_JSON).content('{"some-key" : "some-value"}')
+                            .accept(MediaType.APPLICATION_JSON).content(jsonString)
             ).andReturn().response
         then: 'ncmp service method to update resource is called'
             1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
-                    'parent/child', PATCH, '{some-key=some-value}', 'application/json;charset=UTF-8')
+                    'parent/child', PATCH, jsonString, 'application/json;charset=UTF-8')
         and: 'the response status is OK'
             response.status == HttpStatus.OK.value()
     }
@@ -328,10 +319,10 @@
         when: 'delete data resource request is performed'
             def response = mvc.perform(
                 delete(url).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)
-                .content('{"some-key" : "some-value"}')).andReturn().response
+                .content(jsonString)).andReturn().response
         then: 'the ncmp service method to delete resource is called'
             1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
-                'parent/child', DELETE, '{"some-key" : "some-value"}', 'application/json;charset=UTF-8')
+                'parent/child', DELETE, jsonString, 'application/json;charset=UTF-8')
         and: 'the response is No Content'
             response.status == HttpStatus.NO_CONTENT.value()
     }