From 9cfc03f3af00d0128a5b22e32cc5ba439de627b6 Mon Sep 17 00:00:00 2001 From: danielhanrahan Date: Fri, 30 Jun 2023 12:14:07 +0100 Subject: [PATCH] Combine alreadyDefinedException classes Issue-ID: CPS-1774 Signed-off-by: danielhanrahan Change-Id: I52ff9074a9f8188e8635a811b0d2713a97cb4b10 --- .../NetworkCmProxyRestExceptionHandler.java | 3 +- .../NetworkCmProxyRestExceptionHandlerSpec.groovy | 19 +++++---- .../api/impl/NetworkCmProxyDataServiceImpl.java | 6 +-- .../cps/ncmp/init/SubscriptionModelLoader.java | 3 +- ...rkCmProxyDataServiceImplRegistrationSpec.groovy | 10 ++--- .../ncmp/init/SubscriptionModelLoaderSpec.groovy | 3 +- .../rest/exceptions/CpsRestExceptionHandler.java | 5 +-- .../spi/impl/CpsDataPersistenceServiceImpl.java | 14 +++---- .../spi/exceptions/AlreadyDefinedException.java | 46 ++++++++++------------ .../exceptions/AlreadyDefinedExceptionBatch.java | 34 ---------------- .../cps/spi/exceptions/CpsExceptionsSpec.groovy | 9 +++-- .../CpsDataServiceIntegrationSpec.groovy | 20 +++++----- 12 files changed, 64 insertions(+), 108 deletions(-) delete mode 100644 cps-service/src/main/java/org/onap/cps/spi/exceptions/AlreadyDefinedExceptionBatch.java 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 fac948912..7498c5f6c 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 @@ -34,7 +34,6 @@ import org.onap.cps.ncmp.rest.model.DmiErrorMessage; import org.onap.cps.ncmp.rest.model.DmiErrorMessageDmiResponse; import org.onap.cps.ncmp.rest.model.ErrorMessage; import org.onap.cps.spi.exceptions.AlreadyDefinedException; -import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch; import org.onap.cps.spi.exceptions.CpsException; import org.onap.cps.spi.exceptions.DataNodeNotFoundException; import org.onap.cps.spi.exceptions.DataValidationException; @@ -83,7 +82,7 @@ public class NetworkCmProxyRestExceptionHandler { return buildErrorResponse(HttpStatus.BAD_REQUEST, exception); } - @ExceptionHandler({AlreadyDefinedException.class, AlreadyDefinedExceptionBatch.class }) + @ExceptionHandler({AlreadyDefinedException.class}) public static ResponseEntity handleAlreadyDefinedExceptions(final Exception exception) { return buildErrorResponse(HttpStatus.CONFLICT, exception); } 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 6dc537c8d..592f1d165 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 @@ -36,7 +36,6 @@ import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper import org.onap.cps.ncmp.rest.mapper.DataOperationRequestMapper import org.onap.cps.ncmp.rest.util.DeprecationHelper import org.onap.cps.spi.exceptions.AlreadyDefinedException -import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch import org.onap.cps.spi.exceptions.CpsException import org.onap.cps.spi.exceptions.DataNodeNotFoundException import org.onap.cps.spi.exceptions.DataValidationException @@ -116,15 +115,15 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification { then: 'an HTTP response is returned with correct message and details' assertTestResponse(response, expectedErrorCode, expectedErrorMessage, expectedErrorDetails) where: - scenario | exception || expectedErrorDetails | expectedErrorMessage | expectedErrorCode - 'CPS' | new CpsException(sampleErrorMessage, sampleErrorDetails) || sampleErrorDetails | sampleErrorMessage | INTERNAL_SERVER_ERROR - 'NCMP-server' | new ServerNcmpException(sampleErrorMessage, sampleErrorDetails) || null | sampleErrorMessage | INTERNAL_SERVER_ERROR - 'NCMP-client' | new DmiRequestException(sampleErrorMessage, sampleErrorDetails) || null | sampleErrorMessage | BAD_REQUEST - 'DataNode Validation' | new DataNodeNotFoundException('myDataspaceName', 'myAnchorName') || null | 'DataNode not found' | NOT_FOUND - 'other' | new IllegalStateException(sampleErrorMessage) || null | sampleErrorMessage | INTERNAL_SERVER_ERROR - 'Data Node Not Found' | new DataNodeNotFoundException('myDataspaceName', 'myAnchorName') || 'DataNode not found' | 'DataNode not found' | NOT_FOUND - 'Existing entry' | new AlreadyDefinedException('name',null) || 'name already exists' | 'Already defined exception' | CONFLICT - 'Existing entries' | new AlreadyDefinedExceptionBatch(["x[@id='abc']"]) || 'Check logs for details' | null | CONFLICT + scenario | exception || expectedErrorDetails | expectedErrorMessage | expectedErrorCode + 'CPS' | new CpsException(sampleErrorMessage, sampleErrorDetails) || sampleErrorDetails | sampleErrorMessage | INTERNAL_SERVER_ERROR + 'NCMP-server' | new ServerNcmpException(sampleErrorMessage, sampleErrorDetails) || null | sampleErrorMessage | INTERNAL_SERVER_ERROR + 'NCMP-client' | new DmiRequestException(sampleErrorMessage, sampleErrorDetails) || null | sampleErrorMessage | BAD_REQUEST + 'DataNode Validation' | new DataNodeNotFoundException('myDataspaceName', 'myAnchorName') || null | 'DataNode not found' | NOT_FOUND + 'other' | new IllegalStateException(sampleErrorMessage) || null | sampleErrorMessage | INTERNAL_SERVER_ERROR + 'Data Node Not Found' | new DataNodeNotFoundException('myDataspaceName', 'myAnchorName') || 'DataNode not found' | 'DataNode not found' | NOT_FOUND + 'Existing entry' | new AlreadyDefinedException('name',null) || 'name already exists' | 'Already defined exception' | CONFLICT + 'Existing entries' | AlreadyDefinedException.forDataNodes(['A', 'B'], 'myAnchorName') || '2 data node(s) already exist' | 'Already defined exception' | CONFLICT } def 'Post request with exception returns correct HTTP Status.'() { 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 2e9d7c202..6c1a1b464 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 @@ -65,7 +65,7 @@ import org.onap.cps.ncmp.api.models.DmiPluginRegistration; import org.onap.cps.ncmp.api.models.DmiPluginRegistrationResponse; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch; +import org.onap.cps.spi.exceptions.AlreadyDefinedException; import org.onap.cps.spi.exceptions.CpsException; import org.onap.cps.spi.exceptions.DataNodeNotFoundException; import org.onap.cps.spi.exceptions.DataValidationException; @@ -411,9 +411,9 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService try { lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); return CmHandleRegistrationResponse.createSuccessResponses(cmHandleIds); - } catch (final AlreadyDefinedExceptionBatch alreadyDefinedExceptionBatch) { + } catch (final AlreadyDefinedException alreadyDefinedException) { return CmHandleRegistrationResponse.createFailureResponses( - alreadyDefinedExceptionBatch.getAlreadyDefinedXpaths(), + alreadyDefinedException.getAlreadyDefinedObjectNames(), RegistrationError.CM_HANDLE_ALREADY_EXIST); } catch (final Exception exception) { return CmHandleRegistrationResponse.createFailureResponses(cmHandleIds, exception); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/SubscriptionModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/SubscriptionModelLoader.java index 1be5b2cc6..af9ee721c 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/SubscriptionModelLoader.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/SubscriptionModelLoader.java @@ -31,7 +31,6 @@ import org.onap.cps.api.CpsDataService; import org.onap.cps.api.CpsModuleService; import org.onap.cps.ncmp.api.impl.exception.NcmpStartUpException; import org.onap.cps.spi.exceptions.AlreadyDefinedException; -import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch; import org.onap.cps.spi.model.Dataspace; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; @@ -158,7 +157,7 @@ public class SubscriptionModelLoader implements ModelLoader { final String nodeData = "{\"" + dataNodeName + "\":{}}"; try { cpsDataService.saveData(dataspaceName, anchorName, nodeData, OffsetDateTime.now()); - } catch (final AlreadyDefinedExceptionBatch exception) { + } catch (final AlreadyDefinedException exception) { log.info("Creating new data node '{}' failed as data node already exists", dataNodeName); } catch (final Exception exception) { log.debug("Creating data node for subscription model failed: {}", exception.getMessage()); 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 bd63813e7..c5436594a 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 @@ -36,7 +36,7 @@ import org.onap.cps.ncmp.api.inventory.InventoryPersistence import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse import org.onap.cps.ncmp.api.models.DmiPluginRegistration import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle -import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch +import org.onap.cps.spi.exceptions.AlreadyDefinedException import org.onap.cps.spi.exceptions.DataNodeNotFoundException import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.spi.exceptions.SchemaSetNotFoundException @@ -190,7 +190,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { new NcmpServiceCmHandle(cmHandleId: 'cmhandle3')]) and: 'cm-handle creation is successful for 1st and 3rd; failed for 2nd' def xpath = "somePathWithId[@id='cmhandle2']" - mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(*_) >> { throw new AlreadyDefinedExceptionBatch([xpath]) } + mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(*_) >> { throw AlreadyDefinedException.forDataNodes([xpath], 'some-context') } when: 'registration is updated to create cm-handles' def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) then: 'a response is received for all cm-handles' @@ -221,9 +221,9 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { assert it.errorText == expectedErrorText } where: - scenario | exception || expectedError | expectedErrorText - 'cm-handle already exist' | new AlreadyDefinedExceptionBatch(["'path[@id='cmhandle']".toString()]) || CM_HANDLE_ALREADY_EXIST | 'cm-handle already exists' - 'unknown exception while registering cm-handle' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed' + scenario | exception || expectedError | expectedErrorText + 'cm-handle already exist' | AlreadyDefinedException.forDataNodes(["path[@id='cmhandle']"], 'some-context') || CM_HANDLE_ALREADY_EXIST | 'cm-handle already exists' + 'unknown exception while registering cm-handle' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed' } def 'Update CM-Handle: Update Operation Response is added to the response'() { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/SubscriptionModelLoaderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/SubscriptionModelLoaderSpec.groovy index 128895bae..23fa357ee 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/SubscriptionModelLoaderSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/SubscriptionModelLoaderSpec.groovy @@ -28,7 +28,6 @@ import org.onap.cps.api.CpsDataService import org.onap.cps.api.CpsModuleService import org.onap.cps.ncmp.api.impl.exception.NcmpStartUpException import org.onap.cps.spi.exceptions.AlreadyDefinedException -import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.spi.exceptions.SchemaSetNotFoundException import org.onap.cps.spi.model.Dataspace @@ -199,7 +198,7 @@ class SubscriptionModelLoaderSpec extends Specification { def 'Create top level node fails due to an AlreadyDefined exception'() { given: 'the saving of the node data will throw an Already Defined exception' mockCpsDataService.saveData(*_) >> - { throw new AlreadyDefinedExceptionBatch(['/xpath']) } + { throw AlreadyDefinedException.forDataNodes(['/xpath'], "sampleContextName") } when: 'the method to onboard model is called' objectUnderTest.onboardSubscriptionModel(yangResourceToContentMap) then: 'no exception thrown' diff --git a/cps-rest/src/main/java/org/onap/cps/rest/exceptions/CpsRestExceptionHandler.java b/cps-rest/src/main/java/org/onap/cps/rest/exceptions/CpsRestExceptionHandler.java index 0c6edd5b4..5dfd03bf2 100755 --- a/cps-rest/src/main/java/org/onap/cps/rest/exceptions/CpsRestExceptionHandler.java +++ b/cps-rest/src/main/java/org/onap/cps/rest/exceptions/CpsRestExceptionHandler.java @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2020 Pantheon.tech - * Modifications Copyright (C) 2021-2022 Nordix Foundation + * Modifications Copyright (C) 2021-2023 Nordix Foundation * Modifications Copyright (C) 2022 TechMahindra Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,7 +32,6 @@ import org.onap.cps.rest.controller.DataRestController; import org.onap.cps.rest.controller.QueryRestController; import org.onap.cps.rest.model.ErrorMessage; import org.onap.cps.spi.exceptions.AlreadyDefinedException; -import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch; import org.onap.cps.spi.exceptions.CpsAdminException; import org.onap.cps.spi.exceptions.CpsException; import org.onap.cps.spi.exceptions.CpsPathException; @@ -78,7 +77,7 @@ public class CpsRestExceptionHandler { ? HttpStatus.NOT_FOUND : HttpStatus.BAD_REQUEST, exception); } - @ExceptionHandler({DataInUseException.class, AlreadyDefinedException.class, AlreadyDefinedExceptionBatch.class}) + @ExceptionHandler({DataInUseException.class, AlreadyDefinedException.class}) public static ResponseEntity handleDataInUseException(final Exception exception) { return buildErrorResponse(HttpStatus.CONFLICT, exception); } diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java index 7fed534b7..f4afe3d73 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java @@ -52,7 +52,6 @@ import org.onap.cps.spi.entities.AnchorEntity; import org.onap.cps.spi.entities.DataspaceEntity; import org.onap.cps.spi.entities.FragmentEntity; import org.onap.cps.spi.exceptions.AlreadyDefinedException; -import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch; import org.onap.cps.spi.exceptions.ConcurrencyException; import org.onap.cps.spi.exceptions.CpsAdminException; import org.onap.cps.spi.exceptions.CpsPathException; @@ -105,12 +104,12 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService for (final Collection newList : newLists) { try { addChildrenDataNodes(anchorEntity, parentNodeXpath, newList); - } catch (final AlreadyDefinedExceptionBatch e) { - failedXpaths.addAll(e.getAlreadyDefinedXpaths()); + } catch (final AlreadyDefinedException alreadyDefinedException) { + failedXpaths.addAll(alreadyDefinedException.getAlreadyDefinedObjectNames()); } } if (!failedXpaths.isEmpty()) { - throw new AlreadyDefinedExceptionBatch(failedXpaths); + throw AlreadyDefinedException.forDataNodes(failedXpaths, anchorEntity.getName()); } } @@ -122,7 +121,8 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService try { fragmentRepository.save(newChildAsFragmentEntity); } catch (final DataIntegrityViolationException e) { - throw AlreadyDefinedException.forDataNode(newChild.getXpath(), anchorEntity.getName(), e); + throw AlreadyDefinedException.forDataNodes(Collections.singletonList(newChild.getXpath()), + anchorEntity.getName()); } } @@ -156,7 +156,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService } } if (!failedXpaths.isEmpty()) { - throw new AlreadyDefinedExceptionBatch(failedXpaths); + throw AlreadyDefinedException.forDataNodes(failedXpaths, anchorEntity.getName()); } } @@ -189,7 +189,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService } } if (!failedXpaths.isEmpty()) { - throw new AlreadyDefinedExceptionBatch(failedXpaths); + throw AlreadyDefinedException.forDataNodes(failedXpaths, anchorEntity.getName()); } } diff --git a/cps-service/src/main/java/org/onap/cps/spi/exceptions/AlreadyDefinedException.java b/cps-service/src/main/java/org/onap/cps/spi/exceptions/AlreadyDefinedException.java index 0ad48dda2..863bb0f80 100644 --- a/cps-service/src/main/java/org/onap/cps/spi/exceptions/AlreadyDefinedException.java +++ b/cps-service/src/main/java/org/onap/cps/spi/exceptions/AlreadyDefinedException.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation + * Copyright (C) 2021-2023 Nordix Foundation * Modifications Copyright (C) 2021 Pantheon.tech * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,6 +22,8 @@ package org.onap.cps.spi.exceptions; import java.util.Collection; +import java.util.Collections; +import lombok.Getter; /** * Already defined exception. Indicates the cps object with same name already exists. @@ -31,29 +33,28 @@ import java.util.Collection; public class AlreadyDefinedException extends CpsAdminException { private static final long serialVersionUID = 501929839139881112L; + public static final String ALREADY_DEFINED_EXCEPTION_MESSAGE = "Already defined exception"; + + @Getter + private final Collection alreadyDefinedObjectNames; - /** - * Constructor. - * - * @param objectType the object type - * @param objectName the name of the object - * @param contextName the context name e.g. Anchor or Dataspace - * @param cause the cause of the exception - */ private AlreadyDefinedException(final String objectType, final String objectName, final String contextName, final Throwable cause) { - super("Already defined exception", + super(ALREADY_DEFINED_EXCEPTION_MESSAGE, String.format("%s with name %s already exists for %s.", objectType, objectName, contextName), cause); + alreadyDefinedObjectNames = Collections.singletonList(objectName); + } + + private AlreadyDefinedException(final String objectType, final Collection objectNames, + final String contextName) { + super(ALREADY_DEFINED_EXCEPTION_MESSAGE, + String.format("%d %s already exist for %s.", objectNames.size(), objectType, contextName)); + alreadyDefinedObjectNames = objectNames; } - /** - * Constructor. - * - * @param objectName the name of the object - * @param cause the cause of the exception - */ private AlreadyDefinedException(final String objectName, final Throwable cause) { - super("Already defined exception", String.format("%s already exists.", objectName), cause); + super(ALREADY_DEFINED_EXCEPTION_MESSAGE, String.format("%s already exists.", objectName), cause); + alreadyDefinedObjectNames = Collections.singletonList(objectName); } public static AlreadyDefinedException forDataspace(final String dataspaceName, final Throwable cause) { @@ -70,14 +71,7 @@ public class AlreadyDefinedException extends CpsAdminException { return new AlreadyDefinedException("Schema Set", schemaSetName, contextName, cause); } - public static AlreadyDefinedException forDataNode(final String xpath, final String contextName, - final Throwable cause) { - return new AlreadyDefinedException("Data node", xpath, contextName, cause); - } - - public static AlreadyDefinedException forDataNodes(final Collection xpaths, final String contextName, - final Throwable cause) { - final var name = String.format("(one or more) of %s", xpaths); - return new AlreadyDefinedException("Data node", name, contextName, cause); + public static AlreadyDefinedException forDataNodes(final Collection xpaths, final String contextName) { + return new AlreadyDefinedException("data node(s)", xpaths, contextName); } } diff --git a/cps-service/src/main/java/org/onap/cps/spi/exceptions/AlreadyDefinedExceptionBatch.java b/cps-service/src/main/java/org/onap/cps/spi/exceptions/AlreadyDefinedExceptionBatch.java deleted file mode 100644 index 0ba656aa1..000000000 --- a/cps-service/src/main/java/org/onap/cps/spi/exceptions/AlreadyDefinedExceptionBatch.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.spi.exceptions; - -import java.util.Collection; -import lombok.Getter; - -public class AlreadyDefinedExceptionBatch extends RuntimeException { - - @Getter - private final Collection alreadyDefinedXpaths; - - public AlreadyDefinedExceptionBatch(final Collection alreadyDefinedXPaths) { - this.alreadyDefinedXpaths = alreadyDefinedXPaths; - } -} diff --git a/cps-service/src/test/groovy/org/onap/cps/spi/exceptions/CpsExceptionsSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/spi/exceptions/CpsExceptionsSpec.groovy index 5bd367834..8db106334 100755 --- a/cps-service/src/test/groovy/org/onap/cps/spi/exceptions/CpsExceptionsSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/spi/exceptions/CpsExceptionsSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation + * Copyright (C) 2021-2023 Nordix Foundation * Modifications Copyright (C) 2021 Pantheon.tech * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,7 @@ * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ + package org.onap.cps.spi.exceptions import spock.lang.Specification @@ -152,10 +153,10 @@ class CpsExceptionsSpec extends Specification { == "Anchor with name ${anchorName} already exists for ${dataspaceName}." } - def 'Creating a exception that a data node already exists.'() { + def 'Creating a exception that data nodes already exist.'() { expect: 'the exception details contains the correct message with xpath and dataspace name.' - (AlreadyDefinedException.forDataNode(xpath, dataspaceName, rootCause)).details - == "Data node with name ${xpath} already exists for ${dataspaceName}." + (AlreadyDefinedException.forDataNodes([xpath], anchorName)).details + == "1 data node(s) already exist for ${anchorName}." } def 'Creating a exception that a schema set already exists.'() { diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy index 5c9ced34e..351f3106f 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy @@ -24,7 +24,7 @@ package org.onap.cps.integration.functional import org.onap.cps.api.CpsDataService import org.onap.cps.integration.base.FunctionalSpecBase import org.onap.cps.spi.FetchDescendantsOption -import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch +import org.onap.cps.spi.exceptions.AlreadyDefinedException import org.onap.cps.spi.exceptions.AnchorNotFoundException import org.onap.cps.spi.exceptions.CpsAdminException import org.onap.cps.spi.exceptions.CpsPathException @@ -145,8 +145,8 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase { def json = '{"bookstore": {} }' objectUnderTest.saveData(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, json, now) then: 'an exception that (one cps paths is) already defined is thrown ' - def exceptionThrown = thrown(AlreadyDefinedExceptionBatch) - exceptionThrown.alreadyDefinedXpaths == [ '/bookstore' ] as Set + def exceptionThrown = thrown(AlreadyDefinedException) + exceptionThrown.alreadyDefinedObjectNames == ['/bookstore' ] as Set cleanup: restoreBookstoreDataAnchor(1) } @@ -202,8 +202,8 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase { when: 'attempt to save the list element' objectUnderTest.saveListElements(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/bookstore', json, now) then: 'an exception that (one cps paths is) already defined is thrown ' - def exceptionThrown = thrown(AlreadyDefinedExceptionBatch) - exceptionThrown.alreadyDefinedXpaths == [ '/bookstore/categories[@code=\'1\']' ] as Set + def exceptionThrown = thrown(AlreadyDefinedException) + exceptionThrown.alreadyDefinedObjectNames == ['/bookstore/categories[@code=\'1\']' ] as Set and: 'there is now one extra data nodes' assert originalCountBookstoreChildNodes + 1 == countDataNodesInBookstore() cleanup: @@ -246,8 +246,8 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase { when: 'the batches of new list element(s) are saved' objectUnderTest.saveListElementsBatch(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/bookstore', [jsonNewElement, jsonExistingElement], now) then: 'an already defined (batch) exception is thrown for the existing path' - def exceptionThrown = thrown(AlreadyDefinedExceptionBatch) - assert exceptionThrown.alreadyDefinedXpaths == [ '/bookstore/categories[@code=\'1\']' ] as Set + def exceptionThrown = thrown(AlreadyDefinedException) + assert exceptionThrown.alreadyDefinedObjectNames == ['/bookstore/categories[@code=\'1\']' ] as Set and: 'there is now one extra data node' assert originalCountBookstoreChildNodes + 1 == countDataNodesInBookstore() cleanup: @@ -269,7 +269,7 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase { where: 'the following data is used' scenario | parentXpath | json || expectedException 'parent does not exist' | '/bookstore/categories[@code="unknown"]' | '{"books": [ {"title":"new"} ] } ' || DataNodeNotFoundException - 'already existing child' | '/bookstore' | '{"categories": [ {"code":"1"} ] }' || AlreadyDefinedExceptionBatch + 'already existing child' | '/bookstore' | '{"categories": [ {"code":"1"} ] }' || AlreadyDefinedException } def 'Add multiple child data nodes with partial success.'() { @@ -278,8 +278,8 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase { when: 'attempt to add the elements' objectUnderTest.saveData(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, '/bookstore', json, now) then: 'an already defined (batch) exception is thrown for the existing path' - def thrown = thrown(AlreadyDefinedExceptionBatch) - assert thrown.alreadyDefinedXpaths == [ "/bookstore/categories[@code='1']" ] as Set + def thrown = thrown(AlreadyDefinedException) + assert thrown.alreadyDefinedObjectNames == [ "/bookstore/categories[@code='1']" ] as Set and: 'the new data node has been added i.e. can be retrieved' assert objectUnderTest.getDataNodes(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, '/bookstore/categories[@code="new"]', DIRECT_CHILDREN_ONLY).size() == 1 } -- 2.16.6