diff options
8 files changed, 57 insertions, 47 deletions
diff --git a/cps-dependencies/pom.xml b/cps-dependencies/pom.xml index 5c2ff565ee..80513ba94b 100755 --- a/cps-dependencies/pom.xml +++ b/cps-dependencies/pom.xml @@ -77,6 +77,11 @@ <scope>import</scope> </dependency> <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-web</artifactId> + <version>5.3.13</version> + </dependency> + <dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yangtools-artifacts</artifactId> <version>6.0.1</version> @@ -94,6 +99,11 @@ <version>3.0.0</version> </dependency> <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.8.9</version> + </dependency> + <dependency> <groupId>com.vladmihalcea</groupId> <artifactId>hibernate-types-52</artifactId> <version>2.10.0</version> diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java index 5b89d9f4c4..50b27207ee 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. + * Copyright (C) 2020-2022 Nordix Foundation. * Modifications Copyright (C) 2020-2022 Bell Canada. * Modifications Copyright (C) 2021 Pantheon.tech * ================================================================================ @@ -147,20 +147,24 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic private void validateDataspaceAndModuleNames(final String dataspaceName, final Collection<String> inputModuleNames) { - final Collection<String> retrievedModuleNames = - yangResourceRepository.findAllModuleReferences(dataspaceName, inputModuleNames) + final Collection<String> retrievedModuleReferences = + yangResourceRepository.findAllModuleReferencesByDataspaceAndModuleNames(dataspaceName, inputModuleNames) .stream().map(YangResourceModuleReference::getModuleName) .collect(Collectors.toList()); - if (retrievedModuleNames.isEmpty()) { - dataspaceRepository.getByName(dataspaceName); + if (retrievedModuleReferences.isEmpty()) { + verifyDataspaceName(dataspaceName); } - if (inputModuleNames.size() > retrievedModuleNames.size()) { + if (inputModuleNames.size() > retrievedModuleReferences.size()) { final List<String> moduleNamesNotFound = inputModuleNames.stream() - .filter(moduleName -> !retrievedModuleNames.contains(moduleName)) + .filter(moduleName -> !retrievedModuleReferences.contains(moduleName)) .collect(Collectors.toList()); if (!moduleNamesNotFound.isEmpty()) { throw new ModuleNamesNotFoundException(dataspaceName, moduleNamesNotFound); } } } + + private void verifyDataspaceName(final String dataspaceName) { + dataspaceRepository.getByName(dataspaceName); + } } 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 f22d83b981..78862d7233 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 @@ -337,7 +337,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService deleteDataNodes(dataspaceName, anchorName); targetDeleted = true; } else { - if (isContainerNodeXpath(targetXpath)) { + if (isRootContainerNodeXpath(targetXpath)) { parentNodeXpath = targetXpath; } else { parentNodeXpath = targetXpath.substring(0, targetXpath.lastIndexOf('/')); @@ -423,7 +423,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService return !existingListElementsByXpath.containsKey(replacementDataNode.getXpath()); } - private static boolean isContainerNodeXpath(final String xpath) { + private static boolean isRootContainerNodeXpath(final String xpath) { return 0 == xpath.lastIndexOf('/'); } diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java index ec720b8a96..3719256fcd 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java @@ -106,7 +106,7 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ @Override public Collection<ModuleReference> getYangResourceModuleReferences(final String dataspaceName) { final Set<YangResourceModuleReference> yangResourceModuleReferenceList = - yangResourceRepository.findAllModuleReferences(dataspaceName); + yangResourceRepository.findAllModuleReferencesByDataspace(dataspaceName); return yangResourceModuleReferenceList.stream().map(CpsModulePersistenceServiceImpl::toModuleReference) .collect(Collectors.toList()); } @@ -116,7 +116,7 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ final String anchorName) { final Set<YangResourceModuleReference> yangResourceModuleReferenceList = yangResourceRepository - .findAllModuleReferences(dataspaceName, anchorName); + .findAllModuleReferencesByDataspaceAndAnchor(dataspaceName, anchorName); return yangResourceModuleReferenceList.stream().map(CpsModulePersistenceServiceImpl::toModuleReference) .collect(Collectors.toList()); } diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/ModuleReferenceRepositoryImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/ModuleReferenceRepositoryImpl.java index f4078ffec7..0e79deb8e8 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/repository/ModuleReferenceRepositoryImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/ModuleReferenceRepositoryImpl.java @@ -45,11 +45,11 @@ public class ModuleReferenceRepositoryImpl implements ModuleReferenceQuery { final Collection<ModuleReference> moduleReferencesToCheck) { if (moduleReferencesToCheck == null || moduleReferencesToCheck.isEmpty()) { - return Collections.EMPTY_LIST; + return Collections.emptyList(); } final String tempTableName = "moduleReferencesToCheckTemp" - + UUID.randomUUID().toString().replaceAll("-", ""); + + UUID.randomUUID().toString().replace("-", ""); createTemporaryTable(tempTableName); insertDataIntoTable(tempTableName, moduleReferencesToCheck); diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java index 895937b60a..5e9c47429b 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java @@ -49,7 +49,7 @@ public interface YangResourceRepository extends JpaRepository<YangResourceEntity + "JOIN yang_resource ON yang_resource.id = schema_set_yang_resources.yang_resource_id\n" + "WHERE\n" + "dataspace.name = :dataspaceName", nativeQuery = true) - Set<YangResourceModuleReference> findAllModuleReferences(@Param("dataspaceName") String dataspaceName); + Set<YangResourceModuleReference> findAllModuleReferencesByDataspace(@Param("dataspaceName") String dataspaceName); @Query(value = "SELECT DISTINCT\n" + "yang_resource.module_Name AS module_name,\n" @@ -64,7 +64,7 @@ public interface YangResourceRepository extends JpaRepository<YangResourceEntity + "WHERE\n" + "dataspace.name = :dataspaceName AND\n" + "anchor.name =:anchorName", nativeQuery = true) - Set<YangResourceModuleReference> findAllModuleReferences( + Set<YangResourceModuleReference> findAllModuleReferencesByDataspaceAndAnchor( @Param("dataspaceName") String dataspaceName, @Param("anchorName") String anchorName); @Query(value = "SELECT DISTINCT\n" @@ -77,8 +77,8 @@ public interface YangResourceRepository extends JpaRepository<YangResourceEntity + "JOIN yang_resource ON yang_resource.id = schema_set_yang_resources.yang_resource_id\n" + "WHERE\n" + "dataspace.name = :dataspaceName and yang_resource.module_Name IN (:moduleNames)", nativeQuery = true) - Set<YangResourceModuleReference> findAllModuleReferences(@Param("dataspaceName") String dataspaceName, - @Param("moduleNames") Collection<String> moduleNames); + Set<YangResourceModuleReference> findAllModuleReferencesByDataspaceAndModuleNames( + @Param("dataspaceName") String dataspaceName, @Param("moduleNames") Collection<String> moduleNames); @Query(value = "SELECT id FROM yang_resource WHERE module_name=:name and revision=:revision", nativeQuery = true) diff --git a/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java b/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java index 5ad59df2aa..5e26a22045 100644 --- a/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java +++ b/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java @@ -37,8 +37,6 @@ import org.springframework.stereotype.Service; @Slf4j public class NotificationService { - private static final String ROOT_NODE_XPATH = "/"; - private NotificationProperties notificationProperties; private NotificationPublisher notificationPublisher; private CpsDataUpdatedEventFactory cpsDataUpdatedEventFactory; @@ -120,7 +118,15 @@ public class NotificationService { } private Operation getRootNodeOperation(final String xpath, final Operation operation) { - return ROOT_NODE_XPATH.equals(xpath) ? operation : Operation.UPDATE; + return isRootXpath(xpath) || isRootContainerNodeXpath(xpath) ? operation : Operation.UPDATE; + } + + private static boolean isRootXpath(final String xpath) { + return "/".equals(xpath) || "".equals(xpath); + } + + private static boolean isRootContainerNodeXpath(final String xpath) { + return 0 == xpath.lastIndexOf('/'); } } diff --git a/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy index c20bdeea7c..6ef6874b33 100644 --- a/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy @@ -90,35 +90,15 @@ class NotificationServiceSpec extends Specification { 'dataspace name matches filter' | 'my-dataspace-published' || 1 } - def 'Send UPDATE operation when non-root data nodes are changed.'() { - given: 'notification is enabled' - spyNotificationProperties.isEnabled() >> true - and: 'event factory creates event if operation is UPDATE' - def cpsDataUpdatedEvent = new CpsDataUpdatedEvent() - mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(anchor, myObservedTimestamp, - Operation.UPDATE) >> cpsDataUpdatedEvent - when: 'dataUpdatedEvent is received for non-root xpath' - def future = objectUnderTest.processDataUpdatedEvent(anchor, myObservedTimestamp, '/non-root-node', - operation) - and: 'wait for async processing to complete' - future.get(10, TimeUnit.SECONDS) - then: 'async process completed successfully' - future.isDone() - and: 'notification is sent' - 1 * mockNotificationPublisher.sendNotification(cpsDataUpdatedEvent) - where: - operation << [Operation.CREATE, Operation.UPDATE, Operation.DELETE] - } - - def 'Send same operation when root nodes are changed.'() { + def '#scenario are changed with xpath #xpath and operation #operation'() { given: 'notification is enabled' spyNotificationProperties.isEnabled() >> true and: 'event factory creates event if operation is #operation' def cpsDataUpdatedEvent = new CpsDataUpdatedEvent() - mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(anchor, myObservedTimestamp, operation) >> + mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(anchor, myObservedTimestamp, expectedOperationInEvent) >> cpsDataUpdatedEvent - when: 'dataUpdatedEvent is received for root xpath' - def future = objectUnderTest.processDataUpdatedEvent(anchor, myObservedTimestamp, '/', operation) + when: 'dataUpdatedEvent is received for #xpath' + def future = objectUnderTest.processDataUpdatedEvent(anchor, myObservedTimestamp, xpath, operation) and: 'wait for async processing to complete' future.get(10, TimeUnit.SECONDS) then: 'async process completed successfully' @@ -126,10 +106,21 @@ class NotificationServiceSpec extends Specification { and: 'notification is sent' 1 * mockNotificationPublisher.sendNotification(cpsDataUpdatedEvent) where: - operation << [Operation.CREATE, Operation.UPDATE, Operation.DELETE] + scenario | xpath | operation || expectedOperationInEvent + 'Same event is sent when root nodes' | '' | Operation.CREATE || Operation.CREATE + 'Same event is sent when root nodes' | '' | Operation.UPDATE || Operation.UPDATE + 'Same event is sent when root nodes' | '' | Operation.DELETE || Operation.DELETE + 'Same event is sent when root nodes' | '/' | Operation.CREATE || Operation.CREATE + 'Same event is sent when root nodes' | '/' | Operation.UPDATE || Operation.UPDATE + 'Same event is sent when root nodes' | '/' | Operation.DELETE || Operation.DELETE + 'Same event is sent when container nodes' | '/parent' | Operation.CREATE || Operation.CREATE + 'Same event is sent when container nodes' | '/parent' | Operation.UPDATE || Operation.UPDATE + 'Same event is sent when container nodes' | '/parent' | Operation.DELETE || Operation.DELETE + 'UPDATE event is sent when non root nodes' | '/parent/child' | Operation.CREATE || Operation.UPDATE + 'UPDATE event is sent when non root nodes' | '/parent/child' | Operation.UPDATE || Operation.UPDATE + 'UPDATE event is sent when non root nodes' | '/parent/child' | Operation.DELETE || Operation.UPDATE } - def 'Error handling in notification service.'() { given: 'notification is enabled' spyNotificationProperties.isEnabled() >> true @@ -146,5 +137,4 @@ class NotificationServiceSpec extends Specification { notThrown Exception 1 * spyNotificationErrorHandler.onException(_, _, _, '/', Operation.CREATE) } - } |