Refactor Delete Anchor functionality 79/126679/16
authorRenu Kumari <renu.kumari@bell.ca>
Thu, 20 Jan 2022 18:30:05 +0000 (13:30 -0500)
committerRenu Kumari <renu.kumari@bell.ca>
Wed, 2 Feb 2022 15:31:06 +0000 (10:31 -0500)
- Added a delete DataNode functionality in the CpsDataService
- CpsAdminService uses CpsDataService to delete DataNodes

Issue-ID: CPS-791
Signed-off-by: Renu Kumari <renu.kumari@bell.ca>
Change-Id: I090500dbc4a2ccf061dc105f979472137d43b06d

12 files changed:
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/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy
cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy
cps-ri/src/test/resources/application.yml
cps-service/src/main/java/org/onap/cps/api/CpsDataService.java
cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java
cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java
cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAdminServiceImplSpec.groovy
cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy

index 51b2482..5b89d9f 100755 (executable)
@@ -24,9 +24,9 @@ package org.onap.cps.spi.impl;
 
 import java.util.Collection;
 import java.util.List;
-import java.util.Set;
 import java.util.stream.Collectors;
 import javax.transaction.Transactional;
+import lombok.AllArgsConstructor;
 import org.onap.cps.spi.CpsAdminPersistenceService;
 import org.onap.cps.spi.entities.AnchorEntity;
 import org.onap.cps.spi.entities.DataspaceEntity;
@@ -38,30 +38,19 @@ import org.onap.cps.spi.exceptions.ModuleNamesNotFoundException;
 import org.onap.cps.spi.model.Anchor;
 import org.onap.cps.spi.repository.AnchorRepository;
 import org.onap.cps.spi.repository.DataspaceRepository;
-import org.onap.cps.spi.repository.FragmentRepository;
 import org.onap.cps.spi.repository.SchemaSetRepository;
 import org.onap.cps.spi.repository.YangResourceRepository;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.DataIntegrityViolationException;
 import org.springframework.stereotype.Component;
 
 @Component
+@AllArgsConstructor
 public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceService {
 
-    @Autowired
-    private DataspaceRepository dataspaceRepository;
-
-    @Autowired
-    private AnchorRepository anchorRepository;
-
-    @Autowired
-    private SchemaSetRepository schemaSetRepository;
-
-    @Autowired
-    private FragmentRepository fragmentRepository;
-
-    @Autowired
-    private YangResourceRepository yangResourceRepository;
+    private final DataspaceRepository dataspaceRepository;
+    private final AnchorRepository anchorRepository;
+    private final SchemaSetRepository schemaSetRepository;
+    private final YangResourceRepository yangResourceRepository;
 
     @Override
     public void createDataspace(final String dataspaceName) {
@@ -140,7 +129,6 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic
     @Override
     public void deleteAnchor(final String dataspaceName, final String anchorName) {
         final var anchorEntity = getAnchorEntity(dataspaceName, anchorName);
-        fragmentRepository.deleteByAnchorIn(Set.of(anchorEntity));
         anchorRepository.delete(anchorEntity);
     }
 
index c6e28ab..85b0cb7 100644 (file)
@@ -2,7 +2,7 @@
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021-2022 Nordix Foundation
  *  Modifications Copyright (C) 2021 Pantheon.tech
- *  Modifications Copyright (C) 2020-2021 Bell Canada.
+ *  Modifications Copyright (C) 2020-2022 Bell Canada.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -319,6 +319,14 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
         fragmentRepository.save(parentEntity);
     }
 
+    @Override
+    @Transactional
+    public void deleteDataNodes(final String dataspaceName, final String anchorName) {
+        final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+        anchorRepository.findByDataspaceAndName(dataspaceEntity, anchorName)
+            .ifPresent(
+                anchorEntity -> fragmentRepository.deleteByAnchorIn(Set.of(anchorEntity)));
+    }
 
     @Override
     @Transactional
index 2218014..063bd5b 100644 (file)
@@ -41,8 +41,7 @@ class CpsAdminPersistenceServiceSpec extends CpsPersistenceSpecBase {
     static final String SET_DATA = '/data/anchor.sql'
     static final String SAMPLE_DATA_FOR_ANCHORS_WITH_MODULES = '/data/anchors-schemaset-modules.sql'
     static final String DATASPACE_WITH_NO_DATA = 'DATASPACE-002-NO-DATA'
-    static final Integer DELETED_ANCHOR_ID = 3001
-    static final Long DELETED_FRAGMENT_ID = 4001
+    static final Integer DELETED_ANCHOR_ID = 3002
 
     @Sql(CLEAR_DATA)
     def 'Create and retrieve a new dataspace.'() {
@@ -150,10 +149,9 @@ class CpsAdminPersistenceServiceSpec extends CpsPersistenceSpecBase {
     @Sql([CLEAR_DATA, SET_DATA])
     def 'Delete anchor'() {
         when: 'delete anchor action is invoked'
-            objectUnderTest.deleteAnchor(DATASPACE_NAME, ANCHOR_NAME1)
-        then: 'anchor and associated data fragment are deleted'
+            objectUnderTest.deleteAnchor(DATASPACE_NAME, ANCHOR_NAME2)
+        then: 'anchor is deleted'
             assert anchorRepository.findById(DELETED_ANCHOR_ID).isEmpty()
-            assert fragmentRepository.findById(DELETED_FRAGMENT_ID).isEmpty()
     }
 
     @Sql([CLEAR_DATA, SET_DATA])
index 69e6aa8..3150188 100755 (executable)
@@ -2,7 +2,7 @@
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021-2022 Nordix Foundation
  *  Modifications Copyright (C) 2021 Pantheon.tech
- *  Modifications Copyright (C) 2021 Bell Canada.
+ *  Modifications Copyright (C) 2021-2022 Bell Canada.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -34,7 +34,6 @@ import org.onap.cps.spi.model.DataNodeBuilder
 import org.onap.cps.utils.JsonObjectMapper
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.test.context.jdbc.Sql
-
 import javax.validation.ConstraintViolationException
 import java.util.stream.Collectors
 
@@ -49,6 +48,8 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase {
     static final JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
 
     static final String SET_DATA = '/data/fragment.sql'
+    static final int DATASPACE_1001_ID = 1001L
+    static final int ANCHOR_3003_ID = 3003L
     static final long ID_DATA_NODE_WITH_DESCENDANTS = 4001
     static final String XPATH_DATA_NODE_WITH_DESCENDANTS = '/parent-1'
     static final String XPATH_DATA_NODE_WITH_LEAVES = '/parent-100'
@@ -540,6 +541,20 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase {
             'invalid list element'                          | '/parent-206/child-206/grand-child-206@key="A"]'
     }
 
+    @Sql([CLEAR_DATA, SET_DATA])
+    def 'Delete data node for an anchor.'() {
+        given: 'a data-node exists for an anchor'
+            assert fragmentsExistInDB(DATASPACE_1001_ID, ANCHOR_3003_ID)
+        when: 'data nodes are deleted '
+            objectUnderTest.deleteDataNodes(DATASPACE_NAME, ANCHOR_NAME3)
+        then: 'all data-nodes are deleted successfully'
+            assert !fragmentsExistInDB(DATASPACE_1001_ID, ANCHOR_3003_ID)
+    }
+
+    def fragmentsExistInDB(dataSpaceId, anchorId) {
+        !fragmentRepository.findRootsByDataspaceAndAnchor(dataSpaceId, anchorId).isEmpty()
+    }
+
     static Collection<DataNode> toDataNodes(xpaths) {
         return xpaths.collect { new DataNodeBuilder().withXpath(it).build() }
     }
index 73292bb..18e6ed6 100644 (file)
 spring:
   jpa:
     ddl-auto: create
+    show-sql: true
     properties:
       hibernate:
         enable_lazy_load_no_trans: true
         dialect: org.hibernate.dialect.PostgreSQLDialect
+        format_sql: true
 
   datasource:
     url: ${DB_URL}
index f455e47..d2482d5 100644 (file)
@@ -2,7 +2,7 @@
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2020 Nordix Foundation
  *  Modifications Copyright (C) 2021 Pantheon.tech
- *  Modifications Copyright (C) 2021 Bell Canada
+ *  Modifications Copyright (C) 2021-2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@
 package org.onap.cps.api;
 
 import java.time.OffsetDateTime;
-import org.checkerframework.checker.nullness.qual.NonNull;
 import org.onap.cps.spi.FetchDescendantsOption;
 import org.onap.cps.spi.model.DataNode;
 
@@ -40,8 +39,7 @@ public interface CpsDataService {
      * @param jsonData      json data
      * @param observedTimestamp observedTimestamp
      */
-    void saveData(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull String jsonData,
-        OffsetDateTime observedTimestamp);
+    void saveData(String dataspaceName, String anchorName, String jsonData, OffsetDateTime observedTimestamp);
 
     /**
      * Persists child data fragment under existing data node for the given anchor and dataspace.
@@ -52,8 +50,8 @@ public interface CpsDataService {
      * @param jsonData        json data
      * @param observedTimestamp observedTimestamp
      */
-    void saveData(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull String parentNodeXpath,
-        @NonNull String jsonData, OffsetDateTime observedTimestamp);
+    void saveData(String dataspaceName, String anchorName, String parentNodeXpath, String jsonData,
+        OffsetDateTime observedTimestamp);
 
     /**
      * Persists child data fragment representing one or more list elements under existing data node for the
@@ -65,9 +63,8 @@ public interface CpsDataService {
      * @param jsonData          json data representing list element(s)
      * @param observedTimestamp observedTimestamp
      */
-    void saveListElements(@NonNull String dataspaceName, @NonNull String anchorName,
-                              @NonNull String parentNodeXpath,
-                              @NonNull String jsonData, OffsetDateTime observedTimestamp);
+    void saveListElements(String dataspaceName, String anchorName, String parentNodeXpath, String jsonData,
+        OffsetDateTime observedTimestamp);
 
     /**
      * Retrieves datanode by XPath for given dataspace and anchor.
@@ -79,8 +76,8 @@ public interface CpsDataService {
      *                               (recursively) as well
      * @return data node object
      */
-    DataNode getDataNode(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull String xpath,
-        @NonNull FetchDescendantsOption fetchDescendantsOption);
+    DataNode getDataNode(String dataspaceName, String anchorName, String xpath,
+        FetchDescendantsOption fetchDescendantsOption);
 
     /**
      * Updates data node for given dataspace and anchor using xpath to parent node.
@@ -91,8 +88,8 @@ public interface CpsDataService {
      * @param jsonData        json data
      * @param observedTimestamp observedTimestamp
      */
-    void updateNodeLeaves(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull String parentNodeXpath,
-        @NonNull String jsonData, OffsetDateTime observedTimestamp);
+    void updateNodeLeaves(String dataspaceName, String anchorName, String parentNodeXpath, String jsonData,
+        OffsetDateTime observedTimestamp);
 
     /**
      * Replaces existing data node content including descendants.
@@ -103,8 +100,8 @@ public interface CpsDataService {
      * @param jsonData        json data
      * @param observedTimestamp observedTimestamp
      */
-    void replaceNodeTree(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull String parentNodeXpath,
-        @NonNull String jsonData, OffsetDateTime observedTimestamp);
+    void replaceNodeTree(String dataspaceName, String anchorName, String parentNodeXpath, String jsonData,
+        OffsetDateTime observedTimestamp);
 
     /**
      * Replaces list content by removing all existing elements and inserting the given new elements as json
@@ -116,8 +113,8 @@ public interface CpsDataService {
      * @param jsonData          json data representing the new list elements
      * @param observedTimestamp observedTimestamp
      */
-    void replaceListContent(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull String parentNodeXpath,
-                            @NonNull String jsonData, OffsetDateTime observedTimestamp);
+    void replaceListContent(String dataspaceName, String anchorName, String parentNodeXpath, String jsonData,
+        OffsetDateTime observedTimestamp);
 
     /**
      * Deletes data node for given anchor and dataspace.
@@ -127,8 +124,17 @@ public interface CpsDataService {
      * @param dataNodeXpath data node xpath
      * @param observedTimestamp observed timestamp
      */
-    void deleteDataNode(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull String dataNodeXpath,
-                        OffsetDateTime observedTimestamp);
+    void deleteDataNode(String dataspaceName, String anchorName, String dataNodeXpath,
+        OffsetDateTime observedTimestamp);
+
+    /**
+     * Deletes all data nodes for a given anchor in a dataspace.
+     *
+     * @param dataspaceName     dataspace name
+     * @param anchorName       anchor name
+     * @param observedTimestamp observed timestamp
+     */
+    void deleteDataNodes(String dataspaceName, String anchorName, OffsetDateTime observedTimestamp);
 
     /**
      * Deletes a list or a list-element under given anchor and dataspace.
@@ -138,8 +144,8 @@ public interface CpsDataService {
      * @param listElementXpath list element xpath
      * @param observedTimestamp observedTimestamp
      */
-    void deleteListOrListElement(@NonNull String dataspaceName, @NonNull String anchorName,
-                             @NonNull String listElementXpath, OffsetDateTime observedTimestamp);
+    void deleteListOrListElement(String dataspaceName, String anchorName, String listElementXpath,
+        OffsetDateTime observedTimestamp);
 
     /**
      * Updates leaves of DataNode for given dataspace and anchor using xpath, along with the leaves of each Child Data
index d30a657..1013add 100755 (executable)
 
 package org.onap.cps.api.impl;
 
+import java.time.OffsetDateTime;
 import java.util.Collection;
 import java.util.stream.Collectors;
+import lombok.AllArgsConstructor;
 import org.onap.cps.api.CpsAdminService;
+import org.onap.cps.api.CpsDataService;
 import org.onap.cps.spi.CpsAdminPersistenceService;
 import org.onap.cps.spi.model.Anchor;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Component;
 
 @Component("CpsAdminServiceImpl")
+@AllArgsConstructor(onConstructor = @__(@Lazy))
 public class CpsAdminServiceImpl implements CpsAdminService {
 
-    @Autowired
-    private CpsAdminPersistenceService cpsAdminPersistenceService;
+    private final CpsAdminPersistenceService cpsAdminPersistenceService;
+    @Lazy
+    private final CpsDataService cpsDataService;
 
     @Override
     public void createDataspace(final String dataspaceName) {
@@ -68,6 +73,7 @@ public class CpsAdminServiceImpl implements CpsAdminService {
 
     @Override
     public void deleteAnchor(final String dataspaceName, final String anchorName) {
+        cpsDataService.deleteDataNodes(dataspaceName, anchorName, OffsetDateTime.now());
         cpsAdminPersistenceService.deleteAnchor(dataspaceName, anchorName);
     }
 
index a23bc95..e292bbe 100755 (executable)
@@ -24,6 +24,7 @@ package org.onap.cps.api.impl;
 
 import java.time.OffsetDateTime;
 import java.util.Collection;
+import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.api.CpsAdminService;
 import org.onap.cps.api.CpsDataService;
@@ -37,26 +38,19 @@ import org.onap.cps.spi.model.DataNodeBuilder;
 import org.onap.cps.utils.YangUtils;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 @Service
 @Slf4j
+@AllArgsConstructor
 public class CpsDataServiceImpl implements CpsDataService {
 
     private static final String ROOT_NODE_XPATH = "/";
 
-    @Autowired
-    private CpsDataPersistenceService cpsDataPersistenceService;
-
-    @Autowired
-    private CpsAdminService cpsAdminService;
-
-    @Autowired
-    private YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache;
-
-    @Autowired
-    private NotificationService notificationService;
+    private final CpsDataPersistenceService cpsDataPersistenceService;
+    private final CpsAdminService cpsAdminService;
+    private final YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache;
+    private final NotificationService notificationService;
 
     @Override
     public void saveData(final String dataspaceName, final String anchorName, final String jsonData,
@@ -137,6 +131,12 @@ public class CpsDataServiceImpl implements CpsDataService {
         processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, dataNodeXpath, Operation.DELETE);
     }
 
+    @Override
+    public void deleteDataNodes(final String dataspaceName, final String anchorName,
+        final OffsetDateTime observedTimestamp) {
+        cpsDataPersistenceService.deleteDataNodes(dataspaceName, anchorName);
+    }
+
     @Override
     public void deleteListOrListElement(final String dataspaceName, final String anchorName, final String listNodeXpath,
         final OffsetDateTime observedTimestamp) {
index b8c472f..fd65886 100644 (file)
@@ -2,6 +2,7 @@
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2020 Nordix Foundation.
  *  Modifications Copyright (C) 2021 Pantheon.tech
+ *  Modifications Copyright (C) 2022 Bell Canada
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,7 +24,6 @@ package org.onap.cps.spi;
 
 import java.util.Collection;
 import java.util.Map;
-import org.checkerframework.checker.nullness.qual.NonNull;
 import org.onap.cps.spi.model.DataNode;
 
 /*
@@ -40,8 +40,7 @@ public interface CpsDataPersistenceService {
      * @param anchorName    anchor name
      * @param dataNode      data node
      */
-    void storeDataNode(@NonNull String dataspaceName, @NonNull String anchorName,
-        @NonNull DataNode dataNode);
+    void storeDataNode(String dataspaceName, String anchorName, DataNode dataNode);
 
     /**
      * Add a child to a Fragment.
@@ -51,8 +50,7 @@ public interface CpsDataPersistenceService {
      * @param parentXpath   parent xpath
      * @param dataNode      dataNode
      */
-    void addChildDataNode(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull String parentXpath,
-        @NonNull DataNode dataNode);
+    void addChildDataNode(String dataspaceName, String anchorName, String parentXpath, DataNode dataNode);
 
     /**
      * Adds list child elements to a Fragment.
@@ -63,8 +61,8 @@ public interface CpsDataPersistenceService {
      * @param listElementsCollection collection of data nodes representing list elements
      */
 
-    void addListElements(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull String parentNodeXpath,
-        @NonNull Collection<DataNode> listElementsCollection);
+    void addListElements(String dataspaceName, String anchorName, String parentNodeXpath,
+        Collection<DataNode> listElementsCollection);
 
     /**
      * Retrieves datanode by XPath for given dataspace and anchor.
@@ -76,8 +74,8 @@ public interface CpsDataPersistenceService {
      *                               (recursively) as well
      * @return data node object
      */
-    DataNode getDataNode(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull String xpath,
-        @NonNull FetchDescendantsOption fetchDescendantsOption);
+    DataNode getDataNode(String dataspaceName, String anchorName, String xpath,
+        FetchDescendantsOption fetchDescendantsOption);
 
 
     /**
@@ -88,8 +86,7 @@ public interface CpsDataPersistenceService {
      * @param xpath         xpath
      * @param leaves        the leaves as a map where key is a leaf name and a value is a leaf value
      */
-    void updateDataLeaves(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull String xpath,
-        @NonNull Map<String, Object> leaves);
+    void updateDataLeaves(String dataspaceName, String anchorName, String xpath, Map<String, Object> leaves);
 
     /**
      * Replaces existing data node content including descendants.
@@ -98,7 +95,7 @@ public interface CpsDataPersistenceService {
      * @param anchorName    anchor name
      * @param dataNode      data node
      */
-    void replaceDataNodeTree(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull DataNode dataNode);
+    void replaceDataNodeTree(String dataspaceName, String anchorName, DataNode dataNode);
 
     /**
      * Replaces list content by removing all existing elements and inserting the given new elements
@@ -109,8 +106,8 @@ public interface CpsDataPersistenceService {
      * @param parentNodeXpath parent node xpath
      * @param newListElements collection of data nodes representing the new list content
      */
-    void replaceListContent(@NonNull String dataspaceName, @NonNull String anchorName,
-                            @NonNull String parentNodeXpath, @NonNull Collection<DataNode> newListElements);
+    void replaceListContent(String dataspaceName, String anchorName,
+                            String parentNodeXpath, Collection<DataNode> newListElements);
 
     /**
      * Deletes any dataNode, yang container or yang list or yang list element.
@@ -119,8 +116,15 @@ public interface CpsDataPersistenceService {
      * @param anchorName      anchor name
      * @param targetXpath     xpath to list or list element (include [@key=value] to delete a single list element)
      */
-    void deleteDataNode(@NonNull String dataspaceName, @NonNull String anchorName,
-                        @NonNull String targetXpath);
+    void deleteDataNode(String dataspaceName, String anchorName, String targetXpath);
+
+    /**
+     * Deletes all dataNodes in a given anchor.
+     *
+     * @param dataspaceName   dataspace name
+     * @param anchorName      anchor name
+     */
+    void deleteDataNodes(String dataspaceName, String anchorName);
 
     /**
      * Deletes existing a single list element or the whole list.
@@ -129,8 +133,7 @@ public interface CpsDataPersistenceService {
      * @param anchorName      anchor name
      * @param targetXpath     xpath to list or list element (include [@key=value] to delete a single list element)
      */
-    void deleteListDataNode(@NonNull String dataspaceName, @NonNull String anchorName,
-                                 @NonNull String targetXpath);
+    void deleteListDataNode(String dataspaceName, String anchorName, String targetXpath);
 
     /**
      * Get a datanode by cps path.
@@ -142,7 +145,7 @@ public interface CpsDataPersistenceService {
      *                               included in the output
      * @return the data nodes found i.e. 0 or more data nodes
      */
-    Collection<DataNode> queryDataNodes(@NonNull String dataspaceName, @NonNull String anchorName,
-        @NonNull String cpsPath, @NonNull FetchDescendantsOption fetchDescendantsOption);
+    Collection<DataNode> queryDataNodes(String dataspaceName, String anchorName,
+        String cpsPath, FetchDescendantsOption fetchDescendantsOption);
 
 }
index fe6e460..bb122d1 100755 (executable)
 
 package org.onap.cps.api.impl
 
+import org.onap.cps.api.CpsDataService
 import org.onap.cps.spi.CpsAdminPersistenceService
 import org.onap.cps.spi.model.Anchor
 import spock.lang.Specification
+import java.time.OffsetDateTime
 
 class CpsAdminServiceImplSpec extends Specification {
     def mockCpsAdminPersistenceService = Mock(CpsAdminPersistenceService)
-    def objectUnderTest = new CpsAdminServiceImpl()
-
-    def setup() {
-        objectUnderTest.cpsAdminPersistenceService = mockCpsAdminPersistenceService
-    }
+    def mockCpsDataService = Mock(CpsDataService)
+    def objectUnderTest = new CpsAdminServiceImpl(mockCpsAdminPersistenceService, mockCpsDataService)
 
     def 'Create dataspace method invokes persistence service.'() {
         when: 'create dataspace method is invoked'
@@ -75,7 +74,9 @@ class CpsAdminServiceImplSpec extends Specification {
     def 'Delete anchor.'() {
         when: 'delete anchor is invoked'
             objectUnderTest.deleteAnchor('someDataspace','someAnchor')
-        then: 'associated persistence service method is invoked with same parameters'
+        then: 'delete data nodes is invoked on the data service with expected parameters'
+            1 * mockCpsDataService.deleteDataNodes('someDataspace','someAnchor', _ as OffsetDateTime )
+        and: 'the persistence service method is invoked with same parameters to delete anchor'
              1 * mockCpsAdminPersistenceService.deleteAnchor('someDataspace','someAnchor')
     }
 
index a302eb5..56b0e2d 100644 (file)
@@ -44,14 +44,8 @@ class CpsDataServiceImplSpec extends Specification {
     def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
     def mockNotificationService = Mock(NotificationService)
 
-    def objectUnderTest = new CpsDataServiceImpl()
-
-    def setup() {
-        objectUnderTest.cpsDataPersistenceService = mockCpsDataPersistenceService
-        objectUnderTest.cpsAdminService = mockCpsAdminService
-        objectUnderTest.yangTextSchemaSourceSetCache = mockYangTextSchemaSourceSetCache
-        objectUnderTest.notificationService = mockNotificationService
-    }
+    def objectUnderTest = new CpsDataServiceImpl(mockCpsDataPersistenceService, mockCpsAdminService,
+            mockYangTextSchemaSourceSetCache, mockNotificationService)
 
     def dataspaceName = 'some dataspace'
     def anchorName = 'some anchor'
@@ -237,6 +231,15 @@ class CpsDataServiceImplSpec extends Specification {
             1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/data-node', Operation.DELETE)
     }
 
+    def 'Delete all data nodes for a given anchor and dataspace.'() {
+        given: 'schema set for given anchor and dataspace references test tree model'
+            setupSchemaSetMocks('test-tree.yang')
+        when: 'delete data node method is invoked with correct parameters'
+            objectUnderTest.deleteDataNodes(dataspaceName, anchorName, observedTimestamp)
+        then: 'the persistence service method is invoked with the correct parameters'
+            1 * mockCpsDataPersistenceService.deleteDataNodes(dataspaceName, anchorName)
+    }
+
     def setupSchemaSetMocks(String... yangResources) {
         def anchor = Anchor.builder().name(anchorName).schemaSetName(schemaSetName).build()
         mockCpsAdminService.getAnchor(dataspaceName, anchorName) >> anchor
index d18bcf5..5238952 100755 (executable)
@@ -37,23 +37,17 @@ class E2ENetworkSliceSpec extends Specification {
     def mockDataStoreService = Mock(CpsDataPersistenceService)\r
     def mockCpsAdminService = Mock(CpsAdminService)\r
     def mockNotificationService = Mock(NotificationService)\r
-    def cpsDataServiceImpl = new CpsDataServiceImpl()\r
     def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)\r
     def cpsModuleServiceImpl = new CpsModuleServiceImpl(mockModuleStoreService,\r
             mockYangTextSchemaSourceSetCache,mockCpsAdminService )\r
+    def cpsDataServiceImpl = new CpsDataServiceImpl(mockDataStoreService, mockCpsAdminService,\r
+            mockYangTextSchemaSourceSetCache, mockNotificationService)\r
 \r
     def dataspaceName = 'someDataspace'\r
     def anchorName = 'someAnchor'\r
     def schemaSetName = 'someSchemaSet'\r
     def noTimestamp = null\r
 \r
-    def setup() {\r
-        cpsDataServiceImpl.cpsDataPersistenceService = mockDataStoreService\r
-        cpsDataServiceImpl.cpsAdminService = mockCpsAdminService\r
-        cpsDataServiceImpl.yangTextSchemaSourceSetCache = mockYangTextSchemaSourceSetCache\r
-        cpsDataServiceImpl.notificationService = mockNotificationService\r
-    }\r
-\r
     def 'E2E model can be parsed by CPS.'() {\r
         given: 'Valid yang resource as name-to-content map'\r
             def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap(\r