Merge "Update dmi-registry yang to support cmHandle State"
authorBruno Sakoto <bruno.sakoto@bell.ca>
Thu, 3 Mar 2022 23:28:44 +0000 (23:28 +0000)
committerGerrit Code Review <gerrit@onap.org>
Thu, 3 Mar 2022 23:28:44 +0000 (23:28 +0000)
cps-dependencies/pom.xml
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java
cps-ri/src/main/java/org/onap/cps/spi/repository/ModuleReferenceRepositoryImpl.java
cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java
cps-service/src/main/java/org/onap/cps/notification/NotificationService.java
cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy

index 5c2ff56..80513ba 100755 (executable)
                 <type>pom</type>
                 <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>
                 <artifactId>springfox-boot-starter</artifactId>
                 <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>
index 5b89d9f..50b2720 100755 (executable)
@@ -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);
+    }
 }
index f22d83b..78862d7 100644 (file)
@@ -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('/');
     }
 
index ec720b8..3719256 100755 (executable)
@@ -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());
     }
index f4078ff..0e79deb 100644 (file)
@@ -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);
index 895937b..5e9c474 100644 (file)
@@ -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)
index 5ad59df..5e26a22 100644 (file)
@@ -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('/');
     }
 
 }
index c20bdee..6ef6874 100644 (file)
@@ -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)
     }
-
 }