summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xcps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java7
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java10
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy8
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImplSpec.groovy11
-rwxr-xr-xcps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java16
-rw-r--r--cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java9
-rwxr-xr-xcps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java9
-rw-r--r--cps-ri/src/main/java/org/onap/cps/spi/impl/utils/CpsValidatorImpl.java12
-rwxr-xr-xcps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java11
-rw-r--r--cps-ri/src/main/java/org/onap/cps/spi/repository/SchemaSetRepository.java14
-rw-r--r--cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy27
-rwxr-xr-xcps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy18
-rw-r--r--cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceIntegrationSpec.groovy13
-rw-r--r--cps-ri/src/test/groovy/org/onap/cps/spi/impl/utils/CpsValidatorSpec.groovy20
-rw-r--r--cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServiceDeletePerfTest.groovy16
-rw-r--r--cps-ri/src/test/resources/data/anchor.sql5
-rwxr-xr-xcps-service/src/main/java/org/onap/cps/api/CpsAdminService.java21
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/CpsDataService.java9
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java14
-rwxr-xr-xcps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java17
-rwxr-xr-xcps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java17
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java18
-rwxr-xr-xcps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java19
-rw-r--r--cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java8
-rwxr-xr-xcps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java10
-rw-r--r--cps-service/src/main/java/org/onap/cps/spi/utils/CpsValidator.java9
-rwxr-xr-xcps-service/src/test/groovy/org/onap/cps/api/impl/CpsAdminServiceImplSpec.groovy27
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy13
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy21
30 files changed, 373 insertions, 38 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
index d5500b8d7..d26a59b05 100755
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
@@ -393,7 +393,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
}
private void batchDeleteCmHandlesFromDbAndModuleSyncMap(final Collection<String> tobeRemovedCmHandles) {
- tobeRemovedCmHandles.forEach(inventoryPersistence::deleteSchemaSetWithCascade);
+ inventoryPersistence.deleteSchemaSetsWithCascade(tobeRemovedCmHandles);
inventoryPersistence.deleteDataNodes(mapCmHandleIdsToXpaths(tobeRemovedCmHandles));
tobeRemovedCmHandles.forEach(this::removeDeletedCmHandleFromModuleSyncMap);
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java
index d22cf0e16..cbd30a8fe 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java
@@ -115,6 +115,13 @@ public interface InventoryPersistence {
void deleteSchemaSetWithCascade(String schemaSetName);
/**
+ * Method to delete multiple schema sets.
+ *
+ * @param schemaSetNames schema set names
+ */
+ void deleteSchemaSetsWithCascade(Collection<String> schemaSetNames);
+
+ /**
* Get data node via xpath.
*
* @param xpath xpath
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java
index 1c799c6b2..c8d6c05f9 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java
@@ -169,6 +169,14 @@ public class InventoryPersistenceImpl implements InventoryPersistence {
}
@Override
+ @Timed(value = "cps.ncmp.inventory.persistence.schemaset.delete.batch",
+ description = "Time taken to delete multiple schemaset")
+ public void deleteSchemaSetsWithCascade(final Collection<String> schemaSetNames) {
+ cpsValidator.validateNameCharacters(schemaSetNames);
+ cpsModuleService.deleteSchemaSetsWithCascade(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetNames);
+ }
+
+ @Override
@Timed(value = "cps.ncmp.inventory.persistence.datanode.get",
description = "Time taken to get a data node (from ncmp dmi registry)")
public Collection<DataNode> getDataNode(final String xpath) {
@@ -239,4 +247,4 @@ public class InventoryPersistenceImpl implements InventoryPersistence {
private static String createCmHandleJsonData(final String cmHandleId) {
return "{\"cm-handles\":[" + cmHandleId + "]}";
}
-} \ No newline at end of file
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
index cf3454991..272030b11 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
@@ -249,14 +249,14 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server',
removedCmHandles: ['cmhandle'])
and: '#scenario'
- mockCpsModuleService.deleteSchemaSet(_, 'cmhandle', CASCADE_DELETE_ALLOWED) >>
+ mockCpsModuleService.deleteSchemaSetsWithCascade(_, ['cmhandle']) >>
{ if (!schemaSetExist) { throw new SchemaSetNotFoundException("", "") } }
when: 'registration is updated to delete cmhandle'
def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
then: 'the cmHandle state is updated to "DELETING"'
1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_)
and: 'method to delete relevant schema set is called once'
- 1 * mockInventoryPersistence.deleteSchemaSetWithCascade(_)
+ 1 * mockInventoryPersistence.deleteSchemaSetsWithCascade(_)
and: 'method to delete relevant list/list element is called once'
1 * mockInventoryPersistence.deleteDataNodes(_)
and: 'successful response is received'
@@ -322,7 +322,9 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
addPersistedYangModelCmHandles(['cmhandle'])
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server',
removedCmHandles: ['cmhandle'])
- and: 'schema set deletion failed with unknown error'
+ and: 'schema set batch deletion failed with unknown error'
+ mockInventoryPersistence.deleteSchemaSetsWithCascade(_) >> { throw new RuntimeException('Failed') }
+ and: 'schema set single deletion failed with unknown error'
mockInventoryPersistence.deleteSchemaSetWithCascade(_) >> { throw new RuntimeException('Failed') }
when: 'registration is updated to delete cmhandle'
def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImplSpec.groovy
index 4a98526b4..efe6f00bc 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImplSpec.groovy
@@ -243,10 +243,19 @@ class InventoryPersistenceImplSpec extends Specification {
objectUnderTest.deleteSchemaSetWithCascade('validSchemaSetName')
then: 'the module service to delete schemaSet is invoked once'
1 * mockCpsModuleService.deleteSchemaSet('NFP-Operational', 'validSchemaSetName', CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED)
- and: 'the CM Handle ID is validated'
+ and: 'the schema set name is validated'
1 * mockCpsValidator.validateNameCharacters('validSchemaSetName')
}
+ def 'Delete multiple schema sets with valid schema set names'() {
+ when: 'the method to delete schema sets is called with valid schema set names'
+ objectUnderTest.deleteSchemaSetsWithCascade(['validSchemaSetName1', 'validSchemaSetName2'])
+ then: 'the module service to delete schema sets is invoked once'
+ 1 * mockCpsModuleService.deleteSchemaSetsWithCascade('NFP-Operational', ['validSchemaSetName1', 'validSchemaSetName2'])
+ and: 'the schema set names are validated'
+ 1 * mockCpsValidator.validateNameCharacters(['validSchemaSetName1', 'validSchemaSetName2'])
+ }
+
def 'Get data node via xPath'() {
when: 'the method to get data nodes is called'
objectUnderTest.getDataNode('sample xPath')
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 2cebfc72c..162b268d8 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-2022 Nordix Foundation.
+ * Copyright (C) 2020-2023 Nordix Foundation.
* Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* Modifications Copyright (C) 2022 TechMahindra Ltd.
@@ -131,6 +131,13 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic
}
@Override
+ public Collection<Anchor> getAnchors(final String dataspaceName, final Collection<String> schemaSetNames) {
+ final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+ return anchorRepository.findAllByDataspaceAndSchemaSetNameIn(dataspaceEntity, schemaSetNames)
+ .stream().map(CpsAdminPersistenceServiceImpl::toAnchor).collect(Collectors.toSet());
+ }
+
+ @Override
public Collection<Anchor> queryAnchors(final String dataspaceName, final Collection<String> inputModuleNames) {
try {
validateDataspaceAndModuleNames(dataspaceName, inputModuleNames);
@@ -157,6 +164,13 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic
anchorRepository.delete(anchorEntity);
}
+ @Transactional
+ @Override
+ public void deleteAnchors(final String dataspaceName, final Collection<String> anchorNames) {
+ final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+ anchorRepository.deleteAllByDataspaceAndNameIn(dataspaceEntity, anchorNames);
+ }
+
private AnchorEntity getAnchorEntity(final String dataspaceName, final String anchorName) {
final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
return anchorRepository.getByDataspaceAndName(dataspaceEntity, anchorName);
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 46439fdb3..2fba30ee2 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
@@ -612,6 +612,15 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
@Override
@Transactional
+ public void deleteDataNodes(final String dataspaceName, final Collection<String> anchorNames) {
+ final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+ final Collection<AnchorEntity> anchorEntities =
+ anchorRepository.findAllByDataspaceAndNameIn(dataspaceEntity, anchorNames);
+ fragmentRepository.deleteByAnchorIn(anchorEntities);
+ }
+
+ @Override
+ @Transactional
public void deleteDataNodes(final String dataspaceName, final String anchorName,
final Collection<String> xpathsToDelete) {
final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
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 c9f9a78ef..b4366de75 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
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2020-2022 Nordix Foundation
+ * Copyright (C) 2020-2023 Nordix Foundation
* Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* Modifications Copyright (C) 2022 TechMahindra Ltd.
@@ -193,6 +193,13 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
@Override
@Transactional
+ public void deleteSchemaSets(final String dataspaceName, final Collection<String> schemaSetNames) {
+ final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+ schemaSetRepository.deleteByDataspaceAndNameIn(dataspaceEntity, schemaSetNames);
+ }
+
+ @Override
+ @Transactional
public void deleteUnusedYangResourceModules() {
yangResourceRepository.deleteOrphans();
}
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/utils/CpsValidatorImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/utils/CpsValidatorImpl.java
index 064583142..1f61ee3c5 100644
--- a/cps-ri/src/main/java/org/onap/cps/spi/impl/utils/CpsValidatorImpl.java
+++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/utils/CpsValidatorImpl.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022 Nordix Foundation
+ * Copyright (C) 2022-2023 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
package org.onap.cps.spi.impl.utils;
import com.google.common.collect.Lists;
+import java.util.Arrays;
import java.util.Collection;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -37,13 +38,18 @@ public class CpsValidatorImpl implements CpsValidator {
@Override
public void validateNameCharacters(final String... names) {
+ validateNameCharacters(Arrays.asList(names));
+ }
+
+ @Override
+ public void validateNameCharacters(final Iterable<String> names) {
for (final String name : names) {
final Collection<Character> charactersOfName = Lists.charactersOf(name);
for (final char unsupportedCharacter : UNSUPPORTED_NAME_CHARACTERS) {
if (charactersOfName.contains(unsupportedCharacter)) {
throw new DataValidationException("Name or ID Validation Error.",
- name + " invalid token encountered at position "
- + (name.indexOf(unsupportedCharacter) + 1));
+ name + " invalid token encountered at position "
+ + (name.indexOf(unsupportedCharacter) + 1));
}
}
}
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java
index 3dbd578c7..46b0fec1c 100755
--- a/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java
+++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java
@@ -47,6 +47,12 @@ public interface AnchorRepository extends JpaRepository<AnchorEntity, Integer> {
Collection<AnchorEntity> findAllBySchemaSet(@NotNull SchemaSetEntity schemaSetEntity);
+ Collection<AnchorEntity> findAllByDataspaceAndNameIn(@NotNull DataspaceEntity dataspaceEntity,
+ @NotNull Collection<String> anchorNames);
+
+ Collection<AnchorEntity> findAllByDataspaceAndSchemaSetNameIn(@NotNull DataspaceEntity dataspaceEntity,
+ @NotNull Collection<String> schemaSetNames);
+
Integer countByDataspace(@NotNull DataspaceEntity dataspaceEntity);
@Query(value = "SELECT anchor.* FROM yang_resource\n"
@@ -58,4 +64,7 @@ public interface AnchorRepository extends JpaRepository<AnchorEntity, Integer> {
+ "HAVING COUNT(DISTINCT module_name) = :sizeOfModuleNames", nativeQuery = true)
Collection<AnchorEntity> getAnchorsByDataspaceIdAndModuleNames(@Param("dataspaceId") int dataspaceId,
@Param("moduleNames") Collection<String> moduleNames, @Param("sizeOfModuleNames") int sizeOfModuleNames);
-} \ No newline at end of file
+
+ void deleteAllByDataspaceAndNameIn(@NotNull DataspaceEntity dataspaceEntity,
+ @NotNull Collection<String> anchorNames);
+}
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/SchemaSetRepository.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/SchemaSetRepository.java
index 8cecb0a8e..98d442010 100644
--- a/cps-ri/src/main/java/org/onap/cps/spi/repository/SchemaSetRepository.java
+++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/SchemaSetRepository.java
@@ -2,6 +2,7 @@
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Pantheon.tech
* Modifications Copyright (C) 2022 TechMahindra Ltd.
+ * Modifications Copyright (C) 2023 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +30,9 @@ import org.onap.cps.spi.entities.DataspaceEntity;
import org.onap.cps.spi.entities.SchemaSetEntity;
import org.onap.cps.spi.exceptions.SchemaSetNotFoundException;
import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
@Repository
@@ -70,4 +74,14 @@ public interface SchemaSetRepository extends JpaRepository<SchemaSetEntity, Inte
default List<SchemaSetEntity> getByDataspace(@NotNull final DataspaceEntity dataspaceEntity) {
return findByDataspace(dataspaceEntity).stream().collect(Collectors.toList());
}
+
+ /**
+ * Delete multiple schema sets in a given dataspace.
+ * @param dataspaceEntity dataspace entity
+ * @param schemaSetNames schema set names
+ */
+ @Modifying
+ @Query("DELETE FROM SchemaSetEntity s WHERE s.dataspace = :dataspaceEntity AND s.name IN (:schemaSetNames)")
+ void deleteByDataspaceAndNameIn(@NotNull @Param("dataspaceEntity") final DataspaceEntity dataspaceEntity,
+ @NotNull @Param("schemaSetNames") final Collection<String> schemaSetNames);
}
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 99d44aac8..28d3bcfa4 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
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2022 Nordix Foundation
+ * Copyright (C) 2021-2023 Nordix Foundation
* Modifications Copyright (C) 2021 Pantheon.tech
* Modifications Copyright (C) 2022 Bell Canada
* Modifications Copyright (C) 2022 TechMahindra Ltd.
@@ -142,7 +142,8 @@ class CpsAdminPersistenceServiceSpec extends CpsPersistenceSpecBase {
where: 'the following data is used'
dataspaceName || expectedAnchors
DATASPACE_NAME || [Anchor.builder().name(ANCHOR_NAME1).schemaSetName(SCHEMA_SET_NAME1).dataspaceName(DATASPACE_NAME).build(),
- Anchor.builder().name(ANCHOR_NAME2).schemaSetName(SCHEMA_SET_NAME2).dataspaceName(DATASPACE_NAME).build()]
+ Anchor.builder().name(ANCHOR_NAME2).schemaSetName(SCHEMA_SET_NAME2).dataspaceName(DATASPACE_NAME).build(),
+ Anchor.builder().name(ANCHOR_NAME3).schemaSetName(SCHEMA_SET_NAME2).dataspaceName(DATASPACE_NAME).build()]
DATASPACE_WITH_NO_DATA || []
}
@@ -179,6 +180,17 @@ class CpsAdminPersistenceServiceSpec extends CpsPersistenceSpecBase {
}
@Sql([CLEAR_DATA, SET_DATA])
+ def 'Get all anchors associated with multiple schemasets in a dataspace.'() {
+ when: 'anchors are retrieved by dataspace and schema-sets'
+ def anchors = objectUnderTest.getAnchors('DATASPACE-001', ['SCHEMA-SET-001', 'SCHEMA-SET-002'])
+ then: ' the response contains expected anchors'
+ anchors == Set.of(
+ new Anchor('ANCHOR-001', 'DATASPACE-001', 'SCHEMA-SET-001'),
+ new Anchor('ANCHOR-002', 'DATASPACE-001', 'SCHEMA-SET-002'),
+ new Anchor('ANCHOR-003', 'DATASPACE-001', 'SCHEMA-SET-002'))
+ }
+
+ @Sql([CLEAR_DATA, SET_DATA])
def 'Delete anchor'() {
when: 'delete anchor action is invoked'
objectUnderTest.deleteAnchor(DATASPACE_NAME, ANCHOR_NAME2)
@@ -198,6 +210,15 @@ class CpsAdminPersistenceServiceSpec extends CpsPersistenceSpecBase {
'anchor does not exists' | DATASPACE_NAME | 'unknown' || AnchorNotFoundException
}
+ @Sql([CLEAR_DATA, SET_DATA])
+ def 'Delete multiple anchors'() {
+ when: 'delete anchors action is invoked'
+ objectUnderTest.deleteAnchors(DATASPACE_NAME, ['ANCHOR-002', 'ANCHOR-003'])
+ then: 'anchors are deleted'
+ anchorRepository.findById(3002).isEmpty()
+ anchorRepository.findById(3003).isEmpty()
+ }
+
@Sql([CLEAR_DATA, SAMPLE_DATA_FOR_ANCHORS_WITH_MODULES])
def 'Query anchors that have #scenario.'() {
when: 'all anchor are retrieved for the given dataspace name and module names'
@@ -236,7 +257,7 @@ class CpsAdminPersistenceServiceSpec extends CpsPersistenceSpecBase {
where: 'the following data is used'
scenario | dataspaceName || expectedException | expectedMessageDetails
'dataspace name does not exist' | 'unknown' || DataspaceNotFoundException | 'unknown does not exist'
- 'dataspace contains an anchor' | 'DATASPACE-001' || DataspaceInUseException | 'contains 2 anchor(s)'
+ 'dataspace contains an anchor' | 'DATASPACE-001' || DataspaceInUseException | 'contains 3 anchor(s)'
'dataspace contains schemasets' | 'DATASPACE-003' || DataspaceInUseException | 'contains 1 schemaset(s)'
}
}
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 336d6035a..bb80a1320 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
@@ -55,8 +55,6 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase {
static DataNodeBuilder dataNodeBuilder = new DataNodeBuilder()
static final String SET_DATA = '/data/fragment.sql'
- static int DATASPACE_1001_ID = 1001L
- static int ANCHOR_3003_ID = 3003L
static long ID_DATA_NODE_WITH_DESCENDANTS = 4001
static String XPATH_DATA_NODE_WITH_DESCENDANTS = '/parent-1'
static String XPATH_DATA_NODE_WITH_LEAVES = '/parent-207'
@@ -666,11 +664,23 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase {
@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)
+ assert fragmentsExistInDB(1001, 3003)
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)
+ assert !fragmentsExistInDB(1001, 3003)
+ }
+
+ @Sql([CLEAR_DATA, SET_DATA])
+ def 'Delete data node for multiple anchors.'() {
+ given: 'a data-node exists for an anchor'
+ assert fragmentsExistInDB(1001, 3001)
+ assert fragmentsExistInDB(1001, 3003)
+ when: 'data nodes are deleted '
+ objectUnderTest.deleteDataNodes(DATASPACE_NAME, ['ANCHOR-001', 'ANCHOR-003'])
+ then: 'all data-nodes are deleted successfully'
+ assert !fragmentsExistInDB(1001, 3001)
+ assert !fragmentsExistInDB(1001, 3003)
}
def fragmentsExistInDB(dataSpaceId, anchorId) {
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceIntegrationSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceIntegrationSpec.groovy
index 4c67f7e97..864b3e3b6 100644
--- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceIntegrationSpec.groovy
+++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceIntegrationSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2022 Nordix Foundation
+ * Copyright (C) 2021-2023 Nordix Foundation
* Modifications Copyright (C) 2021-2022 Bell Canada.
* Modifications Copyright (C) 2022 TechMahindra Ltd.
* ================================================================================
@@ -223,7 +223,16 @@ class CpsModulePersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase
when: 'a schema set is deleted with cascade-prohibited option'
objectUnderTest.deleteSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NO_ANCHORS)
then: 'the schema set has been deleted'
- schemaSetRepository.findByDataspaceAndName(dataspaceEntity, SCHEMA_SET_NAME_NO_ANCHORS).isPresent() == false
+ !schemaSetRepository.findByDataspaceAndName(dataspaceEntity, SCHEMA_SET_NAME_NO_ANCHORS).isPresent()
+ }
+
+ @Sql([CLEAR_DATA, SET_DATA])
+ def 'Delete schema sets'() {
+ when: 'schema sets are deleted'
+ objectUnderTest.deleteSchemaSets(DATASPACE_NAME, ['SCHEMA-SET-001', 'SCHEMA-SET-002'])
+ then: 'the schema sets have been deleted'
+ !schemaSetRepository.findByDataspaceAndName(dataspaceEntity, 'SCHEMA-SET-001').isPresent()
+ !schemaSetRepository.findByDataspaceAndName(dataspaceEntity, 'SCHEMA-SET-002').isPresent()
}
@Sql([CLEAR_DATA, SET_DATA])
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/utils/CpsValidatorSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/utils/CpsValidatorSpec.groovy
index ae2ff16bc..345089c93 100644
--- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/utils/CpsValidatorSpec.groovy
+++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/utils/CpsValidatorSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022 Nordix Foundation
+ * Copyright (C) 2022-2023 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,4 +46,22 @@ class CpsValidatorSpec extends Specification {
'position 5' | 'name with spaces' || 'name with spaces invalid token encountered at position 5'
'position 9' | 'nameWith Space' || 'nameWith Space invalid token encountered at position 9'
}
+
+ def 'Validating a list of valid names.'() {
+ given: 'a list of valid names'
+ def names = ['valid-name', 'another-valid-name']
+ when: 'a list of strings is validated'
+ objectUnderTest.validateNameCharacters(names)
+ then: 'no exception is thrown'
+ noExceptionThrown()
+ }
+
+ def 'Validating a list of names with invalid names.'() {
+ given: 'a list of names with an invalid name'
+ def names = ['valid-name', 'name with spaces']
+ when: 'a list of strings is validated'
+ objectUnderTest.validateNameCharacters(names)
+ then: 'a data validation exception is thrown'
+ thrown(DataValidationException)
+ }
}
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServiceDeletePerfTest.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServiceDeletePerfTest.groovy
index 3b9338ce4..706b35ebb 100644
--- a/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServiceDeletePerfTest.groovy
+++ b/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServiceDeletePerfTest.groovy
@@ -212,7 +212,7 @@ class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase
}
@Sql([CLEAR_DATA, PERF_TEST_DATA])
- def 'Delete data nodes for an anchor'() {212
+ def 'Delete data nodes for an anchor'() {
given: 'a node with a large number of descendants is created'
createLineage(objectUnderTest, 50, 50, false)
createLineage(objectUnderTest, 50, 50, true)
@@ -225,4 +225,18 @@ class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase
recordAndAssertPerformance('Delete data nodes for anchor', 300, deleteDurationInMillis)
}
+ @Sql([CLEAR_DATA, PERF_TEST_DATA])
+ def 'Delete data nodes for multiple anchors'() {
+ given: 'a node with a large number of descendants is created'
+ createLineage(objectUnderTest, 50, 50, false)
+ createLineage(objectUnderTest, 50, 50, true)
+ when: 'data nodes are deleted'
+ stopWatch.start()
+ objectUnderTest.deleteDataNodes(PERF_DATASPACE, [PERF_ANCHOR])
+ stopWatch.stop()
+ def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
+ then: 'delete duration is under 300 milliseconds'
+ recordAndAssertPerformance('Delete data nodes for anchor', 300, deleteDurationInMillis)
+ }
+
}
diff --git a/cps-ri/src/test/resources/data/anchor.sql b/cps-ri/src/test/resources/data/anchor.sql
index 40fc44c0a..2ab7966e1 100644
--- a/cps-ri/src/test/resources/data/anchor.sql
+++ b/cps-ri/src/test/resources/data/anchor.sql
@@ -1,7 +1,7 @@
/*
============LICENSE_START=======================================================
Copyright (C) 2020 Pantheon.tech
- Modifications Copyright (C) 2020 Nordix Foundation.
+ Modifications Copyright (C) 2020-2023 Nordix Foundation.
Modifications Copyright (C) 2021-2022 Bell Canada.
================================================================================
Licensed under the Apache License, Version 2.0 (the "License");
@@ -32,7 +32,8 @@ INSERT INTO SCHEMA_SET (ID, NAME, DATASPACE_ID) VALUES
INSERT INTO ANCHOR (ID, NAME, DATASPACE_ID, SCHEMA_SET_ID) VALUES
(3001, 'ANCHOR-001', 1001, 2001),
- (3002, 'ANCHOR-002', 1001, 2002);
+ (3002, 'ANCHOR-002', 1001, 2002),
+ (3003, 'ANCHOR-003', 1001, 2002);
INSERT INTO FRAGMENT (ID, DATASPACE_ID, ANCHOR_ID, PARENT_ID, XPATH, ATTRIBUTES) VALUES
(4001, 1001, 3001, null, '/xpath', '{}');
diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsAdminService.java b/cps-service/src/main/java/org/onap/cps/api/CpsAdminService.java
index b0e68cf8f..fcf3f54cc 100755
--- a/cps-service/src/main/java/org/onap/cps/api/CpsAdminService.java
+++ b/cps-service/src/main/java/org/onap/cps/api/CpsAdminService.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2020-2022 Nordix Foundation
+ * Copyright (C) 2020-2023 Nordix Foundation
* Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* Modifications Copyright (C) 2022 TechMahindra Ltd.
@@ -84,7 +84,7 @@ public interface CpsAdminService {
Collection<Anchor> getAnchors(String dataspaceName);
/**
- * Read all anchors associated the given schema-set in the given dataspace.
+ * Read all anchors associated with the given schema-set in the given dataspace.
*
* @param dataspaceName dataspace name
* @param schemaSetName schema-set name
@@ -93,6 +93,15 @@ public interface CpsAdminService {
Collection<Anchor> getAnchors(String dataspaceName, String schemaSetName);
/**
+ * Read all anchors associated with the given schema-sets in the given dataspace.
+ *
+ * @param dataspaceName dataspace name
+ * @param schemaSetNames schema-set names
+ * @return a collection of anchors
+ */
+ Collection<Anchor> getAnchors(String dataspaceName, Collection<String> schemaSetNames);
+
+ /**
* Get an anchor in the given dataspace using the anchor name.
*
* @param dataspaceName dataspace name
@@ -110,6 +119,14 @@ public interface CpsAdminService {
void deleteAnchor(String dataspaceName, String anchorName);
/**
+ * Delete anchors by name in given dataspace.
+ *
+ * @param dataspaceName dataspace name
+ * @param anchorNames anchor names
+ */
+ void deleteAnchors(String dataspaceName, Collection<String> anchorNames);
+
+ /**
* Query anchor names for the given module names in the provided dataspace.
*
* @param dataspaceName dataspace name
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 9f96df2e4..39fa45ac1 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
@@ -230,6 +230,15 @@ public interface CpsDataService {
void deleteDataNodes(String dataspaceName, String anchorName, OffsetDateTime observedTimestamp);
/**
+ * Deletes all data nodes for multiple anchors in a dataspace.
+ *
+ * @param dataspaceName dataspace name
+ * @param anchorNames anchor names
+ * @param observedTimestamp observed timestamp
+ */
+ void deleteDataNodes(String dataspaceName, Collection<String> anchorNames, OffsetDateTime observedTimestamp);
+
+ /**
* Deletes a list or a list-element under given anchor and dataspace.
*
* @param dataspaceName dataspace name
diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java b/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
index b1f90d686..5ff08c9ac 100644
--- a/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
+++ b/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2020-2022 Nordix Foundation
+ * Copyright (C) 2020-2023 Nordix Foundation
* Modifications Copyright (C) 2020-2021 Pantheon.tech
* Modifications Copyright (C) 2022 TechMahindra Ltd.
* ================================================================================
@@ -80,13 +80,21 @@ public interface CpsModuleService {
* @param dataspaceName dataspace name
* @param schemaSetName schema set name
* @param cascadeDeleteAllowed indicates the allowance to remove associated anchors and data if exist
- * @throws DataInUseException if cascadeDeleteAllowed is set to CASCADE_DELETE_PROHIBITED and there
- * is associated anchor record exists in database
+ * @throws DataInUseException if cascadeDeleteAllowed is set to CASCADE_DELETE_PROHIBITED and there
+ * is associated anchor record exists in database
*/
void deleteSchemaSet(String dataspaceName, String schemaSetName,
CascadeDeleteAllowed cascadeDeleteAllowed);
/**
+ * Deletes Schema Sets with cascade.
+ *
+ * @param dataspaceName dataspace name
+ * @param schemaSetNames schema set names
+ */
+ void deleteSchemaSetsWithCascade(String dataspaceName, Collection<String> schemaSetNames);
+
+ /**
* Retrieve module references for the given dataspace name.
*
* @param dataspaceName dataspace name
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 ece3eb95c..e286eea17 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
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2020-2022 Nordix Foundation
+ * Copyright (C) 2020-2023 Nordix Foundation
* Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* Modifications Copyright (C) 2022 TechMahindra Ltd.
@@ -87,6 +87,13 @@ public class CpsAdminServiceImpl implements CpsAdminService {
}
@Override
+ public Collection<Anchor> getAnchors(final String dataspaceName, final Collection<String> schemaSetNames) {
+ cpsValidator.validateNameCharacters(dataspaceName);
+ cpsValidator.validateNameCharacters(schemaSetNames);
+ return cpsAdminPersistenceService.getAnchors(dataspaceName, schemaSetNames);
+ }
+
+ @Override
public Anchor getAnchor(final String dataspaceName, final String anchorName) {
cpsValidator.validateNameCharacters(dataspaceName, anchorName);
return cpsAdminPersistenceService.getAnchor(dataspaceName, anchorName);
@@ -100,6 +107,14 @@ public class CpsAdminServiceImpl implements CpsAdminService {
}
@Override
+ public void deleteAnchors(final String dataspaceName, final Collection<String> anchorNames) {
+ cpsValidator.validateNameCharacters(dataspaceName);
+ cpsValidator.validateNameCharacters(anchorNames);
+ cpsDataService.deleteDataNodes(dataspaceName, anchorNames, OffsetDateTime.now());
+ cpsAdminPersistenceService.deleteAnchors(dataspaceName, anchorNames);
+ }
+
+ @Override
public Collection<String> queryAnchorNames(final String dataspaceName, final Collection<String> moduleNames) {
cpsValidator.validateNameCharacters(dataspaceName);
final Collection<Anchor> anchors = cpsAdminPersistenceService.queryAnchors(dataspaceName, moduleNames);
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 b149d426e..721d4a9fb 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
@@ -274,8 +274,8 @@ public class CpsDataServiceImpl implements CpsDataService {
}
@Override
- @Timed(value = "cps.data.service.datanode.all.delete",
- description = "Time taken to delete all datanodes")
+ @Timed(value = "cps.data.service.datanode.delete.anchor",
+ description = "Time taken to delete all datanodes for an anchor")
public void deleteDataNodes(final String dataspaceName, final String anchorName,
final OffsetDateTime observedTimestamp) {
cpsValidator.validateNameCharacters(dataspaceName, anchorName);
@@ -284,6 +284,19 @@ public class CpsDataServiceImpl implements CpsDataService {
}
@Override
+ @Timed(value = "cps.data.service.datanode.delete.anchor.batch",
+ description = "Time taken to delete all datanodes for multiple anchors")
+ public void deleteDataNodes(final String dataspaceName, final Collection<String> anchorNames,
+ final OffsetDateTime observedTimestamp) {
+ cpsValidator.validateNameCharacters(dataspaceName);
+ cpsValidator.validateNameCharacters(anchorNames);
+ for (final String anchorName : anchorNames) {
+ processDataUpdatedEventAsync(dataspaceName, anchorName, ROOT_NODE_XPATH, DELETE, observedTimestamp);
+ }
+ cpsDataPersistenceService.deleteDataNodes(dataspaceName, anchorNames);
+ }
+
+ @Override
@Timed(value = "cps.data.service.list.delete",
description = "Time taken to delete a list or list element")
public void deleteListOrListElement(final String dataspaceName, final String anchorName, final String listNodeXpath,
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
index ccd0fcc28..d6c01f7a9 100644
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
@@ -26,6 +26,7 @@ package org.onap.cps.api.impl;
import io.micrometer.core.annotation.Timed;
import java.util.Collection;
import java.util.Map;
+import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.onap.cps.api.CpsAdminService;
import org.onap.cps.api.CpsModuleService;
@@ -95,7 +96,7 @@ public class CpsModuleServiceImpl implements CpsModuleService {
@Override
@Transactional
public void deleteSchemaSet(final String dataspaceName, final String schemaSetName,
- final CascadeDeleteAllowed cascadeDeleteAllowed) {
+ final CascadeDeleteAllowed cascadeDeleteAllowed) {
cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
final Collection<Anchor> anchors = cpsAdminService.getAnchors(dataspaceName, schemaSetName);
if (!anchors.isEmpty() && isCascadeDeleteProhibited(cascadeDeleteAllowed)) {
@@ -110,6 +111,21 @@ public class CpsModuleServiceImpl implements CpsModuleService {
}
@Override
+ @Transactional
+ public void deleteSchemaSetsWithCascade(final String dataspaceName, final Collection<String> schemaSetNames) {
+ cpsValidator.validateNameCharacters(dataspaceName);
+ cpsValidator.validateNameCharacters(schemaSetNames);
+ final Collection<String> anchorNames = cpsAdminService.getAnchors(dataspaceName, schemaSetNames)
+ .stream().map(Anchor::getName).collect(Collectors.toSet());
+ cpsAdminService.deleteAnchors(dataspaceName, anchorNames);
+ cpsModulePersistenceService.deleteUnusedYangResourceModules();
+ cpsModulePersistenceService.deleteSchemaSets(dataspaceName, schemaSetNames);
+ for (final String schemaSetName : schemaSetNames) {
+ yangTextSchemaSourceSetCache.removeFromCache(dataspaceName, schemaSetName);
+ }
+ }
+
+ @Override
public Collection<ModuleReference> getYangResourceModuleReferences(final String dataspaceName) {
cpsValidator.validateNameCharacters(dataspaceName);
return cpsModulePersistenceService.getYangResourceModuleReferences(dataspaceName);
diff --git a/cps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java b/cps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java
index 6bcb69844..1c1e80a20 100755
--- a/cps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java
+++ b/cps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java
@@ -73,7 +73,7 @@ public interface CpsAdminPersistenceService {
void createAnchor(String dataspaceName, String schemaSetName, String anchorName);
/**
- * Read all anchors associated the given schema-set in the given dataspace.
+ * Read all anchors associated with the given schema-set in the given dataspace.
*
* @param dataspaceName dataspace name
* @param schemaSetName schema-set name
@@ -82,6 +82,15 @@ public interface CpsAdminPersistenceService {
Collection<Anchor> getAnchors(String dataspaceName, String schemaSetName);
/**
+ * Read all anchors associated with multiple schema-sets in the given dataspace.
+ *
+ * @param dataspaceName dataspace name
+ * @param schemaSetNames schema-set names
+ * @return a collection of anchors
+ */
+ Collection<Anchor> getAnchors(String dataspaceName, Collection<String> schemaSetNames);
+
+ /**
* Read all anchors in the given a dataspace.
*
* @param dataspaceName dataspace name
@@ -116,4 +125,12 @@ public interface CpsAdminPersistenceService {
* @param anchorName anchor name
*/
void deleteAnchor(String dataspaceName, String anchorName);
+
+ /**
+ * Delete anchors by name in given dataspace.
+ *
+ * @param dataspaceName dataspace name
+ * @param anchorNames anchor names
+ */
+ void deleteAnchors(String dataspaceName, Collection<String> anchorNames);
}
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 0b2cef9bd..90e6ec761 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
@@ -194,6 +194,14 @@ public interface CpsDataPersistenceService {
void deleteDataNodes(String dataspaceName, String anchorName);
/**
+ * Deletes all dataNodes in multiple anchors.
+ *
+ * @param dataspaceName dataspace name
+ * @param anchorNames anchor names
+ */
+ void deleteDataNodes(String dataspaceName, Collection<String> anchorNames);
+
+ /**
* Deletes a single existing list element or the whole list.
*
* @param dataspaceName dataspace name
diff --git a/cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java b/cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java
index f5dc8ac3a..40d4002b9 100755
--- a/cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java
+++ b/cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2020-2022 Nordix Foundation
+ * Copyright (C) 2020-2023 Nordix Foundation
* Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2022 TechMahindra Ltd.
* ================================================================================
@@ -70,6 +70,14 @@ public interface CpsModulePersistenceService {
void deleteSchemaSet(String dataspaceName, String schemaSetName);
/**
+ * Deletes Schema Sets.
+ *
+ * @param dataspaceName dataspace name
+ * @param schemaSetNames schema set names
+ */
+ void deleteSchemaSets(String dataspaceName, Collection<String> schemaSetNames);
+
+ /**
* Returns YANG resources per specific dataspace / schemaSetName.
*
* @param dataspaceName dataspace name
diff --git a/cps-service/src/main/java/org/onap/cps/spi/utils/CpsValidator.java b/cps-service/src/main/java/org/onap/cps/spi/utils/CpsValidator.java
index c7ce8fc92..231094cf1 100644
--- a/cps-service/src/main/java/org/onap/cps/spi/utils/CpsValidator.java
+++ b/cps-service/src/main/java/org/onap/cps/spi/utils/CpsValidator.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022 Nordix Foundation
+ * Copyright (C) 2022-2023 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,4 +28,11 @@ public interface CpsValidator {
* @param names names of data to be validated
*/
void validateNameCharacters(final String... names);
+
+ /**
+ * Validate characters in names within cps.
+ *
+ * @param names names of data to be validated
+ */
+ void validateNameCharacters(final Iterable<String> names);
}
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 e7d4e4ddb..4e0349d2b 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
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2020-2022 Nordix Foundation
+ * Copyright (C) 2020-2023 Nordix Foundation
* Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* Modifications Copyright (C) 2022 TechMahindra Ltd.
@@ -79,6 +79,19 @@ class CpsAdminServiceImplSpec extends Specification {
1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someSchemaSet')
}
+ def 'Retrieve all anchors for multiple schema-sets.'() {
+ given: 'that anchor is associated with the dataspace and schemasets'
+ def anchors = [new Anchor(), new Anchor()]
+ mockCpsAdminPersistenceService.getAnchors('someDataspace', _ as Collection<String>) >> anchors
+ when: 'get anchors is called for a dataspace name and schema set names'
+ def result = objectUnderTest.getAnchors('someDataspace', ['schemaSet1', 'schemaSet2'])
+ then: 'the collection provided by persistence service is returned as result'
+ result == anchors
+ and: 'the CpsValidator is called on the dataspace name and schema-set names'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace')
+ 1 * mockCpsValidator.validateNameCharacters(_)
+ }
+
def 'Retrieve anchor for dataspace and provided anchor name.'() {
given: 'that anchor name is associated with the dataspace'
Anchor anchor = new Anchor()
@@ -118,6 +131,18 @@ class CpsAdminServiceImplSpec extends Specification {
1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someAnchor')
}
+ def 'Delete multiple anchors.'() {
+ when: 'delete anchors is invoked'
+ objectUnderTest.deleteAnchors('someDataspace', ['anchor1', 'anchor2'])
+ then: 'delete data nodes is invoked on the data service with expected parameters'
+ 1 * mockCpsDataService.deleteDataNodes('someDataspace', _ as Collection<String>, _ as OffsetDateTime)
+ and: 'the persistence service method is invoked with same parameters to delete anchor'
+ 1 * mockCpsAdminPersistenceService.deleteAnchors('someDataspace',_ as Collection<String>)
+ and: 'the CpsValidator is called on the dataspace name and anchor names'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace')
+ 1 * mockCpsValidator.validateNameCharacters(_)
+ }
+
def 'Query all anchor identifiers for a dataspace and module names.'() {
given: 'the persistence service is invoked with the expected parameters and returns a list of anchors'
mockCpsAdminPersistenceService.queryAnchors('some-dataspace-name', ['some-module-name']) >> [new Anchor(name:'some-anchor-identifier')]
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 5a74d073a..e304d28d8 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
@@ -378,6 +378,19 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockCpsDataPersistenceService.deleteDataNodes(dataspaceName, anchorName)
}
+ def 'Delete all data nodes for given dataspace and multiple anchors.'() {
+ given: 'schema set for given anchors and dataspace references test tree model'
+ setupSchemaSetMocks('test-tree.yang')
+ when: 'delete data node method is invoked with correct parameters'
+ objectUnderTest.deleteDataNodes(dataspaceName, ['anchor1', 'anchor2'], observedTimestamp)
+ then: 'data updated events are sent to notification service before the delete'
+ 2 * mockNotificationService.processDataUpdatedEvent(dataspaceName, _, '/', Operation.DELETE, observedTimestamp)
+ and: 'the CpsValidator is called on the dataspace name and the anchor names'
+ 2 * mockCpsValidator.validateNameCharacters(_)
+ and: 'the persistence service method is invoked with the correct parameters'
+ 1 * mockCpsDataPersistenceService.deleteDataNodes(dataspaceName, _ as Collection<String>)
+ }
+
def setupSchemaSetMocks(String... yangResources) {
def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet)
mockYangTextSchemaSourceSetCache.get(dataspaceName, schemaSetName) >> mockYangTextSchemaSourceSet
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
index 2bb0e63ab..3884eda66 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
@@ -167,6 +167,27 @@ class CpsModuleServiceImplSpec extends Specification {
return anchors
}
+ def 'Delete multiple schema-sets when cascade is allowed.'() {
+ given: '#numberOfAnchors anchors are associated with each schemaset'
+ mockCpsAdminService.getAnchors('my-dataspace', ['my-schemaset1', 'my-schemaset2']) >> createAnchors(numberOfAnchors * 2)
+ when: 'schema set deletion is requested with cascade allowed'
+ objectUnderTest.deleteSchemaSetsWithCascade('my-dataspace', ['my-schemaset1', 'my-schemaset2'])
+ then: 'anchor deletion is called #numberOfAnchors times'
+ mockCpsAdminService.deleteAnchors('my-dataspace', _)
+ and: 'persistence service method is invoked with same parameters'
+ mockCpsModulePersistenceService.deleteSchemaSets('my-dataspace', _)
+ and: 'schema sets will be removed from the cache'
+ 2 * mockYangTextSchemaSourceSetCache.removeFromCache('my-dataspace', _)
+ and: 'orphan yang resources are deleted'
+ 1 * mockCpsModulePersistenceService.deleteUnusedYangResourceModules()
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('my-dataspace')
+ and: 'the CpsValidator is called on the schemaSetNames'
+ 1 * mockCpsValidator.validateNameCharacters(_)
+ where: 'following parameters are used'
+ numberOfAnchors << [0, 3]
+ }
+
def 'Get all yang resources module references.'() {
given: 'an already present module reference'
def moduleReferences = [new ModuleReference('some module name','some revision name')]