Bug fix for delete data node not working for root node 97/127397/6
authorputhuparambil.aditya <aditya.puthuparambil@bell.ca>
Tue, 1 Mar 2022 11:51:20 +0000 (11:51 +0000)
committerputhuparambil.aditya <aditya.puthuparambil@bell.ca>
Thu, 3 Mar 2022 14:10:15 +0000 (14:10 +0000)
Fixing event for deletion of container node
Fixing event for deletion of root node when '' is passed as xpath

Issue-ID: CPS-895
Signed-off-by: puthuparambil.aditya <aditya.puthuparambil@bell.ca>
Change-Id: I0676aec29e7b7e12bef2300219207ddc22414daa

cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java
cps-service/src/main/java/org/onap/cps/notification/NotificationService.java
cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy

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 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)
     }
-
 }