Refactor Delete Anchor functionality

- 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
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 51b2482..5b89d9f 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
@@ -24,9 +24,9 @@
 
 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.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 @@
     @Override
     public void deleteAnchor(final String dataspaceName, final String anchorName) {
         final var anchorEntity = getAnchorEntity(dataspaceName, anchorName);
-        fragmentRepository.deleteByAnchorIn(Set.of(anchorEntity));
         anchorRepository.delete(anchorEntity);
     }
 
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 c6e28ab..85b0cb7 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
@@ -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 @@
         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
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy
index 2218014..063bd5b 100644
--- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy
+++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy
@@ -41,8 +41,7 @@
     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 @@
     @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])
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy
index 69e6aa8..3150188 100755
--- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy
+++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy
@@ -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.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 @@
     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 @@
             '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() }
     }
diff --git a/cps-ri/src/test/resources/application.yml b/cps-ri/src/test/resources/application.yml
index 73292bb..18e6ed6 100644
--- a/cps-ri/src/test/resources/application.yml
+++ b/cps-ri/src/test/resources/application.yml
@@ -18,10 +18,12 @@
 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}
diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java b/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java
index f455e47..d2482d5 100644
--- a/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java
+++ b/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java
@@ -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 @@
      * @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 @@
      * @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 @@
      * @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 @@
      *                               (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 @@
      * @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 @@
      * @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 @@
      * @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 @@
      * @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 @@
      * @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
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java
index d30a657..1013add 100755
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java
@@ -22,19 +22,24 @@
 
 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 @@
 
     @Override
     public void deleteAnchor(final String dataspaceName, final String anchorName) {
+        cpsDataService.deleteDataNodes(dataspaceName, anchorName, OffsetDateTime.now());
         cpsAdminPersistenceService.deleteAnchor(dataspaceName, anchorName);
     }
 
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
index a23bc95..e292bbe 100755
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
@@ -24,6 +24,7 @@
 
 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.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,
@@ -138,6 +132,12 @@
     }
 
     @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) {
         cpsDataPersistenceService.deleteListDataNode(dataspaceName, anchorName, listNodeXpath);
diff --git a/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java b/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java
index b8c472f..fd65886 100644
--- a/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java
+++ b/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java
@@ -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 @@
 
 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 @@
      * @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 @@
      * @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 @@
      * @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 @@
      *                               (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 @@
      * @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 @@
      * @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 @@
      * @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 @@
      * @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 @@
      * @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 @@
      *                               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);
 
 }
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAdminServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAdminServiceImplSpec.groovy
index fe6e460..bb122d1 100755
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAdminServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAdminServiceImplSpec.groovy
@@ -22,17 +22,16 @@
 
 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 @@
     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')
     }
 
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
index a302eb5..56b0e2d 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
@@ -44,14 +44,8 @@
     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 @@
             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
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy
index d18bcf5..5238952 100755
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy
@@ -37,23 +37,17 @@
     def mockDataStoreService = Mock(CpsDataPersistenceService)

     def mockCpsAdminService = Mock(CpsAdminService)

     def mockNotificationService = Mock(NotificationService)

-    def cpsDataServiceImpl = new CpsDataServiceImpl()

     def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)

     def cpsModuleServiceImpl = new CpsModuleServiceImpl(mockModuleStoreService,

             mockYangTextSchemaSourceSetCache,mockCpsAdminService )

+    def cpsDataServiceImpl = new CpsDataServiceImpl(mockDataStoreService, mockCpsAdminService,

+            mockYangTextSchemaSourceSetCache, mockNotificationService)

 

     def dataspaceName = 'someDataspace'

     def anchorName = 'someAnchor'

     def schemaSetName = 'someSchemaSet'

     def noTimestamp = null

 

-    def setup() {

-        cpsDataServiceImpl.cpsDataPersistenceService = mockDataStoreService

-        cpsDataServiceImpl.cpsAdminService = mockCpsAdminService

-        cpsDataServiceImpl.yangTextSchemaSourceSetCache = mockYangTextSchemaSourceSetCache

-        cpsDataServiceImpl.notificationService = mockNotificationService

-    }

-

     def 'E2E model can be parsed by CPS.'() {

         given: 'Valid yang resource as name-to-content map'

             def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap(