From: DylanB95EST Date: Mon, 21 Feb 2022 12:57:08 +0000 (+0000) Subject: NCMP Java API depends on NCM-Rest-API (cyclic) through json properties on Java API X-Git-Tag: 3.0.0~17 X-Git-Url: https://gerrit.onap.org/r/gitweb?p=cps.git;a=commitdiff_plain;h=d042fcdae75be100f840b6313e078eab278d87ef NCMP Java API depends on NCM-Rest-API (cyclic) through json properties on Java API Using POJO and new converter class instead of previous object mapper Issue-ID: CPS-893 Change-Id: I75531f386f08cb172d2901a4bbe97ae22cc5937e Signed-off-by: DylanB95EST --- diff --git a/cps-dependencies/pom.xml b/cps-dependencies/pom.xml index a76cd3d65..5c2ff565e 100755 --- a/cps-dependencies/pom.xml +++ b/cps-dependencies/pom.xml @@ -44,6 +44,7 @@ /content/repositories/snapshots/ true 1.15.1 + 1.4.2.Final @@ -183,6 +184,16 @@ log4j-to-slf4j 2.17.1 + + org.mapstruct + mapstruct + ${mapstruct.version} + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml index cda6ca3ac..fd02b6e56 100644 --- a/cps-ncmp-rest/docs/openapi/components.yaml +++ b/cps-ncmp-rest/docs/openapi/components.yaml @@ -38,12 +38,15 @@ components: dmiPlugin: type: string example: my-dmi-plugin + default: "" dmiDataPlugin: type: string example: my-dmi-data-plugin + default: "" dmiModelPlugin: type: string example: my-dmi-model-plugin + default: "" createdCmHandles: type: array items: diff --git a/cps-ncmp-rest/pom.xml b/cps-ncmp-rest/pom.xml index b3ae81be5..97305cfe9 100644 --- a/cps-ncmp-rest/pom.xml +++ b/cps-ncmp-rest/pom.xml @@ -61,6 +61,14 @@ io.swagger.core.v3 swagger-annotations + + org.mapstruct + mapstruct + + + org.mapstruct + mapstruct-processor + org.codehaus.groovy diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java index 9e888fb1c..36991952c 100755 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java @@ -21,12 +21,9 @@ package org.onap.cps.ncmp.rest.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; import javax.validation.Valid; import lombok.RequiredArgsConstructor; import org.onap.cps.ncmp.api.NetworkCmProxyDataService; -import org.onap.cps.ncmp.api.models.DmiPluginRegistration; import org.onap.cps.ncmp.rest.api.NetworkCmProxyInventoryApi; import org.onap.cps.ncmp.rest.model.RestDmiPluginRegistration; import org.springframework.http.HttpStatus; @@ -40,7 +37,7 @@ import org.springframework.web.bind.annotation.RestController; public class NetworkCmProxyInventoryController implements NetworkCmProxyInventoryApi { private final NetworkCmProxyDataService networkCmProxyDataService; - private final ObjectMapper objectMapper; + private final RestInputMapper restInputMapper; /** * Update DMI Plugin Registration (used for first registration also). @@ -49,14 +46,11 @@ public class NetworkCmProxyInventoryController implements NetworkCmProxyInventor @Override public ResponseEntity updateDmiPluginRegistration( final @Valid RestDmiPluginRegistration restDmiPluginRegistration) { - final DmiPluginRegistration dmiPluginRegistration = - convertRestObjectToJavaApiObject(restDmiPluginRegistration); - networkCmProxyDataService.updateDmiRegistrationAndSyncModule(dmiPluginRegistration); + networkCmProxyDataService.updateDmiRegistrationAndSyncModule( + restInputMapper.toDmiPluginRegistration(restDmiPluginRegistration)); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } - private DmiPluginRegistration convertRestObjectToJavaApiObject( - final RestDmiPluginRegistration restDmiPluginRegistration) { - return objectMapper.convertValue(restDmiPluginRegistration, DmiPluginRegistration.class); - } } + + diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/RestInputMapper.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/RestInputMapper.java new file mode 100644 index 000000000..d38204cf1 --- /dev/null +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/RestInputMapper.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.rest.controller; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.NullValueMappingStrategy; +import org.mapstruct.NullValuePropertyMappingStrategy; +import org.onap.cps.ncmp.api.models.CmHandle; +import org.onap.cps.ncmp.api.models.DmiPluginRegistration; +import org.onap.cps.ncmp.rest.model.RestCmHandle; +import org.onap.cps.ncmp.rest.model.RestDmiPluginRegistration; + +@Mapper(componentModel = "spring", nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT, + nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT) +public interface RestInputMapper { + + DmiPluginRegistration toDmiPluginRegistration(final RestDmiPluginRegistration restDmiPluginRegistration); + + @Mappings({ + @Mapping(source = "cmHandle", target = "cmHandleID"), + @Mapping(source = "cmHandleProperties", target = "dmiProperties"), + @Mapping(source = "publicCmHandleProperties", target = "publicProperties") + }) + CmHandle toCmHandle(final RestCmHandle restCmHandle); + +} diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java index 7dc6284fc..fd01096e1 100755 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java @@ -33,6 +33,7 @@ import org.onap.cps.spi.exceptions.CpsException; import org.onap.cps.spi.exceptions.DataValidationException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -73,8 +74,8 @@ public class NetworkCmProxyRestExceptionHandler { return buildErrorResponse(HttpStatus.BAD_REQUEST, exception); } - @ExceptionHandler({DataValidationException.class}) - public static ResponseEntity handleDataValidatedExceptions(final DataValidationException exception) { + @ExceptionHandler({DataValidationException.class, HttpMessageNotReadableException.class}) + public static ResponseEntity handleDataValidatedExceptions(final Exception exception) { return buildErrorResponse(HttpStatus.BAD_REQUEST, exception); } diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy index 3c603ed42..079554a22 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy @@ -24,8 +24,9 @@ package org.onap.cps.ncmp.rest.controller import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.TestUtils import org.onap.cps.ncmp.api.NetworkCmProxyDataService -import org.onap.cps.ncmp.api.models.CmHandle import org.onap.cps.ncmp.api.models.DmiPluginRegistration +import org.onap.cps.ncmp.rest.model.RestDmiPluginRegistration +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 @@ -47,46 +48,51 @@ class NetworkCmProxyInventoryControllerSpec extends Specification { @SpringBean NetworkCmProxyDataService mockNetworkCmProxyDataService = Mock() + @SpringBean + RestInputMapper restInputMapper = Mock() + + DmiPluginRegistration mockDmiPluginRegistration = Mock() + + JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper()) + @Value('${rest.api.ncmp-inventory-base-path}/v1') def ncmpBasePathV1 - def 'Register CM Handle Event' () { - given: 'jsonData' - def jsonData = TestUtils.getResourceFileContent('dmi-registration.json') - when: 'post request is performed' + def 'Dmi plugin registration #scenario' () { + given: 'a dmi plugin registration with #scenario' + def jsonData = TestUtils.getResourceFileContent(dmiRegistrationJson) + and: 'the expected rest input as an object' + def expectedRestDmiPluginRegistration = jsonObjectMapper.convertJsonString(jsonData, RestDmiPluginRegistration) + and: 'the converter returns a dmi registration (only for the expected input object)' + restInputMapper.toDmiPluginRegistration(expectedRestDmiPluginRegistration) >> mockDmiPluginRegistration + when: 'post request is performed & registration is called with correct DMI plugin information' def response = mvc.perform( post("$ncmpBasePathV1/ch") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonData) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonData) ).andReturn().response - then: 'the cm handles are registered with the service' - 1 * mockNetworkCmProxyDataService.updateDmiRegistrationAndSyncModule(_) - and: 'response status is No Content' - response.status == HttpStatus.NO_CONTENT.value() + then: 'the converted object is forwarded to the registration service' + 1 * mockNetworkCmProxyDataService.updateDmiRegistrationAndSyncModule(mockDmiPluginRegistration) + and: 'response status is no content' + response.status == HttpStatus.NO_CONTENT.value() + where: 'the following registration json is used' + scenario | dmiRegistrationJson + 'multiple services, added, updated and removed cm handles and many properties' | 'dmi_registration_all_singing_and_dancing.json' + 'updated cm handle with updated/new and removed properties' | 'dmi_registration_updates_only.json' + 'without any properties' | 'dmi_registration_without_properties.json' } - def 'Dmi plugin registration with #scenario' () { - given: 'jsonData, cmHandle, & DmiPluginRegistration' - def jsonData = TestUtils.getResourceFileContent('dmi_registration_combined_valid.json' ) - def cmHandle = new CmHandle(cmHandleID : 'example-name') - def expectedDmiPluginRegistration = new DmiPluginRegistration( - dmiPlugin: 'service1', - dmiDataPlugin: '', - dmiModelPlugin: '', - createdCmHandles: [cmHandle]) + def 'Dmi plugin registration with invalid json' () { + given: 'a dmi plugin registration with #scenario' + def jsonDataWithUndefinedDataLabel = '{"notAdmiPlugin":""}' when: 'post request is performed & registration is called with correct DMI plugin information' def response = mvc.perform( post("$ncmpBasePathV1/ch") .contentType(MediaType.APPLICATION_JSON) - .content(jsonData) + .content(jsonDataWithUndefinedDataLabel) ).andReturn().response - then: 'no NcmpException is thrown & updateDmiRegistrationAndSyncModule is called with correct parameters' - 1 * mockNetworkCmProxyDataService.updateDmiRegistrationAndSyncModule({ - it.getDmiPlugin() == expectedDmiPluginRegistration.getDmiPlugin() - it.getDmiDataPlugin() == expectedDmiPluginRegistration.getDmiDataPlugin() - it.getDmiModelPlugin() == expectedDmiPluginRegistration.getDmiModelPlugin() - it.getCreatedCmHandles().get(0).getCmHandleID() == expectedDmiPluginRegistration.getCreatedCmHandles().get(0).getCmHandleID() - }) + then: 'response status is bad request' + response.status == HttpStatus.BAD_REQUEST.value() } -} +} diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/RestInputMapperSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/RestInputMapperSpec.groovy new file mode 100644 index 000000000..c48a8ed36 --- /dev/null +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/RestInputMapperSpec.groovy @@ -0,0 +1,64 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.rest.controller + +import org.mapstruct.factory.Mappers +import org.onap.cps.ncmp.rest.model.RestCmHandle +import org.onap.cps.ncmp.rest.model.RestDmiPluginRegistration +import spock.lang.Specification + +class RestInputMapperSpec extends Specification { + + def objectUnderTest = Mappers.getMapper(RestInputMapper.class) + + def 'Convert a created REST CM Handle Input to an NCMP Service CM Handle with #scenario'() { + given: 'a rest cm handle input' + def inputRestCmHandle = new RestCmHandle(cmHandle : 'example-id', cmHandleProperties: dmiProperties, + publicCmHandleProperties: publicProperties) + def restDmiPluginRegistration = new RestDmiPluginRegistration( + createdCmHandles: [inputRestCmHandle]) + when: 'to plugin dmi registration is called' + def result = objectUnderTest.toDmiPluginRegistration(restDmiPluginRegistration) + then: 'the result returns the correct number of cm handles' + result.createdCmHandles.size() == 1 + and: 'the converted cm handle has the same id' + result.createdCmHandles[0].cmHandleID == 'example-id' + and: '(empty) properties are converted correctly' + result.createdCmHandles[0].dmiProperties == expectedDmiProperties + result.createdCmHandles[0].publicProperties == expectedPublicProperties + where: 'the following parameters are used' + scenario | dmiProperties | publicProperties || expectedDmiProperties | expectedPublicProperties + 'dmi and public properties' | ['Property-Example': 'example property'] | ['Public-Property-Example': 'public example property'] || ['Property-Example': 'example property'] | ['Public-Property-Example': 'public example property'] + 'no properties' | null | null || [:] | [:] + } + + def 'Handling empty dmi registration'() { + given: 'a rest cm handle input without any cm handles' + def restDmiPluginRegistration = new RestDmiPluginRegistration() + when: 'to plugin dmi registration is called' + def result = objectUnderTest.toDmiPluginRegistration(restDmiPluginRegistration) + then: 'unspecified lists remain as empty lists' + assert result.createdCmHandles == [] + assert result.updatedCmHandles == [] + assert result.removedCmHandles == [] + } + +} diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy index 35544d941..306f546f3 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy @@ -27,6 +27,7 @@ import org.onap.cps.TestUtils import org.onap.cps.ncmp.api.NetworkCmProxyDataService import org.onap.cps.ncmp.api.impl.exception.DmiRequestException import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException +import org.onap.cps.ncmp.rest.controller.RestInputMapper import org.onap.cps.spi.exceptions.CpsException import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.utils.JsonObjectMapper @@ -61,6 +62,9 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification { @SpringBean JsonObjectMapper jsonObjectMapper = Stub() + @SpringBean + RestInputMapper restInputMapper = Mock() + @Value('${rest.api.ncmp-base-path}') def basePathNcmp @@ -105,17 +109,17 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification { } def setupTestException(exception, apiType) { - if (NCMP.equals(apiType)) { + if (NCMP == apiType) { mockNetworkCmProxyDataService.getYangResourcesModuleReferences(*_) >> { throw exception } } mockNetworkCmProxyDataService.updateDmiRegistrationAndSyncModule(*_) >> { throw exception } } def performTestRequest(apiType) { - if (NCMP.equals(apiType)) { + if (NCMP == apiType) { return mvc.perform(get("$dataNodeBaseEndpointNcmp/ch/testCmHandle/modules")).andReturn().response } - def jsonData = TestUtils.getResourceFileContent('dmi-registration.json') + def jsonData = TestUtils.getResourceFileContent('dmi_registration_all_singing_and_dancing.json') return mvc.perform(post("$dataNodeBaseEndpointNcmpInventory/ch").contentType(MediaType.APPLICATION_JSON).content(jsonData)).andReturn().response } diff --git a/cps-ncmp-rest/src/test/resources/dmi-registration.json b/cps-ncmp-rest/src/test/resources/dmi-registration.json deleted file mode 100644 index 4f27e1184..000000000 --- a/cps-ncmp-rest/src/test/resources/dmi-registration.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "dmiPlugin": "onap-dmi-plugin", - "createdCmHandles": [ - { - "cmHandle": "example-name", - "cmHandleProperties": { - "subSystemId" : "system-001" - }, - "publicCmHandleProperties": { - "area" : "south" - } - } - ] -} \ No newline at end of file diff --git a/cps-ncmp-rest/src/test/resources/dmi_registration_all_singing_and_dancing.json b/cps-ncmp-rest/src/test/resources/dmi_registration_all_singing_and_dancing.json new file mode 100644 index 000000000..fd8b56b02 --- /dev/null +++ b/cps-ncmp-rest/src/test/resources/dmi_registration_all_singing_and_dancing.json @@ -0,0 +1,43 @@ +{ + "dmiDataPlugin":"service2", + "dmiModelPlugin":"service3", + "createdCmHandles":[ + { + "cmHandle":"ch1(new)", + "cmHandleProperties":{ + "dmiProp1":"ch1-dmi1", + "dmiProp2":"ch1-dmi2" + }, + "publicCmHandleProperties":{ + "pubProp1":"ch1-pub1", + "pubProp2":"ch1-pub2" + } + }, + { + "cmHandle":"ch2(new)", + "cmHandleProperties":{ + "dmiProp1":"ch2-dmi1", + "dmiProp2":"ch2-dmi2" + }, + "publicCmHandleProperties":{ + "pubProp1":"ch2-pub1", + "pubProp2":"ch2-pub2" + } + } + ], + "updatedCmHandles":[ + { + "cmHandle":"ch3(upd)", + "cmHandleProperties":{ + "dmiProp1":"ch3-dmi1" + }, + "publicCmHandleProperties":{ + "pubProp2":"ch3-pub1" + } + } + ], + "removedCmHandles":[ + "ch4", + "ch5" + ] +} diff --git a/cps-ncmp-rest/src/test/resources/dmi_registration_combined_valid.json b/cps-ncmp-rest/src/test/resources/dmi_registration_combined_valid.json deleted file mode 100644 index bded4f215..000000000 --- a/cps-ncmp-rest/src/test/resources/dmi_registration_combined_valid.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dmiPlugin": "service1", - "dmiDataPlugin": "", - "dmiModelPlugin": "", - "createdCmHandles": [{ - "cmHandle": "example-name" - }] -} \ No newline at end of file diff --git a/cps-ncmp-rest/src/test/resources/dmi_registration_updates_only.json b/cps-ncmp-rest/src/test/resources/dmi_registration_updates_only.json new file mode 100644 index 000000000..58a1a9836 --- /dev/null +++ b/cps-ncmp-rest/src/test/resources/dmi_registration_updates_only.json @@ -0,0 +1,12 @@ +{ + "dmiPlugin": "service1", + "updatedCmHandles":[ + { + "cmHandle":"ch3(upd)", + "cmHandleProperties":{ + "dmiProp1":"ch3-dmi1", + "dmiProp2":null + } + } + ] +} diff --git a/cps-ncmp-rest/src/test/resources/dmi_registration_without_properties.json b/cps-ncmp-rest/src/test/resources/dmi_registration_without_properties.json new file mode 100644 index 000000000..395c098d2 --- /dev/null +++ b/cps-ncmp-rest/src/test/resources/dmi_registration_without_properties.json @@ -0,0 +1,10 @@ +{ + "dmiPlugin":"", + "dmiDataPlugin":"service2", + "dmiModelPlugin":"service3", + "createdCmHandles":[ + { + "cmHandle": "ch1(new)" + } + ] +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java index aac44e43e..446e45b2b 100755 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java @@ -81,15 +81,13 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService public void updateDmiRegistrationAndSyncModule(final DmiPluginRegistration dmiPluginRegistration) { dmiPluginRegistration.validateDmiPluginRegistration(); try { - if (dmiPluginRegistration.getCreatedCmHandles() != null) { + if (!dmiPluginRegistration.getCreatedCmHandles().isEmpty()) { parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration); } - if (dmiPluginRegistration.getUpdatedCmHandles() != null) { + if (!dmiPluginRegistration.getUpdatedCmHandles().isEmpty()) { parseAndUpdateCmHandlesInDmiRegistration(dmiPluginRegistration); } - if (dmiPluginRegistration.getRemovedCmHandles() != null) { - parseAndRemoveCmHandlesInDmiRegistration(dmiPluginRegistration); - } + parseAndRemoveCmHandlesInDmiRegistration(dmiPluginRegistration); } catch (final JsonProcessingException | DataNodeNotFoundException e) { final String errorMessage = String.format( "Error occurred while processing the CM-handle registration request, caused by : [%s]", diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandle.java index 9a9b6faaf..88c6f3376 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandle.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandle.java @@ -20,7 +20,6 @@ package org.onap.cps.ncmp.api.models; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; import java.util.Collections; @@ -39,15 +38,12 @@ import org.springframework.validation.annotation.Validated; @NoArgsConstructor public class CmHandle { - @JsonProperty("cmHandle") private String cmHandleID; @JsonSetter(nulls = Nulls.AS_EMPTY) - @JsonProperty("cmHandleProperties") private Map dmiProperties = Collections.emptyMap(); @JsonSetter(nulls = Nulls.AS_EMPTY) - @JsonProperty("publicCmHandleProperties") private Map publicProperties = Collections.emptyMap(); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java index f1b3888c6..c302f7de5 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java @@ -22,9 +22,8 @@ package org.onap.cps.ncmp.api.models; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.annotation.JsonSetter; -import com.fasterxml.jackson.annotation.Nulls; import com.google.common.base.Strings; +import java.util.Collections; import java.util.List; import lombok.Getter; import lombok.Setter; @@ -39,20 +38,17 @@ import org.onap.cps.ncmp.api.impl.exception.NcmpException; @JsonInclude(Include.NON_NULL) public class DmiPluginRegistration { - @JsonSetter(nulls = Nulls.AS_EMPTY) private String dmiPlugin; - @JsonSetter(nulls = Nulls.AS_EMPTY) private String dmiDataPlugin; - @JsonSetter(nulls = Nulls.AS_EMPTY) private String dmiModelPlugin; - private List createdCmHandles; + private List createdCmHandles = Collections.emptyList(); - private List updatedCmHandles; + private List updatedCmHandles = Collections.emptyList(); - private List removedCmHandles; + private List removedCmHandles = Collections.emptyList(); /** * Validates plugin service names. diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/PersistenceCmHandlesList.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/PersistenceCmHandlesList.java index d4f6e952d..9762ac4e1 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/PersistenceCmHandlesList.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/PersistenceCmHandlesList.java @@ -30,7 +30,7 @@ import lombok.Getter; public class PersistenceCmHandlesList { @JsonProperty("cm-handles") - private List persistenceCmHandles = new ArrayList<>(); + private final List persistenceCmHandles = new ArrayList<>(); /** * Create a PersistenceCmHandleList given all service names and a collection of cmHandles. diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy index 00fda149f..a475f9c34 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy @@ -76,19 +76,19 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { expectedCallsToSaveNode * mockCpsDataService.saveListElements('NCMP-Admin', 'ncmp-dmi-registry', '/dmi-registry', expectedJsonData, noTimestamp) and: 'update data node leaves is called with correct parameters' - expectedCallsToPropertyHandler * mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(updatedCmHandles) + expectedCallsToUpdateCmHandleProperty * mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(updatedCmHandles) and: 'delete schema set is invoked with the correct parameters' expectedCallsToDeleteSchemaSetAndListElement * mockCpsModuleService.deleteSchemaSet('NFP-Operational', 'cmHandle001', CASCADE_DELETE_ALLOWED) and: 'delete list or list element is invoked with the correct parameters' expectedCallsToDeleteSchemaSetAndListElement * mockCpsDataService.deleteListOrListElement('NCMP-Admin', 'ncmp-dmi-registry', "/dmi-registry/cm-handles[@id='cmHandle001']", noTimestamp) where: - scenario | createdCmHandles | updatedCmHandles | removedCmHandles || expectedCallsToSaveNode | expectedCallsToDeleteSchemaSetAndListElement | expectedCallsToPropertyHandler - 'create' | [persistenceCmHandle] | [] | [] || 1 | 0 | 1 + scenario | createdCmHandles | updatedCmHandles | removedCmHandles || expectedCallsToSaveNode | expectedCallsToDeleteSchemaSetAndListElement | expectedCallsToUpdateCmHandleProperty + 'create' | [persistenceCmHandle] | [] | [] || 1 | 0 | 0 'update' | [] | [persistenceCmHandle] | [] || 0 | 0 | 1 - 'delete' | [] | [] | cmHandlesArray || 0 | 1 | 1 + 'delete' | [] | [] | cmHandlesArray || 0 | 1 | 0 'create, update and delete' | [persistenceCmHandle] | [persistenceCmHandle] | cmHandlesArray || 1 | 1 | 1 - 'no valid data' | null | null | null || 0 | 0 | 0 + 'no valid data' | [] | [] | [] || 0 | 0 | 0 } def 'Register a DMI Plugin for the given cm-handle(s) without DMI properties.'() { @@ -107,22 +107,17 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { '/dmi-registry', expectedJsonData, noTimestamp) } - def 'Register a DMI Plugin for a given cm-handle(s) with JSON processing errors during #scenario process.'() { + def 'Register a DMI Plugin for a given cm-handle(s) with JSON processing errors during process.'() { given: 'a registration without cm-handle properties ' NetworkCmProxyDataServiceImpl objectUnderTest = getObjectUnderTestWithModelSyncDisabled() def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:'some-plugin') - dmiPluginRegistration.createdCmHandles = createdCmHandles - dmiPluginRegistration.updatedCmHandles = updatedCmHandles + dmiPluginRegistration.createdCmHandles = [persistenceCmHandle] and: 'an json processing exception occurs' spiedJsonObjectMapper.asJsonString(_) >> { throw (new JsonProcessingException('')) } when: 'registration is updated and modules are synced' objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) then: 'a data validation exception is thrown' thrown(DataValidationException) - where: - scenario | createdCmHandles | updatedCmHandles - 'create' | [persistenceCmHandle] | [] - 'update' | [] | [persistenceCmHandle] } def 'Register a DMI Plugin for the given cm-handle(s) with no data found during delete process.'() { diff --git a/csit/tests/cps-model-sync/cps-model-sync.robot b/csit/tests/cps-model-sync/cps-model-sync.robot index 99b9caa9a..5021f77e9 100644 --- a/csit/tests/cps-model-sync/cps-model-sync.robot +++ b/csit/tests/cps-model-sync/cps-model-sync.robot @@ -34,7 +34,7 @@ ${auth} Basic Y3BzdXNlcjpjcHNyMGNrcyE= ${ncmpInventoryBasePath} /ncmpInventory ${ncmpBasePath} /ncmp ${dmiUrl} http://${DMI_HOST}:${DMI_PORT} -${jsonData} {"dmiPlugin":"${dmiUrl}","dmiDataPlugin":null,"dmiModelPlugin":null,"createdCmHandles":[{"cmHandle":"PNFDemo","cmHandleProperties":{"Book1":"Sci-Fi Book"},"publicCmHandleProperties":{"Contact":"storeemail@bookstore.com"}}],"updatedCmHandles":[{"cmHandle":"PNFDemo","cmHandleProperties":{"Book1":"Romance Book"},"publicCmHandleProperties":{"Contact":"newemailforstore@bookstore.com"}}]} +${jsonData} {"dmiPlugin":"${dmiUrl}","dmiDataPlugin":"","dmiModelPlugin":"","createdCmHandles":[{"cmHandle":"PNFDemo","cmHandleProperties":{"Book1":"Sci-Fi Book"},"publicCmHandleProperties":{"Contact":"storeemail@bookstore.com"}}],"updatedCmHandles":[{"cmHandle":"PNFDemo","cmHandleProperties":{"Book1":"Romance Book"},"publicCmHandleProperties":{"Contact":"newemailforstore@bookstore.com"}}]} *** Test Cases *** Register node, update data node and sync modules.