/*
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Nordix Foundation.
- * Modifications Copyright (C) 2020 Bell Canada.
+ * Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
import org.onap.cps.spi.CpsAdminPersistenceService;
import org.onap.cps.spi.entities.AnchorEntity;
import org.onap.cps.spi.entities.DataspaceEntity;
+import org.onap.cps.spi.entities.SchemaSetEntity;
import org.onap.cps.spi.entities.YangResourceModuleReference;
import org.onap.cps.spi.exceptions.AlreadyDefinedException;
import org.onap.cps.spi.exceptions.DataspaceInUseException;
final int numberOfAssociatedAnchors = anchorRepository.countByDataspace(dataspaceEntity);
if (numberOfAssociatedAnchors != 0) {
throw new DataspaceInUseException(dataspaceName,
- String.format("Dataspace contains %d anchor(s)", numberOfAssociatedAnchors));
+ String.format("Dataspace contains %d anchor(s)", numberOfAssociatedAnchors));
}
final int numberOfAssociatedSchemaSets = schemaSetRepository.countByDataspace(dataspaceEntity);
if (numberOfAssociatedSchemaSets != 0) {
throw new DataspaceInUseException(dataspaceName,
- String.format("Dataspace contains %d schemaset(s)", numberOfAssociatedSchemaSets));
+ String.format("Dataspace contains %d schemaset(s)", numberOfAssociatedSchemaSets));
}
dataspaceRepository.delete(dataspaceEntity);
}
public Collection<Anchor> getAnchors(final String dataspaceName) {
final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
final Collection<AnchorEntity> anchorEntities = anchorRepository.findAllByDataspace(dataspaceEntity);
- return anchorEntities.stream().map(CpsAdminPersistenceServiceImpl::toAnchor).collect(Collectors.toList());
+ return anchorEntities.stream().map(CpsAdminPersistenceServiceImpl::toAnchor).collect(Collectors.toSet());
+ }
+
+ @Override
+ public Collection<Anchor> getAnchors(final String dataspaceName, final String schemaSetName) {
+ final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+ final SchemaSetEntity schemaSetEntity = schemaSetRepository.getByDataspaceAndName(
+ dataspaceEntity, schemaSetName);
+ return anchorRepository.findAllBySchemaSet(schemaSetEntity)
+ .stream().map(CpsAdminPersistenceServiceImpl::toAnchor)
+ .collect(Collectors.toSet());
}
@Override
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Nordix Foundation
- * Modifications Copyright (C) 2020-2021 Bell Canada.
+ * Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.exception.ConstraintViolationException;
-import org.onap.cps.spi.CascadeDeleteAllowed;
import org.onap.cps.spi.CpsAdminPersistenceService;
import org.onap.cps.spi.CpsModulePersistenceService;
-import org.onap.cps.spi.entities.AnchorEntity;
import org.onap.cps.spi.entities.SchemaSetEntity;
import org.onap.cps.spi.entities.YangResourceEntity;
import org.onap.cps.spi.entities.YangResourceModuleReference;
import org.onap.cps.spi.exceptions.AlreadyDefinedException;
import org.onap.cps.spi.exceptions.DuplicatedYangResourceException;
import org.onap.cps.spi.exceptions.ModelValidationException;
-import org.onap.cps.spi.exceptions.SchemaSetInUseException;
import org.onap.cps.spi.model.ModuleReference;
import org.onap.cps.spi.repository.AnchorRepository;
import org.onap.cps.spi.repository.DataspaceRepository;
@Override
@Transactional
- public void deleteSchemaSet(final String dataspaceName, final String schemaSetName,
- final CascadeDeleteAllowed cascadeDeleteAllowed) {
+ public void deleteSchemaSet(final String dataspaceName, final String schemaSetName) {
final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
final var schemaSetEntity =
schemaSetRepository.getByDataspaceAndName(dataspaceEntity, schemaSetName);
-
- final Collection<AnchorEntity> anchorEntities = anchorRepository.findAllBySchemaSet(schemaSetEntity);
- if (!anchorEntities.isEmpty()) {
- if (cascadeDeleteAllowed != CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED) {
- throw new SchemaSetInUseException(dataspaceName, schemaSetName);
- }
- fragmentRepository.deleteByAnchorIn(anchorEntities);
- anchorRepository.deleteAll(anchorEntities);
- }
schemaSetRepository.delete(schemaSetEntity);
+ }
+
+ @Override
+ @Transactional
+ public void deleteUnusedYangResourceModules() {
yangResourceRepository.deleteOrphans();
}
/**
* Convert the specified data integrity violation exception into a CPS duplicated Yang resource exception
* if the cause of the error is a yang checksum database constraint violation.
+ *
* @param originalException the original db exception.
* @param yangResourceEntities the collection of Yang resources involved in the db failure.
* @return an optional converted CPS duplicated Yang resource exception. The optional is empty if the original
/**
* Get the name of the yang resource having the specified checksum.
+ *
* @param checksum the checksum. Null is supported.
* @param yangResourceEntities the list of yang resources to search among.
* @return the name found or null if none.
/**
* Get the checksum that caused the constraint violation exception.
+ *
* @param exception the exception having the checksum in error.
* @return the checksum in error or null if not found.
*/
* ============LICENSE_START=======================================================
* Copyright (C) 2021 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.
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'
+ 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
result.size() == expectedAnchors.size()
result.containsAll(expectedAnchors)
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()]
+ 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()]
DATASPACE_WITH_NO_DATA || []
}
+ @Sql([CLEAR_DATA, SET_DATA])
+ def 'Get all anchors associated with schemaset in a dataspace.'() {
+ when: 'anchors are retrieved by dataspace and schema-set'
+ def anchors = objectUnderTest.getAnchors(dataspace, schemasetName)
+ then: ' the response contains expected anchors'
+ anchors == expectedAnchors
+ where:
+ scenario | dataspace | schemasetName || expectedAnchors
+ 'no-anchors' | 'DATASPACE-003' | 'SCHEMA-SET-002-NO-ANCHORS' || Collections.emptySet()
+ 'one-anchor' | 'DATASPACE-001' | 'SCHEMA-SET-001' || Set.of(new Anchor('ANCHOR-001', 'DATASPACE-001', 'SCHEMA-SET-001'))
+ }
+
+ @Sql([CLEAR_DATA, SET_DATA])
+ def 'Error Handling: Get all anchors associated with schemaset in a dataspace.'() {
+ when: 'anchors are retrieved by dataspace and schema-set'
+ def anchors = objectUnderTest.getAnchors(dataspace, schemasetName)
+ then: ' an expected expception is thrown'
+ thrown(expectedException)
+ where:
+ scenario | dataspace | schemasetName || expectedException
+ 'unknown-dataspace' | 'unknown' | 'SCHEMA-SET-002-NO-ANCHORS' || DataspaceNotFoundException
+ 'unknown-schemaset' | 'DATASPACE-001' | 'unknown-schema-set' || SchemaSetNotFoundException
+ }
+
@Sql(CLEAR_DATA)
def 'Get all anchors in unknown dataspace.'() {
when: 'attempt to get all anchors in an unknown dataspace'
}
@Sql([CLEAR_DATA, SET_DATA])
- def 'delete anchor error scenario: #scenario'(){
+ def 'delete anchor error scenario: #scenario'() {
when: 'delete anchor attempt is performed'
objectUnderTest.deleteAnchor(dataspaceName, anchorName)
then: 'an #expectedException is thrown'
def thrownException = thrown(expectedException)
thrownException.details.contains(expectedMessageDetails)
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 schemasets' | 'DATASPACE-003' || DataspaceInUseException | 'contains 1 schemaset(s)'
+ 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 schemasets' | 'DATASPACE-003' || DataspaceInUseException | 'contains 1 schemaset(s)'
}
}
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2021 Nordix Foundation
- * 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.
}
@Sql([CLEAR_DATA, SET_DATA])
- def 'Delete schema set with cascade delete prohibited but no anchors using it'() {
+ def 'Delete schema set'() {
when: 'a schema set is deleted with cascade-prohibited option'
- objectUnderTest.deleteSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NO_ANCHORS,
- CASCADE_DELETE_PROHIBITED)
+ 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
- and: 'any orphaned (not used by any schema set anymore) yang resources are deleted'
- def orphanedResourceId = 3100L
- yangResourceRepository.findById(orphanedResourceId).isPresent() == false
- and: 'any shared (still in use by other schema set) yang resources still persists'
- def sharedResourceId = 3003L
- yangResourceRepository.findById(sharedResourceId).isPresent()
- }
-
- @Sql([CLEAR_DATA, SET_DATA])
- def 'Delete schema set with cascade allowed.'() {
- when: 'a schema set is deleted with cascade-allowed option'
- objectUnderTest.deleteSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_WITH_ANCHORS_AND_DATA,
- CASCADE_DELETE_ALLOWED)
- then: 'the schema set has been deleted'
- schemaSetRepository
- .findByDataspaceAndName(dataspaceEntity, SCHEMA_SET_NAME_WITH_ANCHORS_AND_DATA).isPresent() == false
- and: 'the associated anchors are removed'
- def associatedAnchorsIds = [ 6001, 6002 ]
- associatedAnchorsIds.each {anchorRepository.findById(it).isPresent() == false }
- and: 'the fragment(s) under those anchors are removed'
- def fragmentUnderAnchor1Id = 7001L
- fragmentRepository.findById(fragmentUnderAnchor1Id).isPresent() == false
- and: 'the shared resources still persist'
- def sharedResourceIds = [ 3003L, 3004L ]
- sharedResourceIds.each {yangResourceRepository.findById(it).isPresent() }
}
@Sql([CLEAR_DATA, SET_DATA])
def 'Delete schema set error scenario: #scenario.'() {
when: 'attempt to delete a schema set where #scenario'
- objectUnderTest.deleteSchemaSet(dataspaceName, schemaSetName, CASCADE_DELETE_PROHIBITED)
+ objectUnderTest.deleteSchemaSet(dataspaceName, schemaSetName)
then: 'an #expectedException is thrown'
thrown(expectedException)
where: 'the following data is used'
scenario | dataspaceName | schemaSetName || expectedException
'dataspace does not exist' | 'unknown' | 'not-relevant' || DataspaceNotFoundException
'schema set does not exists' | DATASPACE_NAME | 'unknown' || SchemaSetNotFoundException
- 'cascade prohibited but schema set in use' | DATASPACE_NAME | SCHEMA_SET_NAME_WITH_ANCHORS_AND_DATA || SchemaSetInUseException
+ }
+
+ @Sql([CLEAR_DATA, SET_DATA])
+ def 'Delete only orphan Yang Resources'() {
+ given: 'a schema set is deleted and and yang resource is not used anymore'
+ objectUnderTest.deleteSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NO_ANCHORS)
+ when: 'orphan yang resources are deleted'
+ objectUnderTest.deleteUnusedYangResourceModules()
+ then: 'any orphaned (not used by any schema set anymore) yang resources are deleted'
+ def orphanedResourceId = 3100L
+ yangResourceRepository.findById(orphanedResourceId).isPresent() == false
+ and: 'any shared (still in use by other schema set) yang resources still persists'
+ def sharedResourceId = 3003L
+ yangResourceRepository.findById(sharedResourceId).isPresent()
}
def assertSchemaSetPersisted(expectedDataspaceName,
============LICENSE_START=======================================================
Copyright (C) 2020 Pantheon.tech
Modifications Copyright (C) 2020 Nordix Foundation.
- 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.
INSERT INTO DATASPACE (ID, NAME) VALUES
(1001, 'DATASPACE-001'),
- (1002, 'DATASPACE-002'),
+ (1002, 'DATASPACE-002-NO-DATA'),
(1003, 'DATASPACE-003');
INSERT INTO SCHEMA_SET (ID, NAME, DATASPACE_ID) VALUES
(2001, 'SCHEMA-SET-001', 1001),
(2002, 'SCHEMA-SET-002', 1001),
- (2003, 'SCHEMA-SET-002', 1003);
+ (2003, 'SCHEMA-SET-002-NO-ANCHORS', 1003);
INSERT INTO ANCHOR (ID, NAME, DATASPACE_ID, SCHEMA_SET_ID) VALUES
(3001, 'ANCHOR-001', 1001, 2001),
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Nordix Foundation
- * Modifications Copyright (C) 2020 Bell Canada.
+ * Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
package org.onap.cps.api;
import java.util.Collection;
-import org.checkerframework.checker.nullness.qual.NonNull;
import org.onap.cps.spi.exceptions.AlreadyDefinedException;
import org.onap.cps.spi.exceptions.CpsException;
import org.onap.cps.spi.model.Anchor;
* @param dataspaceName dataspace name
* @throws AlreadyDefinedException if dataspace with same name already exists
*/
- void createDataspace(@NonNull String dataspaceName);
+ void createDataspace(String dataspaceName);
/**
* Delete dataspace.
*
* @param dataspaceName the name of the dataspace to delete
*/
- void deleteDataspace(@NonNull String dataspaceName);
+ void deleteDataspace(String dataspaceName);
/**
* Create an Anchor.
* @param anchorName anchor name
* @throws CpsException if input data is invalid.
*/
- void createAnchor(@NonNull String dataspaceName, @NonNull String schemaSetName, @NonNull String anchorName);
+ void createAnchor(String dataspaceName, String schemaSetName, String anchorName);
/**
* Read all anchors in the given dataspace.
* @param dataspaceName dataspace name
* @return a collection of anchors
*/
- @NonNull
- Collection<Anchor> getAnchors(@NonNull String dataspaceName);
+ Collection<Anchor> getAnchors(String dataspaceName);
+
+ /**
+ * Read all anchors associated the given schema-set in the given dataspace.
+ *
+ * @param dataspaceName dataspace name
+ * @param schemaSetName schema-set name
+ * @return a collection of anchors
+ */
+ Collection<Anchor> getAnchors(String dataspaceName, String schemaSetName);
/**
* Get an anchor in the given dataspace using the anchor name.
* @param anchorName anchor name
* @return an anchor
*/
- @NonNull
- Anchor getAnchor(@NonNull String dataspaceName, @NonNull String anchorName);
+ Anchor getAnchor(String dataspaceName, String anchorName);
/**
* Delete anchor by name in given dataspace.
* @param dataspaceName dataspace name
* @param anchorName anchor name
*/
- void deleteAnchor(@NonNull String dataspaceName, @NonNull String anchorName);
+ void deleteAnchor(String dataspaceName, String anchorName);
/**
* Query anchor names for the given module names in the provided dataspace.
*
- *
* @param dataspaceName dataspace name
- * @param moduleNames a collection of module names
+ * @param moduleNames a collection of module names
* @return a collection of anchor names in the given dataspace. The schema set for each anchor must include all the
* given module names
*/
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Nordix Foundation
- * Modifications Copyright (C) 2020 Bell Canada.
+ * Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
return cpsAdminPersistenceService.getAnchors(dataspaceName);
}
+ @Override
+ public Collection<Anchor> getAnchors(final String dataspaceName, final String schemaSetName) {
+ return cpsAdminPersistenceService.getAnchors(dataspaceName, schemaSetName);
+ }
+
@Override
public Anchor getAnchor(final String dataspaceName, final String anchorName) {
return cpsAdminPersistenceService.getAnchor(dataspaceName, anchorName);
* ============LICENSE_START=======================================================
* Copyright (C) 2020-2021 Nordix Foundation
* Modifications Copyright (C) 2020-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.
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import org.onap.cps.api.CpsAdminService;
import org.onap.cps.api.CpsModuleService;
import org.onap.cps.spi.CascadeDeleteAllowed;
import org.onap.cps.spi.CpsModulePersistenceService;
+import org.onap.cps.spi.exceptions.SchemaSetInUseException;
+import org.onap.cps.spi.model.Anchor;
import org.onap.cps.spi.model.ModuleReference;
import org.onap.cps.spi.model.SchemaSet;
import org.onap.cps.yang.YangTextSchemaSourceSetBuilder;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
@Service("CpsModuleServiceImpl")
public class CpsModuleServiceImpl implements CpsModuleService {
- @Autowired
private CpsModulePersistenceService cpsModulePersistenceService;
-
- @Autowired
private YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache;
+ private CpsAdminService cpsAdminService;
+
+ /**
+ * Create an instance of CpsModuleServiceImpl.
+ *
+ * @param cpsModulePersistenceService cpsModulePersistenceService
+ * @param yangTextSchemaSourceSetCache yangTextSchemaSourceSetCache
+ * @param cpsAdminService cpsAdminService
+ */
+ public CpsModuleServiceImpl(final CpsModulePersistenceService cpsModulePersistenceService,
+ final YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache, final CpsAdminService cpsAdminService) {
+ this.cpsModulePersistenceService = cpsModulePersistenceService;
+ this.yangTextSchemaSourceSetCache = yangTextSchemaSourceSetCache;
+ this.cpsAdminService = cpsAdminService;
+ }
@Override
public void createSchemaSet(final String dataspaceName, final String schemaSetName,
@Override
public void createSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
- final Map<String, String> newYangResourcesModuleNameToContentMap,
- final List<ModuleReference> moduleReferences) {
+ final Map<String, String> newYangResourcesModuleNameToContentMap,
+ final List<ModuleReference> moduleReferences) {
cpsModulePersistenceService.storeSchemaSetFromModules(dataspaceName, schemaSetName,
- newYangResourcesModuleNameToContentMap, moduleReferences);
+ newYangResourcesModuleNameToContentMap, moduleReferences);
}
}
@Override
+ @Transactional
public void deleteSchemaSet(final String dataspaceName, final String schemaSetName,
final CascadeDeleteAllowed cascadeDeleteAllowed) {
- cpsModulePersistenceService.deleteSchemaSet(dataspaceName, schemaSetName, cascadeDeleteAllowed);
+ final Collection<Anchor> anchors = cpsAdminService.getAnchors(dataspaceName, schemaSetName);
+ if (!anchors.isEmpty() && isCascadeDeleteProhibited(cascadeDeleteAllowed)) {
+ throw new SchemaSetInUseException(dataspaceName, schemaSetName);
+ }
+ for (final Anchor anchor : anchors) {
+ cpsAdminService.deleteAnchor(dataspaceName, anchor.getName());
+ }
+ cpsModulePersistenceService.deleteSchemaSet(dataspaceName, schemaSetName);
+ cpsModulePersistenceService.deleteUnusedYangResourceModules();
}
@Override
final String anchorName) {
return cpsModulePersistenceService.getYangResourceModuleReferences(dataspaceName, anchorName);
}
+
+ private boolean isCascadeDeleteProhibited(final CascadeDeleteAllowed cascadeDeleteAllowed) {
+ return CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED == cascadeDeleteAllowed;
+ }
}
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Nordix Foundation.
- * Modifications Copyright (C) 2020 Bell Canada.
+ * Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
package org.onap.cps.spi;
import java.util.Collection;
-import org.checkerframework.checker.nullness.qual.NonNull;
import org.onap.cps.spi.exceptions.AlreadyDefinedException;
import org.onap.cps.spi.model.Anchor;
* @param dataspaceName dataspace name
* @throws AlreadyDefinedException if dataspace with same name already exists
*/
- void createDataspace(@NonNull String dataspaceName);
+ void createDataspace(String dataspaceName);
/**
* Delete dataspace.
*
* @param dataspaceName the name of the dataspace to delete
*/
- void deleteDataspace(@NonNull String dataspaceName);
+ void deleteDataspace(String dataspaceName);
/**
* Create an Anchor.
* @param schemaSetName schema set name
* @param anchorName anchor name
*/
- void createAnchor(@NonNull String dataspaceName, @NonNull String schemaSetName, @NonNull String anchorName);
+ void createAnchor(String dataspaceName, String schemaSetName, String anchorName);
+
+ /**
+ * Read all anchors associated the given schema-set in the given dataspace.
+ *
+ * @param dataspaceName dataspace name
+ * @param schemaSetName schema-set name
+ * @return a collection of anchors
+ */
+ Collection<Anchor> getAnchors(String dataspaceName, String schemaSetName);
/**
* Read all anchors in the given a dataspace.
* @param dataspaceName dataspace name
* @return a collection of anchors
*/
- @NonNull
- Collection<Anchor> getAnchors(@NonNull String dataspaceName);
+ Collection<Anchor> getAnchors(String dataspaceName);
/**
* Query anchor names for the given module names in the provided dataspace.
* @param anchorName anchor name
* @return an anchor
*/
- @NonNull
- Anchor getAnchor(@NonNull String dataspaceName, @NonNull String anchorName);
+ Anchor getAnchor(String dataspaceName, String anchorName);
/**
* Delete anchor by name in given dataspace.
* @param dataspaceName dataspace name
* @param anchorName anchor name
*/
- void deleteAnchor(@NonNull String dataspaceName, @NonNull String anchorName);
+ void deleteAnchor(String dataspaceName, String anchorName);
}
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Nordix Foundation
- * Modifications Copyright (C) 2020 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.
import java.util.Collection;
import java.util.List;
import java.util.Map;
-import org.checkerframework.checker.nullness.qual.NonNull;
-import org.onap.cps.spi.exceptions.DataInUseException;
import org.onap.cps.spi.model.ModuleReference;
/**
* @param schemaSetName schema set name
* @param yangResourcesNameToContentMap YANG resources (files) map where key is a name and value is content
*/
- void storeSchemaSet(@NonNull String dataspaceName, @NonNull String schemaSetName,
- @NonNull Map<String, String> yangResourcesNameToContentMap);
+ void storeSchemaSet(String dataspaceName, String schemaSetName, Map<String, String> yangResourcesNameToContentMap);
/**
* Stores a schema set from new modules and existing modules.
* @param dataspaceName Dataspace name
* @param schemaSetName Schema set name
* @param newYangResourcesModuleNameToContentMap YANG resources map where key is a module name and value is content
- * @param moduleReferences List of YANG resources module references
+ * @param moduleReferences List of YANG resources module references
*/
- void storeSchemaSetFromModules(@NonNull String dataspaceName, @NonNull String schemaSetName,
- @NonNull Map<String, String> newYangResourcesModuleNameToContentMap,
- @NonNull List<ModuleReference> moduleReferences);
+ void storeSchemaSetFromModules(String dataspaceName, String schemaSetName,
+ Map<String, String> newYangResourcesModuleNameToContentMap, List<ModuleReference> moduleReferences);
/**
* Deletes Schema Set.
*
- * @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
+ * @param dataspaceName dataspace name
+ * @param schemaSetName schema set name
*/
- void deleteSchemaSet(@NonNull String dataspaceName, @NonNull String schemaSetName,
- @NonNull CascadeDeleteAllowed cascadeDeleteAllowed);
+ void deleteSchemaSet(String dataspaceName, String schemaSetName);
/**
* Returns YANG resources per specific dataspace / schemaSetName.
*
- * @param dataspaceName dataspace name
+ * @param dataspaceName dataspace name
* @param schemaSetName schema set name
* @return YANG resources (files) map where key is a name and value is content
*/
- @NonNull
- Map<String, String> getYangSchemaResources(@NonNull String dataspaceName,
- @NonNull String schemaSetName);
+ Map<String, String> getYangSchemaResources(String dataspaceName, String schemaSetName);
/**
* Returns YANG resources per specific dataspace / anchorName.
*
* @param dataspaceName dataspace name
- * @param anchorName anchor name
+ * @param anchorName anchor name
* @return YANG resources (files) map where key is a name and value is content
*/
- @NonNull
- Map<String, String> getYangSchemaSetResources(@NonNull String dataspaceName,
- @NonNull String anchorName);
+ Map<String, String> getYangSchemaSetResources(String dataspaceName, String anchorName);
/**
* Returns YANG resources module references for the given dataspace name.
* @return a collection of module names and revisions
*/
Collection<ModuleReference> getYangResourceModuleReferences(String dataspaceName, String anchorName);
+
+ /**
+ * Remove unused Yang Resource Modules.
+ */
+ void deleteUnusedYangResourceModules();
}
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Nordix Foundation
- * Modifications Copyright (C) 2020 Bell Canada.
+ * Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
objectUnderTest.getAnchors('someDataspace') == anchors
}
+ def 'Retrieve all anchors for schema-set.'() {
+ given: 'that anchor is associated with the dataspace and schemaset'
+ def anchors = [new Anchor()]
+ mockCpsAdminPersistenceService.getAnchors('someDataspace', 'someSchemaSet') >> anchors
+ expect: 'the collection provided by persistence service is returned as result'
+ objectUnderTest.getAnchors('someDataspace', 'someSchemaSet') == anchors
+ }
+
def 'Retrieve anchor for dataspace and provided anchor name.'() {
given: 'that anchor name is associated with the dataspace'
Anchor anchor = new Anchor()
* ============LICENSE_START=======================================================
* Copyright (C) 2020-2021 Nordix Foundation
* Modifications Copyright (C) 2020-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.
package org.onap.cps.api.impl
import org.onap.cps.TestUtils
+import org.onap.cps.api.CpsAdminService
import org.onap.cps.spi.CpsModulePersistenceService
import org.onap.cps.spi.exceptions.ModelValidationException
+import org.onap.cps.spi.exceptions.SchemaSetInUseException
+import org.onap.cps.spi.model.Anchor
import org.onap.cps.spi.model.ExtendedModuleReference
import org.onap.cps.spi.model.ModuleReference
import org.spockframework.spring.SpringBean
import org.springframework.cache.caffeine.CaffeineCacheManager
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
-
import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED
import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED
@SpringBootTest
@EnableCaching
-@ContextConfiguration(classes = [YangTextSchemaSourceSetCache.class, CpsModuleServiceImpl.class])
+@ContextConfiguration(classes = [YangTextSchemaSourceSetCache, CpsModuleServiceImpl])
class CpsModuleServiceImplSpec extends Specification {
@SpringBean
CpsModulePersistenceService mockModuleStoreService = Mock()
+ @SpringBean
+ CpsAdminService mockCpsAdminService = Mock()
+
@SpringBean
CacheManager cacheManager = new CaffeineCacheManager("yangSchema")
1 * mockModuleStoreService.getYangSchemaResources('someDataspace', 'someSchemaSet') >> yangResourcesNameToContentMap
}
- def 'Delete set by name and dataspace with #cascadeDeleteOption.'() {
- when: 'schema set deletion is requested'
- objectUnderTest.deleteSchemaSet(dataspaceName, schemaSetname, cascadeDeleteOption)
- then: 'persistence service method is invoked with same parameters'
- mockModuleStoreService.deleteSchemaSet(dataspaceName, schemaSetname, cascadeDeleteOption)
+ def 'Delete schema-set when cascade is allowed.'() {
+ given: '#numberOfAnchors anchors are associated with schemaset'
+ def associatedAnchors = createAnchors(numberOfAnchors)
+ mockCpsAdminService.getAnchors('my-dataspace', 'my-schemaset') >> associatedAnchors
+ when: 'schema set deletion is requested with cascade allowed'
+ objectUnderTest.deleteSchemaSet('my-dataspace', 'my-schemaset', CASCADE_DELETE_ALLOWED)
+ then: 'anchor deletion is called #numberOfAnchors times'
+ numberOfAnchors * mockCpsAdminService.deleteAnchor('my-dataspace', _)
+ and: 'persistence service method is invoked with same parameters'
+ 1 * mockModuleStoreService.deleteSchemaSet('my-dataspace', 'my-schemaset')
+ and: 'orphan yang resources are deleted'
+ 1 * mockModuleStoreService.deleteUnusedYangResourceModules()
where: 'following parameters are used'
- dataspaceName | schemaSetname | cascadeDeleteOption
- 'dataspace-1' | 'schemas-set-1' | CASCADE_DELETE_ALLOWED
- 'dataspace-2' | 'schemas-set-2' | CASCADE_DELETE_PROHIBITED
+ numberOfAnchors << [0, 3]
+ }
+
+ def 'Delete schema-set when cascade is prohibited.'() {
+ given: 'no anchors are associated with schemaset'
+ mockCpsAdminService.getAnchors('my-dataspace', 'my-schemaset') >> Collections.emptyList()
+ when: 'schema set deletion is requested with cascade allowed'
+ objectUnderTest.deleteSchemaSet('my-dataspace', 'my-schemaset', CASCADE_DELETE_PROHIBITED)
+ then: 'no anchors are deleted'
+ 0 * mockCpsAdminService.deleteAnchor(_, _)
+ and: 'persistence service method is invoked with same parameters'
+ 1 * mockModuleStoreService.deleteSchemaSet('my-dataspace', 'my-schemaset')
+ and: 'orphan yang resources are deleted'
+ 1 * mockModuleStoreService.deleteUnusedYangResourceModules()
+ }
+
+ def 'Delete schema-set when cascade is prohibited and schema-set has anchors.'() {
+ given: '2 anchors are associated with schemaset'
+ mockCpsAdminService.getAnchors('my-dataspace', 'my-schemaset') >> createAnchors(2)
+ when: 'schema set deletion is requested with cascade allowed'
+ objectUnderTest.deleteSchemaSet('my-dataspace', 'my-schemaset', CASCADE_DELETE_PROHIBITED)
+ then: 'Schema-Set in Use exception is thrown'
+ thrown(SchemaSetInUseException)
+ }
+
+ def createAnchors(int anchorCount) {
+ def anchors = []
+ (0..<anchorCount).each { anchors.add(new Anchor("my-anchor-$it", 'my-dataspace', 'my-schemaset')) }
+ return anchors
}
- def 'Get all yang resources module references.'(){
+ def 'Get all yang resources module references.'() {
given: 'an already present module reference'
def moduleReferences = [new ExtendedModuleReference()]
mockModuleStoreService.getYangResourceModuleReferences('someDataspaceName') >> moduleReferences
}
- def 'Get all yang resources module references for the given dataspace name and anchor name.'(){
+ def 'Get all yang resources module references for the given dataspace name and anchor name.'() {
given: 'the module store service service returns a list module references'
def moduleReferences = [new ModuleReference()]
mockModuleStoreService.getYangResourceModuleReferences('someDataspaceName', 'someAnchorName') >> moduleReferences
/*\r
* ============LICENSE_START=======================================================\r
* Copyright (C) 2021 Nordix Foundation.\r
- * Modifications Copyright (C) 2021 Bell Canada.\r
+ * Modifications Copyright (C) 2021-2022 Bell Canada.\r
* Modifications Copyright (C) 2021 Pantheon.tech\r
* ================================================================================\r
* Licensed under the Apache License, Version 2.0 (the "License");\r
\r
package org.onap.cps.api.impl\r
\r
-import java.time.OffsetDateTime\r
import org.onap.cps.TestUtils\r
import org.onap.cps.api.CpsAdminService\r
import org.onap.cps.notification.NotificationService\r
def mockDataStoreService = Mock(CpsDataPersistenceService)\r
def mockCpsAdminService = Mock(CpsAdminService)\r
def mockNotificationService = Mock(NotificationService)\r
- def cpsModuleServiceImpl = new CpsModuleServiceImpl()\r
def cpsDataServiceImpl = new CpsDataServiceImpl()\r
def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)\r
+ def cpsModuleServiceImpl = new CpsModuleServiceImpl(mockModuleStoreService,\r
+ mockYangTextSchemaSourceSetCache,mockCpsAdminService )\r
\r
def dataspaceName = 'someDataspace'\r
def anchorName = 'someAnchor'\r
cpsDataServiceImpl.cpsAdminService = mockCpsAdminService\r
cpsDataServiceImpl.yangTextSchemaSourceSetCache = mockYangTextSchemaSourceSetCache\r
cpsDataServiceImpl.notificationService = mockNotificationService\r
- cpsModuleServiceImpl.yangTextSchemaSourceSetCache = mockYangTextSchemaSourceSetCache\r
- cpsModuleServiceImpl.cpsModulePersistenceService = mockModuleStoreService\r
}\r
\r
def 'E2E model can be parsed by CPS.'() {\r