Replace gson mapper with jackson mapper 33/126633/8
authorsourabh_sourabh <sourabh.sourabh@est.tech>
Tue, 18 Jan 2022 16:27:46 +0000 (21:57 +0530)
committersourabh_sourabh <sourabh.sourabh@est.tech>
Tue, 25 Jan 2022 16:25:25 +0000 (21:55 +0530)
We introduced JsonObjectMapper (wapper) as Spring component.

Issue-ID: CPS-751

Change-Id: I536b0771a3a263325e6907717baf6941d70c0d6c
Signed-off-by: sourabh_sourabh <sourabh.sourabh@est.tech>
27 files changed:
cps-ncmp-rest/pom.xml
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy
cps-ncmp-service/pom.xml
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java
cps-rest/src/main/java/org/onap/cps/rest/controller/QueryRestController.java
cps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy
cps-rest/src/test/groovy/org/onap/cps/rest/controller/QueryRestControllerSpec.groovy
cps-rest/src/test/groovy/org/onap/cps/rest/exceptions/CpsRestExceptionHandlerSpec.groovy
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java
cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryCpsPathQueryImpl.java
cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy
cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy
cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsPersistenceSpecBase.groovy
cps-service/pom.xml
cps-service/src/main/java/org/onap/cps/utils/JsonObjectMapper.java [new file with mode: 0644]
cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy [new file with mode: 0644]

index 93ee680..26b83be 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
   ============LICENSE_START=======================================================
-  Copyright (C) 2021 Nordix Foundation
+  Copyright (C) 2021-2022 Nordix Foundation
   Modifications Copyright (C) 2021 Bell Canada
   ================================================================================
   Licensed under the Apache License, Version 2.0 (the "License");
             <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>
index f2f43c9..419f6e9 100755 (executable)
@@ -27,8 +27,6 @@ import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum
 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.PATCH;
 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE;
 
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -36,6 +34,7 @@ import java.util.List;
 import java.util.stream.Collectors;
 import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.modelmapper.ModelMapper;
 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
@@ -48,6 +47,7 @@ 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.utils.JsonObjectMapper;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -56,21 +56,14 @@ import org.springframework.web.bind.annotation.RestController;
 @Slf4j
 @RestController
 @RequestMapping("${rest.api.ncmp-base-path}")
+@RequiredArgsConstructor
 public class NetworkCmProxyController implements NetworkCmProxyApi {
 
-    private static final Gson GSON = new GsonBuilder().create();
     private static final String NO_BODY = null;
 
-    private final ModelMapper modelMapper = new ModelMapper();
+    private final ModelMapper modelMapper;
     private final NetworkCmProxyDataService networkCmProxyDataService;
-
-    /**
-     * Constructor Injection for Dependencies.
-     * @param networkCmProxyDataService Data Service Interface
-     */
-    public NetworkCmProxyController(final NetworkCmProxyDataService networkCmProxyDataService) {
-        this.networkCmProxyDataService = networkCmProxyDataService;
-    }
+    private final JsonObjectMapper jsonObjectMapper;
 
     /**
      * Get resource data from operational datastore.
@@ -119,7 +112,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
         final String cmHandle,
         final Object requestBody, final String contentType) {
         final Object responseObject = networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
-            resourceIdentifier, PATCH, GSON.toJson(requestBody), contentType);
+            resourceIdentifier, PATCH, jsonObjectMapper.asJsonString(requestBody), contentType);
         return ResponseEntity.ok(responseObject);
     }
 
@@ -136,7 +129,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
     public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String resourceIdentifier,
         final String cmHandle, final Object requestBody, final String contentType) {
         networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
-                resourceIdentifier, CREATE, GSON.toJson(requestBody), contentType);
+                resourceIdentifier, CREATE, jsonObjectMapper.asJsonString(requestBody), contentType);
         return new ResponseEntity<>(HttpStatus.CREATED);
     }
 
@@ -155,7 +148,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
                                                                        final Object requestBody,
                                                                        final String contentType) {
         networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
-            resourceIdentifier, UPDATE, GSON.toJson(requestBody), contentType);
+                resourceIdentifier, UPDATE, jsonObjectMapper.asJsonString(requestBody), contentType);
         return new ResponseEntity<>(HttpStatus.OK);
     }
 
index b5dc2ea..0c8b222 100644 (file)
@@ -22,9 +22,6 @@
 
 package org.onap.cps.ncmp.rest.controller
 
-import org.onap.cps.TestUtils
-import org.onap.cps.spi.model.ModuleReference
-
 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.PATCH
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
@@ -35,6 +32,11 @@ import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum
 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE
 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.DELETE
 
+import com.fasterxml.jackson.databind.ObjectMapper
+import org.modelmapper.ModelMapper
+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
@@ -54,10 +56,16 @@ class NetworkCmProxyControllerSpec extends Specification {
     @SpringBean
     NetworkCmProxyDataService mockNetworkCmProxyDataService = Mock()
 
+    @SpringBean
+    ModelMapper modelMapper = new ModelMapper()
+
+    @SpringBean
+    JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+
     @Value('${rest.api.ncmp-base-path}/v1')
     def ncmpBasePathV1
 
-    def jsonString = '{"some-key":"some-value"}'
+    def requestBody = '{"some-key":"some-value"}'
 
     def 'Get Resource Data from pass-through operational.' () {
         given: 'resource data url'
@@ -115,11 +123,11 @@ class NetworkCmProxyControllerSpec extends Specification {
             def response = mvc.perform(
                 put(updateUrl)
                     .contentType(MediaType.APPLICATION_JSON_VALUE)
-                    .accept(MediaType.APPLICATION_JSON_VALUE).content(jsonString)
+                    .accept(MediaType.APPLICATION_JSON_VALUE).content(requestBody)
             ).andReturn().response
         then: 'ncmp service method to update resource is called'
             1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
-                'parent/child', UPDATE, jsonString, 'application/json;charset=UTF-8')
+                'parent/child', UPDATE, requestBody, 'application/json;charset=UTF-8')
         and: 'the response status is OK'
             response.status == HttpStatus.OK.value()
     }
@@ -192,11 +200,11 @@ class NetworkCmProxyControllerSpec extends Specification {
             def response = mvc.perform(
                     patch(url)
                             .contentType(MediaType.APPLICATION_JSON)
-                            .accept(MediaType.APPLICATION_JSON).content(jsonString)
+                            .accept(MediaType.APPLICATION_JSON).content(requestBody)
             ).andReturn().response
         then: 'ncmp service method to update resource is called'
             1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
-                    'parent/child', PATCH, jsonString, '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()
     }
index f36a706..7b3cd89 100644 (file)
 package org.onap.cps.ncmp.rest.exceptions
 
 import groovy.json.JsonSlurper
+import org.modelmapper.ModelMapper
 import org.onap.cps.ncmp.api.NetworkCmProxyDataService
 import org.onap.cps.ncmp.api.impl.exception.NcmpException
 import org.onap.cps.spi.exceptions.CpsException
+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
@@ -44,6 +46,12 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification {
     @SpringBean
     NetworkCmProxyDataService mockNetworkCmProxyDataService = Mock()
 
+    @SpringBean
+    ModelMapper modelMapper = Stub()
+
+    @SpringBean
+    JsonObjectMapper jsonObjectMapper = Stub()
+
     @Value('${rest.api.ncmp-base-path}')
     def basePath
 
index b702793..871bd14 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
   ============LICENSE_START=======================================================
-  Copyright (C) 2021 Nordix Foundation
+  Copyright (C) 2021-2022 Nordix Foundation
   Modifications Copyright (C) 2021 Pantheon.tech
   ================================================================================
   Licensed under the Apache License, Version 2.0 (the "License");
@@ -66,5 +66,9 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-validation</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.modelmapper</groupId>
+            <artifactId>modelmapper</artifactId>
+        </dependency>
     </dependencies>
 </project>
index 240d6b5..82145ef 100755 (executable)
@@ -27,13 +27,13 @@ import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum
 import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.api.CpsAdminService;
 import org.onap.cps.api.CpsDataService;
@@ -50,11 +50,13 @@ import org.onap.cps.ncmp.api.models.PersistenceCmHandlesList;
 import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
 import org.onap.cps.spi.exceptions.DataValidationException;
 import org.onap.cps.spi.model.ModuleReference;
+import org.onap.cps.utils.JsonObjectMapper;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 
 @Slf4j
 @Service
+@RequiredArgsConstructor
 public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService {
 
     private static final String NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME = "NFP-Operational";
@@ -65,37 +67,17 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
 
     private static final OffsetDateTime NO_TIMESTAMP = null;
 
-    private CpsDataService cpsDataService;
+    private final CpsDataService cpsDataService;
 
-    private ObjectMapper objectMapper;
+    private final JsonObjectMapper jsonObjectMapper;
 
-    private DmiDataOperations dmiDataOperations;
+    private final DmiDataOperations dmiDataOperations;
 
-    private DmiModelOperations dmiModelOperations;
+    private final DmiModelOperations dmiModelOperations;
 
-    private CpsModuleService cpsModuleService;
+    private final CpsModuleService cpsModuleService;
 
-    private CpsAdminService cpsAdminService;
-
-    /**
-     * Constructor Injection for Dependencies.
-     * @param dmiDataOperations DMI operation
-     * @param cpsDataService Data Service Interface
-     * @param objectMapper Object Mapper
-     */
-    public NetworkCmProxyDataServiceImpl(final DmiDataOperations dmiDataOperations,
-                                         final DmiModelOperations dmiModelOperations,
-                                         final CpsModuleService cpsModuleService,
-                                         final CpsDataService cpsDataService,
-                                         final CpsAdminService cpsAdminService,
-                                         final ObjectMapper objectMapper) {
-        this.dmiDataOperations = dmiDataOperations;
-        this.dmiModelOperations = dmiModelOperations;
-        this.cpsModuleService = cpsModuleService;
-        this.cpsDataService = cpsDataService;
-        this.cpsAdminService = cpsAdminService;
-        this.objectMapper = objectMapper;
-    }
+    private final CpsAdminService cpsAdminService;
 
     @Override
     public void updateDmiRegistrationAndSyncModule(final DmiPluginRegistration dmiPluginRegistration) {
@@ -198,7 +180,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
         throws JsonProcessingException {
         final PersistenceCmHandlesList updatedPersistenceCmHandlesList =
             getUpdatedPersistenceCmHandlesList(dmiPluginRegistration, dmiPluginRegistration.getUpdatedCmHandles());
-        final String cmHandlesAsJson = objectMapper.writeValueAsString(updatedPersistenceCmHandlesList);
+        final String cmHandlesAsJson = jsonObjectMapper.asJsonString(updatedPersistenceCmHandlesList);
         cpsDataService.updateNodeLeavesAndExistingDescendantLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
                 "/dmi-registry", cmHandlesAsJson, NO_TIMESTAMP);
     }
@@ -223,7 +205,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
 
     private void registerAndSyncNewCmHandles(final PersistenceCmHandlesList persistenceCmHandlesList)
         throws JsonProcessingException  {
-        final String cmHandleJsonData = objectMapper.writeValueAsString(persistenceCmHandlesList);
+        final String cmHandleJsonData = jsonObjectMapper.asJsonString(persistenceCmHandlesList);
         cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, "/dmi-registry",
             cmHandleJsonData, NO_TIMESTAMP);
 
index 095f677..3bfb424 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-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.
@@ -25,10 +25,10 @@ import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum
 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.READ;
 import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.DATA;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
 import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
 import org.onap.cps.ncmp.api.models.PersistenceCmHandle;
+import org.onap.cps.utils.JsonObjectMapper;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
@@ -45,10 +45,10 @@ public class DmiDataOperations extends DmiOperations {
      * @param dmiRestClient {@code DmiRestClient}
      */
     public DmiDataOperations(final PersistenceCmHandleRetriever cmHandlePropertiesRetriever,
-                             final ObjectMapper objectMapper,
+                             final JsonObjectMapper jsonObjectMapper,
                              final NcmpConfiguration.DmiProperties dmiProperties,
                              final DmiRestClient dmiRestClient) {
-        super(cmHandlePropertiesRetriever, objectMapper, dmiProperties, dmiRestClient);
+        super(cmHandlePropertiesRetriever, jsonObjectMapper, dmiProperties, dmiRestClient);
     }
 
     /**
@@ -73,7 +73,7 @@ public class DmiDataOperations extends DmiOperations {
             .operation(READ)
             .build();
         dmiRequestBody.asCmHandleProperties(persistenceCmHandle.getAdditionalProperties());
-        final String jsonBody = getDmiRequestBodyAsString(dmiRequestBody);
+        final String jsonBody = jsonObjectMapper.asJsonString(dmiRequestBody);
 
         final var dmiResourceDataUrl = getDmiDatastoreUrlWithOptions(
             persistenceCmHandle.resolveDmiServiceName(DATA), cmHandle, resourceId,
@@ -106,7 +106,7 @@ public class DmiDataOperations extends DmiOperations {
             .dataType(dataType)
             .build();
         dmiRequestBody.asCmHandleProperties(persistenceCmHandle.getAdditionalProperties());
-        final String jsonBody = getDmiRequestBodyAsString(dmiRequestBody);
+        final String jsonBody = jsonObjectMapper.asJsonString(dmiRequestBody);
         final String dmiUrl =
             getResourceInDataStoreUrl(persistenceCmHandle.resolveDmiServiceName(DATA),
             cmHandle, resourceId, PASSTHROUGH_RUNNING);
index 20a3309..1ce6dcf 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-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.
@@ -22,7 +22,6 @@ package org.onap.cps.ncmp.api.impl.operations;
 
 import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.MODEL;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonObject;
 import java.util.ArrayList;
@@ -34,10 +33,14 @@ import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
 import org.onap.cps.ncmp.api.models.PersistenceCmHandle;
 import org.onap.cps.ncmp.api.models.YangResource;
 import org.onap.cps.spi.model.ModuleReference;
+import org.onap.cps.utils.JsonObjectMapper;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
 
+/**
+ * Operations class for DMI Model.
+ */
 @Component
 public class DmiModelOperations extends DmiOperations {
 
@@ -47,10 +50,10 @@ public class DmiModelOperations extends DmiOperations {
      * @param dmiRestClient {@code DmiRestClient}
      */
     public DmiModelOperations(final PersistenceCmHandleRetriever cmHandlePropertiesRetriever,
-                              final ObjectMapper objectMapper,
+                              final JsonObjectMapper jsonObjectMapper,
                               final NcmpConfiguration.DmiProperties dmiProperties,
                               final DmiRestClient dmiRestClient) {
-        super(cmHandlePropertiesRetriever, objectMapper, dmiProperties, dmiRestClient);
+        super(cmHandlePropertiesRetriever, jsonObjectMapper, dmiProperties, dmiRestClient);
     }
 
     /**
@@ -65,7 +68,7 @@ public class DmiModelOperations extends DmiOperations {
         dmiRequestBody.asCmHandleProperties(persistenceCmHandle.getAdditionalProperties());
         final ResponseEntity<Object> dmiFetchModulesResponseEntity = getResourceFromDmiWithJsonData(
             persistenceCmHandle.resolveDmiServiceName(MODEL),
-            getDmiRequestBodyAsString(dmiRequestBody), persistenceCmHandle.getId(), "modules");
+                jsonObjectMapper.asJsonString(dmiRequestBody), persistenceCmHandle.getId(), "modules");
         return toModuleReferences((Map) dmiFetchModulesResponseEntity.getBody());
     }
 
@@ -144,7 +147,7 @@ public class DmiModelOperations extends DmiOperations {
             if (moduleReferencesAsList != null) {
                 moduleReferencesAsList.forEach(moduleReferenceAsMap -> {
                     final ModuleReference moduleReference =
-                        objectMapper.convertValue(moduleReferenceAsMap, ModuleReference.class);
+                            jsonObjectMapper.convertToValueType(moduleReferenceAsMap, ModuleReference.class);
                     moduleReferences.add(moduleReference);
                 });
             }
@@ -159,7 +162,7 @@ public class DmiModelOperations extends DmiOperations {
         if (yangResourcesAsList != null) {
             yangResourcesAsList.forEach(yangResourceAsMap -> {
                 final YangResource yangResource =
-                    objectMapper.convertValue(yangResourceAsMap, YangResource.class);
+                        jsonObjectMapper.convertToValueType(yangResourceAsMap, YangResource.class);
                 yangResourcesModuleNameToContentMap.put(yangResource.getModuleName(),
                     yangResource.getYangSource());
             });
index 5097280..2f7376e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-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.
 
 package org.onap.cps.ncmp.api.impl.operations;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.base.Strings;
 import lombok.Getter;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
 import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
-import org.onap.cps.ncmp.api.impl.exception.NcmpException;
+import org.onap.cps.utils.JsonObjectMapper;
 import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Service;
 
 @Slf4j
+@RequiredArgsConstructor
+@Service
 public class DmiOperations {
 
     @Getter
@@ -44,28 +46,13 @@ public class DmiOperations {
         }
     }
 
-    protected ObjectMapper objectMapper;
-    protected PersistenceCmHandleRetriever cmHandlePropertiesRetriever;
-    protected DmiRestClient dmiRestClient;
-    protected NcmpConfiguration.DmiProperties dmiProperties;
+    protected final PersistenceCmHandleRetriever cmHandlePropertiesRetriever;
+    protected final JsonObjectMapper jsonObjectMapper;
+    protected final NcmpConfiguration.DmiProperties dmiProperties;
+    protected final DmiRestClient dmiRestClient;
 
     static final String URL_SEPARATOR = "/";
 
-    /**
-     * Constructor for {@code DmiOperations}. This method also manipulates url properties.
-     *
-     * @param dmiRestClient {@code DmiRestClient}
-     */
-    public DmiOperations(final PersistenceCmHandleRetriever cmHandlePropertiesRetriever,
-                         final ObjectMapper objectMapper,
-                         final NcmpConfiguration.DmiProperties dmiProperties,
-                         final DmiRestClient dmiRestClient) {
-        this.cmHandlePropertiesRetriever = cmHandlePropertiesRetriever;
-        this.objectMapper = objectMapper;
-        this.dmiRestClient = dmiRestClient;
-        this.dmiProperties = dmiProperties;
-    }
-
     String getCmHandleUrl(final String dmiServiceName, final String cmHandle) {
         return dmiServiceName
             + dmiProperties.getDmiBasePath()
@@ -95,20 +82,4 @@ public class DmiOperations {
         return httpHeaders;
     }
 
-    /**
-     * Convert DmiRequestBody to JSON.
-     *
-     * @param dmiRequestBody the dmi request body
-     * @return DmiRequestBody as JSON
-     */
-    String getDmiRequestBodyAsString(final DmiRequestBody dmiRequestBody) {
-        try {
-            return objectMapper.writeValueAsString(dmiRequestBody);
-        } catch (final JsonProcessingException e) {
-            log.error("Parsing error occurred while converting Object to JSON.");
-            throw new NcmpException("Parsing error occurred while converting given object to JSON.",
-                e.getMessage());
-        }
-    }
-
 }
index b7f059a..4647571 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-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.
 
 package org.onap.cps.ncmp.api.impl
 
-import com.fasterxml.jackson.databind.ObjectMapper
 import org.onap.cps.api.CpsAdminService
 import org.onap.cps.api.CpsModuleService
+import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations
 import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations
 import org.onap.cps.ncmp.api.models.PersistenceCmHandle
 import org.onap.cps.spi.model.ModuleReference
+import org.onap.cps.utils.JsonObjectMapper
 import spock.lang.Specification
 
 class NetworkCmProxyDataServiceImplModelSyncSpec extends Specification {
 
+    def mockJsonObjectMapper = Mock(JsonObjectMapper)
     def mockCpsModuleService = Mock(CpsModuleService)
     def mockCpsAdminService = Mock(CpsAdminService)
     def mockDmiModelOperations = Mock(DmiModelOperations)
+    def mockDmiDataOperations = Mock(DmiDataOperations)
 
-    def objectUnderTest = new NetworkCmProxyDataServiceImpl(null, mockDmiModelOperations,
-        mockCpsModuleService, null, mockCpsAdminService, new ObjectMapper())
+    def objectUnderTest = new NetworkCmProxyDataServiceImpl(null, mockJsonObjectMapper, mockDmiDataOperations, mockDmiModelOperations,
+            mockCpsModuleService, mockCpsAdminService)
 
     def expectedDataspaceName = 'NFP-Operational'
 
index 90fcbfc..b954b41 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-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.
@@ -22,13 +22,17 @@ package org.onap.cps.ncmp.api.impl
 
 import com.fasterxml.jackson.core.JsonProcessingException
 import com.fasterxml.jackson.databind.ObjectMapper
+import org.onap.cps.api.CpsAdminService
 import org.onap.cps.api.CpsDataService
 import org.onap.cps.api.CpsModuleService
 import org.onap.cps.ncmp.api.impl.exception.NcmpException
+import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations
+import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations
 import org.onap.cps.ncmp.api.models.CmHandle
 import org.onap.cps.ncmp.api.models.DmiPluginRegistration
 import org.onap.cps.spi.exceptions.DataNodeNotFoundException
 import org.onap.cps.spi.exceptions.DataValidationException
+import org.onap.cps.utils.JsonObjectMapper
 import spock.lang.Shared
 import spock.lang.Specification
 
@@ -44,7 +48,10 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
 
     def mockCpsDataService = Mock(CpsDataService)
     def mockCpsModuleService = Mock(CpsModuleService)
-    def spyObjectMapper = Spy(ObjectMapper)
+    def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
+    def mockCpsAdminService = Mock(CpsAdminService)
+    def mockDmiModelOperations = Mock(DmiModelOperations)
+    def mockDmiDataOperations = Mock(DmiDataOperations)
 
     def noTimestamp = null
 
@@ -102,7 +109,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
             dmiPluginRegistration.createdCmHandles = createdCmHandles
             dmiPluginRegistration.updatedCmHandles = updatedCmHandles
         and: 'an json processing exception occurs'
-            spyObjectMapper.writeValueAsString(_) >> { throw (new JsonProcessingException('')) }
+            spiedJsonObjectMapper.asJsonString(_) >> { throw (new JsonProcessingException('')) }
         when: 'registration is updated and modules are synced'
             objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
         then: 'a data validation exception is thrown'
@@ -182,8 +189,8 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
     }
 
     def getObjectUnderTestWithModelSyncDisabled() {
-        def objectUnderTest = Spy(new NetworkCmProxyDataServiceImpl(null, null, mockCpsModuleService,
-                mockCpsDataService, null, spyObjectMapper))
+        def objectUnderTest = Spy(new NetworkCmProxyDataServiceImpl(mockCpsDataService, spiedJsonObjectMapper, mockDmiDataOperations, mockDmiModelOperations,
+                mockCpsModuleService, mockCpsAdminService))
         objectUnderTest.syncModulesAndCreateAnchor(*_) >> null
         return objectUnderTest
     }
index 5753d7b..51af0f5 100644 (file)
@@ -28,6 +28,8 @@ import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum
 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.READ
 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE
 
+import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations
+import org.onap.cps.utils.JsonObjectMapper
 import com.fasterxml.jackson.core.JsonProcessingException
 import com.fasterxml.jackson.databind.ObjectMapper
 import org.onap.cps.api.CpsAdminService
@@ -46,11 +48,12 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
     def mockCpsDataService = Mock(CpsDataService)
     def mockCpsModuleService = Mock(CpsModuleService)
     def mockCpsAdminService = Mock(CpsAdminService)
-    def spyObjectMapper = Spy(ObjectMapper)
+    def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
+    def mockDmiModelOperations = Mock(DmiModelOperations)
     def mockDmiDataOperations = Mock(DmiDataOperations)
 
-    def objectUnderTest = new NetworkCmProxyDataServiceImpl(mockDmiDataOperations, null,
-        mockCpsModuleService, mockCpsDataService, mockCpsAdminService, spyObjectMapper)
+    def objectUnderTest = new NetworkCmProxyDataServiceImpl(mockCpsDataService, spiedJsonObjectMapper, mockDmiDataOperations, mockDmiModelOperations,
+        mockCpsModuleService, mockCpsAdminService)
 
     def cmHandleXPath = "/dmi-registry/cm-handles[@id='testCmHandle']"
 
@@ -126,9 +129,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
                 cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
         and: 'objectMapper not able to parse object'
-            def mockObjectMapper = Mock(ObjectMapper)
-            objectUnderTest.objectMapper = mockObjectMapper
-            mockObjectMapper.writeValueAsString(_) >> { throw new JsonProcessingException('testException') }
+            spiedJsonObjectMapper.asJsonString(_) >> { throw new JsonProcessingException('testException') }
         and: 'dmi returns NOK response'
             mockDmiDataOperations.getResourceDataFromDmi(*_)
                 >> new ResponseEntity<>('NOK-json', HttpStatus.NOT_FOUND)
index b9704b1..54ae0aa 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-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.
 
 package org.onap.cps.ncmp.api.impl.operations
 
-import org.onap.cps.ncmp.api.impl.client.DmiRestClient
+import com.fasterxml.jackson.databind.ObjectMapper
 import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
+import org.onap.cps.utils.JsonObjectMapper
+import org.spockframework.spring.SpringBean
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.test.context.SpringBootTest
 import org.springframework.http.ResponseEntity
@@ -37,6 +39,9 @@ import org.springframework.http.HttpStatus
 @ContextConfiguration(classes = [NcmpConfiguration.DmiProperties, DmiDataOperations])
 class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
 
+    @SpringBean
+    JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+
     @Autowired
     DmiDataOperations objectUnderTest
 
index 335bc06..2efd6c2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-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.
 package org.onap.cps.ncmp.api.impl.operations
 
 import com.fasterxml.jackson.core.JsonProcessingException
+import com.fasterxml.jackson.databind.ObjectMapper
 import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
-import org.onap.cps.ncmp.api.impl.exception.NcmpException
 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.boot.test.context.SpringBootTest
 import org.springframework.http.HttpStatus
@@ -41,6 +43,9 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
     @Autowired
     DmiModelOperations objectUnderTest
 
+    @SpringBean
+    JsonObjectMapper spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
+
     def 'Retrieving module references.'() {
         given: 'a persistence cm handle'
             mockPersistenceCmHandleRetrieval([])
@@ -158,11 +163,11 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
         given: 'a persistence cm handle'
             mockPersistenceCmHandleRetrieval([])
         and: 'a Json processing exception occurs'
-            spyObjectMapper.writeValueAsString(_) >> {throw (new JsonProcessingException(''))}
+            spiedJsonObjectMapper.asJsonString(_) >> {throw (new JsonProcessingException('parsing error'))}
         when: 'a dmi operation is executed'
             objectUnderTest.getModuleReferences(persistenceCmHandle)
         then: 'an ncmp exception is thrown'
-            def exceptionThrown = thrown(NcmpException)
+            def exceptionThrown = thrown(JsonProcessingException)
         and: 'the message indicates a parsing error'
             exceptionThrown.message.toLowerCase().contains('parsing error')
     }
index a55b1ba..fc2818b 100755 (executable)
@@ -2,7 +2,7 @@
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2020-2021 Bell Canada.
  *  Modifications Copyright (C) 2021 Pantheon.tech
- *  Modifications Copyright (C) 2021 Nordix Foundation
+ *  Modifications Copyright (C) 2021-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.
@@ -22,7 +22,6 @@
 
 package org.onap.cps.rest.controller;
 
-import com.google.gson.Gson;
 import java.time.OffsetDateTime;
 import java.time.format.DateTimeFormatter;
 import javax.validation.ValidationException;
@@ -32,6 +31,7 @@ import org.onap.cps.api.CpsDataService;
 import org.onap.cps.rest.api.CpsDataApi;
 import org.onap.cps.spi.FetchDescendantsOption;
 import org.onap.cps.utils.DataMapUtils;
+import org.onap.cps.utils.JsonObjectMapper;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -47,17 +47,18 @@ public class DataRestController implements CpsDataApi {
     private static final DateTimeFormatter ISO_TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern(ISO_TIMESTAMP_FORMAT);
 
     private final CpsDataService cpsDataService;
-    private final Gson gson;
+    private final JsonObjectMapper jsonObjectMapper;
 
     @Override
     public ResponseEntity<String> createNode(final String dataspaceName, final String anchorName,
         final Object jsonData, final String parentNodeXpath, final String observedTimestamp) {
+        final String jsonDataAsString = jsonObjectMapper.asJsonString(jsonData);
         if (isRootXpath(parentNodeXpath)) {
-            cpsDataService.saveData(dataspaceName, anchorName, gson.toJson(jsonData),
-                toOffsetDateTime(observedTimestamp));
+            cpsDataService.saveData(dataspaceName, anchorName, jsonDataAsString,
+                    toOffsetDateTime(observedTimestamp));
         } else {
-            cpsDataService.saveData(dataspaceName, anchorName, parentNodeXpath, gson.toJson(jsonData),
-                toOffsetDateTime(observedTimestamp));
+            cpsDataService.saveData(dataspaceName, anchorName, parentNodeXpath,
+                    jsonDataAsString, toOffsetDateTime(observedTimestamp));
         }
         return new ResponseEntity<>(HttpStatus.CREATED);
     }
@@ -73,8 +74,8 @@ public class DataRestController implements CpsDataApi {
     @Override
     public ResponseEntity<String> addListElements(final String parentNodeXpath,
         final String dataspaceName, final String anchorName, final Object jsonData, final String observedTimestamp) {
-        cpsDataService.saveListElements(dataspaceName, anchorName, parentNodeXpath, gson.toJson(jsonData),
-            toOffsetDateTime(observedTimestamp));
+        cpsDataService.saveListElements(dataspaceName, anchorName, parentNodeXpath,
+                jsonObjectMapper.asJsonString(jsonData), toOffsetDateTime(observedTimestamp));
         return new ResponseEntity<>(HttpStatus.CREATED);
     }
 
@@ -91,8 +92,8 @@ public class DataRestController implements CpsDataApi {
     @Override
     public ResponseEntity<Object> updateNodeLeaves(final String dataspaceName,
         final String anchorName, final Object jsonData, final String parentNodeXpath, final String observedTimestamp) {
-        cpsDataService.updateNodeLeaves(dataspaceName, anchorName, parentNodeXpath, gson.toJson(jsonData),
-            toOffsetDateTime(observedTimestamp));
+        cpsDataService.updateNodeLeaves(dataspaceName, anchorName, parentNodeXpath,
+                jsonObjectMapper.asJsonString(jsonData), toOffsetDateTime(observedTimestamp));
         return new ResponseEntity<>(HttpStatus.OK);
     }
 
@@ -100,8 +101,8 @@ public class DataRestController implements CpsDataApi {
     public ResponseEntity<Object> replaceNode(final String dataspaceName, final String anchorName,
         final Object jsonData, final String parentNodeXpath, final String observedTimestamp) {
         cpsDataService
-            .replaceNodeTree(dataspaceName, anchorName, parentNodeXpath, gson.toJson(jsonData),
-                toOffsetDateTime(observedTimestamp));
+                .replaceNodeTree(dataspaceName, anchorName, parentNodeXpath,
+                        jsonObjectMapper.asJsonString(jsonData), toOffsetDateTime(observedTimestamp));
         return new ResponseEntity<>(HttpStatus.OK);
     }
 
@@ -109,8 +110,8 @@ public class DataRestController implements CpsDataApi {
     public ResponseEntity<Object> replaceListContent(final String parentNodeXpath,
         final String dataspaceName, final String anchorName, final Object jsonData,
         final String observedTimestamp) {
-        cpsDataService.replaceListContent(dataspaceName, anchorName, parentNodeXpath, gson.toJson(jsonData),
-            toOffsetDateTime(observedTimestamp));
+        cpsDataService.replaceListContent(dataspaceName, anchorName, parentNodeXpath,
+                jsonObjectMapper.asJsonString(jsonData), toOffsetDateTime(observedTimestamp));
         return new ResponseEntity<>(HttpStatus.OK);
     }
 
index 8aa65a0..eb422dc 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-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.
 
 package org.onap.cps.rest.controller;
 
-import com.google.gson.Gson;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import javax.validation.Valid;
+import lombok.RequiredArgsConstructor;
 import org.onap.cps.api.CpsQueryService;
 import org.onap.cps.rest.api.CpsQueryApi;
 import org.onap.cps.spi.FetchDescendantsOption;
 import org.onap.cps.spi.model.DataNode;
 import org.onap.cps.utils.DataMapUtils;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.onap.cps.utils.JsonObjectMapper;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -39,10 +39,11 @@ import org.springframework.web.bind.annotation.RestController;
 
 @RestController
 @RequestMapping("${rest.api.cps-base-path}")
+@RequiredArgsConstructor
 public class QueryRestController implements CpsQueryApi {
 
-    @Autowired
-    private CpsQueryService cpsQueryService;
+    private final CpsQueryService cpsQueryService;
+    private final JsonObjectMapper jsonObjectMapper;
 
     @Override
     public ResponseEntity<Object> getNodesByDataspaceAndAnchorAndCpsPath(final String dataspaceName,
@@ -55,6 +56,6 @@ public class QueryRestController implements CpsQueryApi {
         for (final DataNode dataNode : dataNodes) {
             dataNodeList.add(DataMapUtils.toDataMap(dataNode));
         }
-        return new ResponseEntity<>(new Gson().toJson(dataNodeList), HttpStatus.OK);
+        return new ResponseEntity<>(jsonObjectMapper.asJsonString(dataNodeList), HttpStatus.OK);
     }
 }
index fbb5636..4d75848 100755 (executable)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-2022 Nordix Foundation
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2021 Bell Canada.
  *  ================================================================================
 
 package org.onap.cps.rest.controller
 
+import com.fasterxml.jackson.databind.ObjectMapper
 import org.onap.cps.api.CpsDataService
 import org.onap.cps.spi.model.DataNode
 import org.onap.cps.spi.model.DataNodeBuilder
 import org.onap.cps.utils.DateTimeUtility
+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
@@ -50,6 +52,9 @@ class DataRestControllerSpec extends Specification {
     @SpringBean
     CpsDataService mockCpsDataService = Mock()
 
+    @SpringBean
+    JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+
     @Autowired
     MockMvc mvc
 
index 550dec9..1e42a00 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-2022 Nordix Foundation
  *  Modifications Copyright (C) 2021 Bell Canada.
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  ================================================================================
 
 package org.onap.cps.rest.controller
 
-import org.onap.cps.spi.model.DataNode
-
 import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
 import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
 
-import com.google.gson.Gson
-import org.modelmapper.ModelMapper
-import org.onap.cps.api.CpsAdminService
-import org.onap.cps.api.CpsDataService
-import org.onap.cps.api.CpsModuleService
+import com.fasterxml.jackson.databind.ObjectMapper
+import org.onap.cps.utils.JsonObjectMapper
 import org.onap.cps.api.CpsQueryService
 import org.onap.cps.spi.model.DataNodeBuilder
 import org.spockframework.spring.SpringBean
@@ -49,6 +44,9 @@ class QueryRestControllerSpec extends Specification {
     @SpringBean
     CpsQueryService mockCpsQueryService = Mock()
 
+    @SpringBean
+    JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+
     @Autowired
     MockMvc mvc
 
index 658dcaa..a2eaa52 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2020 Pantheon.tech
- *  Modifications Copyright (C) 2021 Nordix Foundation
+ *  Modifications Copyright (C) 2021-2022 Nordix Foundation
  *  Modifications Copyright (C) 2021 Bell Canada.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -38,6 +38,7 @@ import org.onap.cps.spi.exceptions.ModelValidationException
 import org.onap.cps.spi.exceptions.NotFoundInDataspaceException
 import org.onap.cps.spi.exceptions.SchemaSetInUseException
 import org.onap.cps.spi.exceptions.DataspaceInUseException
+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
@@ -58,19 +59,22 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
 class CpsRestExceptionHandlerSpec extends Specification {
 
     @SpringBean
-    CpsAdminService mockCpsAdminService = Mock()
+    CpsAdminService mockCpsAdminService = Stub()
 
     @SpringBean
-    CpsModuleService mockCpsModuleService = Mock()
+    CpsModuleService mockCpsModuleService = Stub()
 
     @SpringBean
-    CpsDataService mockCpsDataService = Mock()
+    CpsDataService mockCpsDataService = Stub()
 
     @SpringBean
-    CpsQueryService mockCpsQueryService = Mock()
+    CpsQueryService mockCpsQueryService = Stub()
 
     @SpringBean
-    ModelMapper modelMapper = Mock()
+    ModelMapper modelMapper = Stub()
+
+    @SpringBean
+    JsonObjectMapper jsonObjectMapper = Stub()
 
     @Autowired
     MockMvc mvc
index c616c8f..c6e28ab 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-2022 Nordix Foundation
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2020-2021 Bell Canada.
  *  ================================================================================
@@ -24,12 +24,8 @@ package org.onap.cps.spi.impl;
 
 import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSet.Builder;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -41,6 +37,7 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import javax.transaction.Transactional;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.hibernate.StaleStateException;
 import org.onap.cps.cpspath.parser.CpsPathQuery;
@@ -53,43 +50,29 @@ import org.onap.cps.spi.exceptions.AlreadyDefinedException;
 import org.onap.cps.spi.exceptions.ConcurrencyException;
 import org.onap.cps.spi.exceptions.CpsPathException;
 import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
-import org.onap.cps.spi.exceptions.DataValidationException;
 import org.onap.cps.spi.model.DataNode;
 import org.onap.cps.spi.model.DataNodeBuilder;
 import org.onap.cps.spi.repository.AnchorRepository;
 import org.onap.cps.spi.repository.DataspaceRepository;
 import org.onap.cps.spi.repository.FragmentRepository;
+import org.onap.cps.utils.JsonObjectMapper;
 import org.springframework.dao.DataIntegrityViolationException;
 import org.springframework.stereotype.Service;
 
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService {
 
-    private DataspaceRepository dataspaceRepository;
+    private final DataspaceRepository dataspaceRepository;
 
-    private AnchorRepository anchorRepository;
+    private final AnchorRepository anchorRepository;
 
-    private FragmentRepository fragmentRepository;
+    private final FragmentRepository fragmentRepository;
 
-    private final ObjectMapper objectMapper;
+    private final JsonObjectMapper jsonObjectMapper;
 
-    /**
-     * Constructor.
-     *
-     * @param dataspaceRepository dataspaceRepository
-     * @param anchorRepository    anchorRepository
-     * @param fragmentRepository  fragmentRepository
-     */
-    public CpsDataPersistenceServiceImpl(final DataspaceRepository dataspaceRepository,
-        final AnchorRepository anchorRepository, final FragmentRepository fragmentRepository) {
-        this.dataspaceRepository = dataspaceRepository;
-        this.anchorRepository = anchorRepository;
-        this.fragmentRepository = fragmentRepository;
-        objectMapper = new ObjectMapper();
-    }
 
-    private static final Gson GSON = new GsonBuilder().create();
     private static final String REG_EX_FOR_OPTIONAL_LIST_INDEX = "(\\[@[\\s\\S]+?]){0,1})";
     private static final Pattern REG_EX_PATTERN_FOR_LIST_ELEMENT_KEY_PREDICATE =
             Pattern.compile("\\[(\\@([^\\/]{0,9999}))\\]$");
@@ -152,7 +135,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
      * @param dataNodeToBeConverted dataNode
      * @return a Fragment built from current DataNode
      */
-    private static FragmentEntity convertToFragmentWithAllDescendants(final DataspaceEntity dataspaceEntity,
+    private FragmentEntity convertToFragmentWithAllDescendants(final DataspaceEntity dataspaceEntity,
         final AnchorEntity anchorEntity, final DataNode dataNodeToBeConverted) {
         final FragmentEntity parentFragment = toFragmentEntity(dataspaceEntity, anchorEntity, dataNodeToBeConverted);
         final Builder<FragmentEntity> childFragmentsImmutableSetBuilder = ImmutableSet.builder();
@@ -177,13 +160,13 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
         }
     }
 
-    private static FragmentEntity toFragmentEntity(final DataspaceEntity dataspaceEntity,
+    private FragmentEntity toFragmentEntity(final DataspaceEntity dataspaceEntity,
         final AnchorEntity anchorEntity, final DataNode dataNode) {
         return FragmentEntity.builder()
             .dataspace(dataspaceEntity)
             .anchor(anchorEntity)
             .xpath(dataNode.getXpath())
-            .attributes(GSON.toJson(dataNode.getLeaves()))
+            .attributes(jsonObjectMapper.asJsonString(dataNode.getLeaves()))
             .build();
     }
 
@@ -249,14 +232,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
         final List<DataNode> childDataNodes = getChildDataNodes(fragmentEntity, fetchDescendantsOption);
         Map<String, Object> leaves = new HashMap<>();
         if (fragmentEntity.getAttributes() != null) {
-            try {
-                leaves = objectMapper.readValue(fragmentEntity.getAttributes(), Map.class);
-            } catch (final JsonProcessingException jsonProcessingException) {
-                final String message = "Parsing error occurred while processing fragmentEntity attributes.";
-                log.error(message);
-                throw new DataValidationException(message,
-                    jsonProcessingException.getMessage(), jsonProcessingException);
-            }
+            leaves = jsonObjectMapper.convertJsonString(fragmentEntity.getAttributes(), Map.class);
         }
         return new DataNodeBuilder()
             .withXpath(fragmentEntity.getXpath())
@@ -278,7 +254,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
     public void updateDataLeaves(final String dataspaceName, final String anchorName, final String xpath,
         final Map<String, Object> leaves) {
         final FragmentEntity fragmentEntity = getFragmentByXpath(dataspaceName, anchorName, xpath);
-        fragmentEntity.setAttributes(GSON.toJson(leaves));
+        fragmentEntity.setAttributes(jsonObjectMapper.asJsonString(leaves));
         fragmentRepository.save(fragmentEntity);
     }
 
@@ -296,10 +272,10 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
         }
     }
 
-    private static void replaceDataNodeTree(final FragmentEntity existingFragmentEntity,
+    private void replaceDataNodeTree(final FragmentEntity existingFragmentEntity,
                                             final DataNode newDataNode) {
 
-        existingFragmentEntity.setAttributes(GSON.toJson(newDataNode.getLeaves()));
+        existingFragmentEntity.setAttributes(jsonObjectMapper.asJsonString(newDataNode.getLeaves()));
 
         final Map<String, FragmentEntity> existingChildrenByXpath = existingFragmentEntity.getChildFragments()
             .stream().collect(Collectors.toMap(FragmentEntity::getXpath, childFragmentEntity -> childFragmentEntity));
@@ -412,7 +388,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
         return firstChildNodeXpath.substring(0, firstChildNodeXpath.lastIndexOf("[") + 1);
     }
 
-    private static FragmentEntity getFragmentForReplacement(final FragmentEntity parentEntity,
+    private FragmentEntity getFragmentForReplacement(final FragmentEntity parentEntity,
                                                             final DataNode newListElement,
                                                             final FragmentEntity existingListElementEntity) {
         if (existingListElementEntity == null) {
@@ -433,10 +409,11 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
         return !existingListElementsByXpath.containsKey(replacementDataNode.getXpath());
     }
 
-    private static void copyAttributesFromNewListElement(final FragmentEntity existingListElementEntity,
+    private void copyAttributesFromNewListElement(final FragmentEntity existingListElementEntity,
                                                          final DataNode newListElement) {
         final FragmentEntity replacementFragmentEntity =
-            FragmentEntity.builder().attributes(GSON.toJson(newListElement.getLeaves())).build();
+                FragmentEntity.builder().attributes(jsonObjectMapper.asJsonString(
+                        newListElement.getLeaves())).build();
         existingListElementEntity.setAttributes(replacementFragmentEntity.getAttributes());
     }
 
index fddedca..3720249 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation.
+ *  Copyright (C) 2021-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.
 
 package org.onap.cps.spi.repository;
 
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import javax.persistence.Query;
+import lombok.RequiredArgsConstructor;
 import org.onap.cps.cpspath.parser.CpsPathPrefixType;
 import org.onap.cps.cpspath.parser.CpsPathQuery;
 import org.onap.cps.spi.entities.FragmentEntity;
+import org.onap.cps.utils.JsonObjectMapper;
 
+@RequiredArgsConstructor
 public class FragmentRepositoryCpsPathQueryImpl implements FragmentRepositoryCpsPathQuery {
 
     public static final String SIMILAR_TO_ABSOLUTE_PATH_PREFIX = "%/";
@@ -39,8 +40,7 @@ public class FragmentRepositoryCpsPathQueryImpl implements FragmentRepositoryCps
 
     @PersistenceContext
     private EntityManager entityManager;
-
-    private static final Gson GSON = new GsonBuilder().create();
+    private final JsonObjectMapper jsonObjectMapper;
 
     @Override
     public List<FragmentEntity> findByAnchorAndCpsPath(final int anchorId, final CpsPathQuery cpsPathQuery) {
@@ -52,7 +52,8 @@ public class FragmentRepositoryCpsPathQueryImpl implements FragmentRepositoryCps
         queryParameters.put("xpathRegex", xpathRegex);
         if (cpsPathQuery.hasLeafConditions()) {
             sqlStringBuilder.append(" AND attributes @> :leafDataAsJson\\:\\:jsonb");
-            queryParameters.put("leafDataAsJson", GSON.toJson(cpsPathQuery.getLeavesData()));
+            queryParameters.put("leafDataAsJson", jsonObjectMapper.asJsonString(
+                    cpsPathQuery.getLeavesData()));
         }
 
         addTextFunctionCondition(cpsPathQuery, sqlStringBuilder, queryParameters);
index 85e1155..69e6aa8 100755 (executable)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-2022 Nordix Foundation
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2021 Bell Canada.
  *  ================================================================================
@@ -21,9 +21,8 @@
  */
 package org.onap.cps.spi.impl
 
+import com.fasterxml.jackson.databind.ObjectMapper
 import com.google.common.collect.ImmutableSet
-import com.google.gson.Gson
-import com.google.gson.GsonBuilder
 import org.onap.cps.spi.CpsDataPersistenceService
 import org.onap.cps.spi.entities.FragmentEntity
 import org.onap.cps.spi.exceptions.AlreadyDefinedException
@@ -32,6 +31,7 @@ import org.onap.cps.spi.exceptions.DataNodeNotFoundException
 import org.onap.cps.spi.exceptions.DataspaceNotFoundException
 import org.onap.cps.spi.model.DataNode
 import org.onap.cps.spi.model.DataNodeBuilder
+import org.onap.cps.utils.JsonObjectMapper
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.test.context.jdbc.Sql
 
@@ -46,7 +46,7 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase {
     @Autowired
     CpsDataPersistenceService objectUnderTest
 
-    static final Gson GSON = new GsonBuilder().create()
+    static final JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
 
     static final String SET_DATA = '/data/fragment.sql'
     static final long ID_DATA_NODE_WITH_DESCENDANTS = 4001
@@ -549,7 +549,7 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase {
     }
 
     static Map<String, Object> getLeavesMap(FragmentEntity fragmentEntity) {
-        return GSON.fromJson(fragmentEntity.getAttributes(), Map<String, Object>.class)
+        return jsonObjectMapper.convertJsonString(fragmentEntity.getAttributes(), Map<String, Object>.class)
     }
 
     def static assertLeavesMaps(actualLeavesMap, expectedLeavesMap) {
index 162a566..7166008 100644 (file)
@@ -18,6 +18,7 @@
 
 package org.onap.cps.spi.impl
 
+import com.fasterxml.jackson.databind.ObjectMapper
 import org.hibernate.StaleStateException
 import org.onap.cps.spi.FetchDescendantsOption
 import org.onap.cps.spi.entities.FragmentEntity
@@ -27,6 +28,7 @@ import org.onap.cps.spi.model.DataNodeBuilder
 import org.onap.cps.spi.repository.AnchorRepository
 import org.onap.cps.spi.repository.DataspaceRepository
 import org.onap.cps.spi.repository.FragmentRepository
+import org.onap.cps.utils.JsonObjectMapper
 import spock.lang.Specification
 
 
@@ -35,9 +37,10 @@ class CpsDataPersistenceServiceSpec extends Specification {
     def mockDataspaceRepository = Mock(DataspaceRepository)
     def mockAnchorRepository = Mock(AnchorRepository)
     def mockFragmentRepository = Mock(FragmentRepository)
+    def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
 
     def objectUnderTest = new CpsDataPersistenceServiceImpl(
-            mockDataspaceRepository, mockAnchorRepository, mockFragmentRepository)
+            mockDataspaceRepository, mockAnchorRepository, mockFragmentRepository, jsonObjectMapper)
 
     def 'Handling of StaleStateException (caused by concurrent updates) during data node tree update.'() {
 
index 8ec5c90..8e13be2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-2022 Nordix Foundation
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2021 Bell Canada.
  *  ================================================================================
 
 package org.onap.cps.spi.impl
 
+import com.fasterxml.jackson.databind.ObjectMapper
 import org.onap.cps.DatabaseTestContainer
 import org.onap.cps.spi.repository.AnchorRepository
 import org.onap.cps.spi.repository.DataspaceRepository
 import org.onap.cps.spi.repository.FragmentRepository
 import org.onap.cps.spi.repository.YangResourceRepository
+import org.onap.cps.utils.JsonObjectMapper
+import org.spockframework.spring.SpringBean
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.test.context.SpringBootTest
 import org.testcontainers.spock.Testcontainers
@@ -52,6 +55,9 @@ class CpsPersistenceSpecBase extends Specification {
     @Autowired
     FragmentRepository fragmentRepository
 
+    @SpringBean
+    JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+
     static final String CLEAR_DATA = '/data/clear-all.sql'
 
     static final String DATASPACE_NAME = 'DATASPACE-001'
index 6cef985..0c75564 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 <!--\r
   ============LICENSE_START=======================================================\r
-  Copyright (C) 2021 Nordix Foundation\r
+  Copyright (C) 2021-2022 Nordix Foundation\r
   Modifications Copyright (C) 2021 Bell Canada.\r
   Modifications Copyright (C) 2021 Pantheon.tech\r
   ================================================================================\r
       <artifactId>groovy</artifactId>\r
       <scope>test</scope>\r
     </dependency>\r
+    <dependency>\r
+      <groupId>org.codehaus.groovy</groupId>\r
+      <artifactId>groovy-json</artifactId>\r
+      <scope>test</scope>\r
+    </dependency>\r
     <dependency>\r
       <groupId>org.spockframework</groupId>\r
       <artifactId>spock-core</artifactId>\r
diff --git a/cps-service/src/main/java/org/onap/cps/utils/JsonObjectMapper.java b/cps-service/src/main/java/org/onap/cps/utils/JsonObjectMapper.java
new file mode 100644 (file)
index 0000000..2459b51
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  ============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.utils;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.spi.exceptions.DataValidationException;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@RequiredArgsConstructor
+@Component
+public class JsonObjectMapper {
+
+    private final ObjectMapper objectMapper;
+
+    /**
+     * Serializing generic java object to JSON using Jackson.
+     *
+     * @param object any java object value
+     * @return the generated JSON as a string.
+     */
+    public String asJsonString(final Object object) {
+        try {
+            return objectMapper.writeValueAsString(object);
+        } catch (final JsonProcessingException e) {
+            log.error("Parsing error occurred while converting Object to JSON string.");
+            throw new DataValidationException("Parsing error occurred while converting given object to JSON string.",
+                    e.getMessage());
+        }
+    }
+
+    /**
+     * Constructing JavaType out of given type (typically java.lang.Class).
+     * Allow efficient value conversions for structurally compatible json objects,
+     * according to standard Jackson configuration.
+     *
+     * @param jsonObject   structurally compatible json object
+     * @param valueType compatible Object class type
+     * @param <T>         type parameter
+     * @return a class object of specific class type 'T'
+     */
+    public <T> T convertToValueType(final Object jsonObject, final Class<T> valueType) {
+        try {
+            return objectMapper.convertValue(jsonObject, valueType);
+        } catch (final IllegalArgumentException e) {
+            log.error("Found structurally incompatible object while converting into value type.");
+            throw new DataValidationException("Found structurally incompatible object while converting "
+                    + "into value type.", e.getMessage());
+        }
+    }
+
+    /**
+     * Deserialize JSON content from given JSON content String.
+     *
+     * @param jsonContent   JSON content
+     * @param valueType compatible Object class type
+     * @param <T>       type parameter
+     * @return a class object of specific class type 'T'
+     */
+    public <T> T convertJsonString(final String jsonContent, final Class<T> valueType) {
+        try {
+            return objectMapper.readValue(jsonContent, valueType);
+        } catch (final JsonProcessingException e) {
+            log.error("Parsing error occurred while converting JSON content to specific class type.");
+            throw new DataValidationException("Parsing error occurred while converting "
+                    + "JSON content to specific class type.", e.getMessage());
+        }
+    }
+}
diff --git a/cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy
new file mode 100644 (file)
index 0000000..f9b8feb
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *  ============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.utils
+
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import groovy.json.JsonSlurper
+import org.onap.cps.TestUtils
+import org.onap.cps.spi.exceptions.DataValidationException
+import spock.lang.Specification
+
+class JsonObjectMapperSpec extends Specification {
+
+    def spiedObjectMapper = Spy(ObjectMapper)
+    def jsonObjectMapper = new JsonObjectMapper(spiedObjectMapper)
+
+    def 'Map a structured object to json String.'() {
+        given: 'an object model'
+            def object = spiedObjectMapper.readValue(TestUtils.getResourceFileContent('bookstore.json'), Object)
+        when: 'the object is mapped to string'
+            def content = jsonObjectMapper.asJsonString(object);
+        then: 'the result is a valid json string (can be parsed)'
+            def contentMap = new JsonSlurper().parseText(content)
+        and: 'the parsed content is as expected'
+            assert contentMap.'test:bookstore'.'bookstore-name' == 'Chapters'
+    }
+
+    def 'Map a structurally compatible object to class object of specific class type T.'() {
+        given: 'a map object model'
+            def contentMap = new JsonSlurper().parseText(TestUtils.getResourceFileContent('bookstore.json'))
+        when: 'converted into a Map'
+            def result = jsonObjectMapper.convertToValueType(contentMap, Map);
+        then: 'the result is a mapped into class of type Map'
+            assert result instanceof Map
+        and: 'the map contains the expected key'
+            assert result.containsKey('test:bookstore')
+            assert result.'test:bookstore'.categories[0].name == 'SciFi'
+
+    }
+
+    def 'Mapping an unstructured json string to class object of specific class type T.'() {
+        given: 'Unstructured json string'
+            def content = '{ "nest": { "birds": "bird"] } }'
+        when: 'mapping json string to given class type'
+            def contentMap = jsonObjectMapper.convertJsonString(content, Map);
+        then: 'an exception is thrown'
+            thrown(DataValidationException)
+    }
+
+    def 'Map an incompatible object to class object of specific class type T.'() {
+        given: 'a map object model'
+            def contentMap = new JsonSlurper().parseText(TestUtils.getResourceFileContent('bookstore.json'))
+        and: 'Object mapper throws an exception'
+            spiedObjectMapper.convertValue(*_) >> { throw new IllegalArgumentException() }
+        when: 'converted into specific class type'
+            jsonObjectMapper.convertToValueType(contentMap, Object);
+        then: 'an exception is thrown'
+            thrown(DataValidationException)
+    }
+
+    def 'Map a unstructured object to json String.'() {
+        given: 'Unstructured object'
+            def object = new Object()
+        when: 'the object is mapped to string'
+            jsonObjectMapper.asJsonString(object);
+        then: 'an exception is thrown'
+            thrown(DataValidationException)
+    }
+}