diff options
27 files changed, 288 insertions, 455 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java index f929d6708c..79f5496eb7 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java @@ -56,7 +56,7 @@ public class ModuleSyncService { @AllArgsConstructor private static final class ModuleDelta { Collection<ModuleReference> allModuleReferences; - Map<String, String> newModuleNameToContentMap; + Map<String, String> newYangResourceContentPerName; } /** @@ -90,7 +90,7 @@ public class ModuleSyncService { if (sourceModuleSetTag.isEmpty() && targetModuleSetTag.isEmpty()) { final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle, targetModuleSetTag); cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, - schemaSetName, moduleDelta.newModuleNameToContentMap, moduleDelta.allModuleReferences); + schemaSetName, moduleDelta.newYangResourceContentPerName, moduleDelta.allModuleReferences); } else { syncAndCreateSchemaSet(yangModelCmHandle, schemaSetName, targetModuleSetTag); cpsAnchorService.updateAnchorSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, schemaSetName); @@ -111,7 +111,7 @@ public class ModuleSyncService { cpsModuleService.createSchemaSetFromModules( NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName, - moduleDelta.newModuleNameToContentMap, + moduleDelta.newYangResourceContentPerName, moduleDelta.allModuleReferences ); log.info("Successfully created Schema Set {} for CM Handle {}", schemaSetName, @@ -133,11 +133,11 @@ public class ModuleSyncService { dmiModelOperations.getModuleReferences(yangModelCmHandle, targetModuleSetTag); final Collection<ModuleReference> newModuleReferences = cpsModuleService.identifyNewModuleReferences(allModuleReferences); - final Map<String, String> newYangResources = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, - targetModuleSetTag, newModuleReferences); + final Map<String, String> newYangResourceContentPerName = + dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, targetModuleSetTag, newModuleReferences); log.debug("Module delta calculated for CM handle ID: {}. All references: {}. New modules: {}", - yangModelCmHandle.getId(), allModuleReferences, newYangResources.keySet()); - return new ModuleDelta(allModuleReferences, newYangResources); + yangModelCmHandle.getId(), allModuleReferences, newYangResourceContentPerName.keySet()); + return new ModuleDelta(allModuleReferences, newYangResourceContentPerName); } private void setCmHandleModuleSetTag(final YangModelCmHandle yangModelCmHandle, final String newModuleSetTag) { diff --git a/cps-ri/pom.xml b/cps-ri/pom.xml index 7ae85df851..aa5fad9ac2 100644 --- a/cps-ri/pom.xml +++ b/cps-ri/pom.xml @@ -3,7 +3,7 @@ ============LICENSE_START=======================================================
Copyright (C) 2020-2021 Pantheon.tech
Modifications Copyright (C) 2020-2021 Bell Canada
- Modifications Copyright (C) 2020-2024 Nordix Foundation
+ Modifications Copyright (C) 2020-2025 Nordix Foundation
================================================================================
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@ <artifactId>cps-ri</artifactId>
<properties>
- <minimum-coverage>0.29</minimum-coverage>
+ <minimum-coverage>0.31</minimum-coverage>
<!-- Additional coverage is provided by integration-test module -->
</properties>
diff --git a/cps-ri/src/main/java/org/onap/cps/ri/CpsAdminPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/ri/CpsAdminPersistenceServiceImpl.java index 494d6919da..588a639ab8 100755 --- a/cps-ri/src/main/java/org/onap/cps/ri/CpsAdminPersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/ri/CpsAdminPersistenceServiceImpl.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020-2024 Nordix Foundation. + * Copyright (C) 2020-2025 Nordix Foundation. * Modifications Copyright (C) 2020-2022 Bell Canada. * Modifications Copyright (C) 2021 Pantheon.tech * Modifications Copyright (C) 2022 TechMahindra Ltd. @@ -91,10 +91,10 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic @Override public void createAnchor(final String dataspaceName, final String schemaSetName, final String anchorName) { - final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName); - final var schemaSetEntity = - schemaSetRepository.getByDataspaceAndName(dataspaceEntity, schemaSetName); - final var anchorEntity = AnchorEntity.builder() + final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName); + final SchemaSetEntity schemaSetEntity = schemaSetRepository + .getByDataspaceAndName(dataspaceEntity, schemaSetName); + final AnchorEntity anchorEntity = AnchorEntity.builder() .name(anchorName) .dataspace(dataspaceEntity) .schemaSet(schemaSetEntity) @@ -114,7 +114,7 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic @Override public Collection<Anchor> getAnchors(final String dataspaceName) { - final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName); + final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName); final Collection<AnchorEntity> anchorEntities = anchorRepository.findAllByDataspace(dataspaceEntity); return anchorEntities.stream().map(CpsAdminPersistenceServiceImpl::toAnchor).collect(Collectors.toSet()); } @@ -154,14 +154,14 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic @Transactional @Override public void deleteAnchor(final String dataspaceName, final String anchorName) { - final var anchorEntity = getAnchorEntity(dataspaceName, anchorName); + final AnchorEntity anchorEntity = getAnchorEntity(dataspaceName, anchorName); anchorRepository.delete(anchorEntity); } @Transactional @Override public void deleteAnchors(final String dataspaceName, final Collection<String> anchorNames) { - final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName); + final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName); anchorRepository.deleteAllByDataspaceAndNameIn(dataspaceEntity, anchorNames); } @@ -178,7 +178,7 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic } private AnchorEntity getAnchorEntity(final String dataspaceName, final String anchorName) { - final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName); + final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName); return anchorRepository.getByDataspaceAndName(dataspaceEntity, anchorName); } diff --git a/cps-ri/src/main/java/org/onap/cps/ri/CpsModulePersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/ri/CpsModulePersistenceServiceImpl.java index aaf6165471..dbc6c28ec5 100755 --- a/cps-ri/src/main/java/org/onap/cps/ri/CpsModulePersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/ri/CpsModulePersistenceServiceImpl.java @@ -36,7 +36,6 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -103,10 +102,9 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ @Override public Collection<ModuleReference> getYangResourceModuleReferences(final String dataspaceName) { - final Set<YangResourceModuleReference> yangResourceModuleReferenceList = + final Collection<YangResourceModuleReference> yangResourceModuleReferences = yangResourceRepository.findAllModuleReferencesByDataspace(dataspaceName); - return yangResourceModuleReferenceList.stream().map(CpsModulePersistenceServiceImpl::toModuleReference) - .collect(Collectors.toList()); + return yangResourceModuleReferences.stream().map(CpsModulePersistenceServiceImpl::toModuleReference).toList(); } @Override @@ -150,19 +148,24 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ @Override @Transactional - public void storeSchemaSet(final String dataspaceName, final String schemaSetName, - final Map<String, String> moduleReferenceNameToContentMap) { - final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName); - final Set<YangResourceEntity> yangResourceEntities = synchronizeYangResources(moduleReferenceNameToContentMap); - final SchemaSetEntity schemaSetEntity = new SchemaSetEntity(); - schemaSetEntity.setName(schemaSetName); - schemaSetEntity.setDataspace(dataspaceEntity); - schemaSetEntity.setYangResources(yangResourceEntities); - try { - schemaSetRepository.save(schemaSetEntity); - } catch (final DataIntegrityViolationException e) { - throw AlreadyDefinedException.forSchemaSet(schemaSetName, dataspaceName, e); - } + @Timed(value = "cps.module.persistence.schemaset.create", + description = "Time taken to store a schemaset (list of module references)") + public void createSchemaSet(final String dataspaceName, final String schemaSetName, + final Map<String, String> yangResourceContentPerName) { + final Set<YangResourceEntity> yangResourceEntities = synchronizeYangResources(yangResourceContentPerName); + createAndSaveSchemaSetEntity(dataspaceName, schemaSetName, yangResourceEntities); + } + + @Override + @Transactional + @Timed(value = "cps.module.persistence.schemaset.createFromNewAndExistingModules", + description = "Time taken to store a schemaset (from new and existing)") + public void createSchemaSetFromNewAndExistingModules(final String dataspaceName, final String schemaSetName, + final Map<String, String> newYangResourceContentPerName, + final Collection<ModuleReference> allModuleReferences) { + synchronizeYangResources(newYangResourceContentPerName); + final Set<YangResourceEntity> allYangResourceEntities = getYangResourceEntities(allModuleReferences); + createAndSaveSchemaSetEntity(dataspaceName, schemaSetName, allYangResourceEntities); } @Override @@ -181,22 +184,6 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ @Override @Transactional - @Timed(value = "cps.module.persistence.schemaset.store", - description = "Time taken to store a schemaset (list of module references)") - public void storeSchemaSetFromModules(final String dataspaceName, final String schemaSetName, - final Map<String, String> newModuleNameToContentMap, - final Collection<ModuleReference> allModuleReferences) { - storeSchemaSet(dataspaceName, schemaSetName, newModuleNameToContentMap); - final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName); - final SchemaSetEntity schemaSetEntity = - schemaSetRepository.getByDataspaceAndName(dataspaceEntity, schemaSetName); - final List<Integer> allYangResourceIds = - yangResourceRepository.getResourceIdsByModuleReferences(allModuleReferences); - yangResourceRepository.insertSchemaSetIdYangResourceId(schemaSetEntity.getId(), allYangResourceIds); - } - - @Override - @Transactional public void deleteSchemaSet(final String dataspaceName, final String schemaSetName) { final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName); final SchemaSetEntity schemaSetEntity = @@ -213,14 +200,16 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ @Override @Transactional - public void updateSchemaSetFromModules(final String dataspaceName, final String schemaSetName, - final Map<String, String> newModuleNameToContentMap, - final Collection<ModuleReference> allModuleReferences) { + public void updateSchemaSetFromNewAndExistingModules(final String dataspaceName, final String schemaSetName, + final Map<String, String> newYangResourcesPerName, + final Collection<ModuleReference> allModuleReferences) { final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName); final SchemaSetEntity schemaSetEntity = schemaSetRepository.getByDataspaceAndName(dataspaceEntity, schemaSetName); - storeAndLinkNewModules(newModuleNameToContentMap, schemaSetEntity); - updateAllModuleReferences(allModuleReferences, schemaSetEntity.getId()); + synchronizeYangResources(newYangResourcesPerName); + final Set<YangResourceEntity> allYangResourceEntities = getYangResourceEntities(allModuleReferences); + schemaSetEntity.setYangResources(allYangResourceEntities); + schemaSetRepository.save(schemaSetEntity); } @Override @@ -237,9 +226,35 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ return moduleReferenceRepository.identifyNewModuleReferences(moduleReferencesToCheck); } - private Set<YangResourceEntity> synchronizeYangResources( - final Map<String, String> moduleReferenceNameToContentMap) { - final Map<String, YangResourceEntity> checksumToEntityMap = moduleReferenceNameToContentMap.entrySet().stream() + private Set<YangResourceEntity> synchronizeYangResources(final Map<String, String> yangResourceContentPerName) { + final Map<String, YangResourceEntity> yangResourceEntitiesPerChecksum = + getYangResourceEntityPerChecksum(yangResourceContentPerName); + + final List<YangResourceEntity> existingYangResourceEntities = + yangResourceRepository.findAllByChecksumIn(yangResourceEntitiesPerChecksum.keySet()); + + existingYangResourceEntities.forEach(exist -> yangResourceEntitiesPerChecksum.remove(exist.getChecksum())); + final Collection<YangResourceEntity> newYangResourceEntities = yangResourceEntitiesPerChecksum.values(); + + if (!newYangResourceEntities.isEmpty()) { + try { + yangResourceRepository.saveAll(newYangResourceEntities); + } catch (final DataIntegrityViolationException dataIntegrityViolationException) { + convertExceptionIfNeeded(dataIntegrityViolationException, newYangResourceEntities); + } + } + + // return ALL yang resourceEntities + return ImmutableSet.<YangResourceEntity>builder() + .addAll(existingYangResourceEntities) + .addAll(newYangResourceEntities) + .build(); + } + + private static Map<String, YangResourceEntity> getYangResourceEntityPerChecksum( + final Map<String, String> yangResourceContentPerName) { + final Map<String, YangResourceEntity> yangResourceEntityPerChecksum = + yangResourceContentPerName.entrySet().stream() .map(entry -> { final String checksum = DigestUtils.sha256Hex(entry.getValue().getBytes(StandardCharsets.UTF_8)); final Map<String, String> moduleNameAndRevisionMap = createModuleNameAndRevisionMap(entry.getKey(), @@ -256,29 +271,22 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ YangResourceEntity::getChecksum, entity -> entity )); + return yangResourceEntityPerChecksum; + } - final List<YangResourceEntity> existingYangResourceEntities = - yangResourceRepository.findAllByChecksumIn(checksumToEntityMap.keySet()); - existingYangResourceEntities.forEach(yangFile -> checksumToEntityMap.remove(yangFile.getChecksum())); - - final Collection<YangResourceEntity> newYangResourceEntities = checksumToEntityMap.values(); - if (!newYangResourceEntities.isEmpty()) { - try { - yangResourceRepository.saveAll(newYangResourceEntities); - } catch (final DataIntegrityViolationException dataIntegrityViolationException) { - // Throw a CPS duplicated Yang resource exception if the cause of the error is a yang checksum - // database constraint violation. If it is not, then throw the original exception - final Optional<DuplicatedYangResourceException> convertedException = - convertToDuplicatedYangResourceException( - dataIntegrityViolationException, newYangResourceEntities); - throw convertedException.isPresent() ? convertedException.get() : dataIntegrityViolationException; - } + private void createAndSaveSchemaSetEntity(final String dataspaceName, + final String schemaSetName, + final Set<YangResourceEntity> yangResourceEntities) { + final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName); + final SchemaSetEntity schemaSetEntity = new SchemaSetEntity(); + schemaSetEntity.setName(schemaSetName); + schemaSetEntity.setDataspace(dataspaceEntity); + schemaSetEntity.setYangResources(yangResourceEntities); + try { + schemaSetRepository.save(schemaSetEntity); + } catch (final DataIntegrityViolationException e) { + throw AlreadyDefinedException.forSchemaSet(schemaSetName, dataspaceName, e); } - - return ImmutableSet.<YangResourceEntity>builder() - .addAll(existingYangResourceEntities) - .addAll(newYangResourceEntities) - .build(); } private static Map<String, String> createModuleNameAndRevisionMap(final String sourceName, final String source) { @@ -323,6 +331,14 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ return RevisionSourceIdentifier.create(sourceName); } + private void convertExceptionIfNeeded(final DataIntegrityViolationException dataIntegrityViolationException, + final Collection<YangResourceEntity> newYangResourceEntities) { + final Optional<DuplicatedYangResourceException> convertedException = + convertToDuplicatedYangResourceException( + dataIntegrityViolationException, newYangResourceEntities); + throw convertedException.isPresent() ? convertedException.get() : dataIntegrityViolationException; + } + /** * 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. @@ -372,6 +388,13 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ return "no checksum found"; } + private Set<YangResourceEntity> getYangResourceEntities(final Collection<ModuleReference> moduleReferences) { + return moduleReferences.stream().map(moduleReference -> + yangResourceRepository + .findByModuleNameAndRevision(moduleReference.getModuleName(), moduleReference.getRevision())) + .collect(Collectors.toSet()); + } + private static ModuleReference toModuleReference( final YangResourceModuleReference yangResourceModuleReference) { return ModuleReference.builder() @@ -392,20 +415,4 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ .dataspaceName(schemaSetEntity.getDataspace().getName()).build(); } - private void storeAndLinkNewModules(final Map<String, String> newModuleNameToContentMap, - final SchemaSetEntity schemaSetEntity) { - final Set<YangResourceEntity> yangResourceEntities - = new HashSet<>(synchronizeYangResources(newModuleNameToContentMap)); - schemaSetEntity.setYangResources(yangResourceEntities); - schemaSetRepository.save(schemaSetEntity); - } - - private void updateAllModuleReferences(final Collection<ModuleReference> allModuleReferences, - final Integer schemaSetEntityId) { - yangResourceRepository.deleteSchemaSetYangResourceForSchemaSetId(schemaSetEntityId); - final List<Integer> allYangResourceIds = - yangResourceRepository.getResourceIdsByModuleReferences(allModuleReferences); - yangResourceRepository.insertSchemaSetIdYangResourceId(schemaSetEntityId, allYangResourceIds); - } - } diff --git a/cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetYangResourceRepository.java b/cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetYangResourceRepository.java deleted file mode 100644 index 410dcc2e26..0000000000 --- a/cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetYangResourceRepository.java +++ /dev/null @@ -1,36 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021-2025 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ri.repository; - -import java.util.List; - -public interface SchemaSetYangResourceRepository { - - - /** - * Link yang resources (ids) with a schema set (id). - * - * @param schemaSetId the schema set id - * @param yangResourceIds list of yang resource ids - */ - void insertSchemaSetIdYangResourceId(final Integer schemaSetId, final List<Integer> yangResourceIds); - -} diff --git a/cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetYangResourceRepositoryImpl.java b/cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetYangResourceRepositoryImpl.java deleted file mode 100644 index 989809af5b..0000000000 --- a/cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetYangResourceRepositoryImpl.java +++ /dev/null @@ -1,58 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021-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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ri.repository; - -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import java.sql.PreparedStatement; -import java.util.List; -import org.hibernate.Session; -import org.springframework.transaction.annotation.Transactional; - -@Transactional -public class SchemaSetYangResourceRepositoryImpl implements SchemaSetYangResourceRepository { - - private static final int MAX_INSERT_BATCH_SIZE = 100; - - @PersistenceContext - private EntityManager entityManager; - - @Override - public void insertSchemaSetIdYangResourceId(final Integer schemaSetId, final List<Integer> yangResourceIds) { - final Session session = entityManager.unwrap(Session.class); - session.doWork(connection -> { - try (PreparedStatement preparedStatement = connection.prepareStatement( - "INSERT INTO SCHEMA_SET_YANG_RESOURCES (SCHEMA_SET_ID, YANG_RESOURCE_ID) VALUES ( ?, ?)")) { - int sqlQueryCount = 1; - for (final int yangResourceId : yangResourceIds) { - preparedStatement.setInt(1, schemaSetId); - preparedStatement.setInt(2, yangResourceId); - preparedStatement.addBatch(); - if (sqlQueryCount % MAX_INSERT_BATCH_SIZE == 0 || sqlQueryCount == yangResourceIds.size()) { - preparedStatement.executeBatch(); - } - sqlQueryCount++; - } - } - }); - } -} - diff --git a/cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceNativeRepository.java b/cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceNativeRepository.java deleted file mode 100644 index 2875511c1e..0000000000 --- a/cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceNativeRepository.java +++ /dev/null @@ -1,31 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ri.repository; - -import java.util.Collection; -import java.util.List; -import org.onap.cps.api.model.ModuleReference; - -public interface YangResourceNativeRepository { - - List<Integer> getResourceIdsByModuleReferences(Collection<ModuleReference> moduleReferences); - -} diff --git a/cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceNativeRepositoryImpl.java b/cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceNativeRepositoryImpl.java deleted file mode 100644 index 34f1ee362a..0000000000 --- a/cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceNativeRepositoryImpl.java +++ /dev/null @@ -1,69 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ri.repository; - -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import jakarta.persistence.Query; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.StringJoiner; -import lombok.extern.slf4j.Slf4j; -import org.hibernate.type.StandardBasicTypes; -import org.onap.cps.api.model.ModuleReference; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -@Slf4j -@Repository -public class YangResourceNativeRepositoryImpl implements YangResourceNativeRepository { - - @PersistenceContext - private EntityManager entityManager; - - @Override - @Transactional - public List<Integer> getResourceIdsByModuleReferences(final Collection<ModuleReference> moduleReferences) { - if (moduleReferences.isEmpty()) { - return Collections.emptyList(); - } - final Query query = entityManager.createNativeQuery(getCombinedSelectSqlQuery(moduleReferences)) - .unwrap(org.hibernate.query.NativeQuery.class) - .addScalar("id", StandardBasicTypes.INTEGER); - final List<Integer> yangResourceIds = query.getResultList(); - if (yangResourceIds.size() != moduleReferences.size()) { - log.warn("ModuleReferences size : {} and QueryResult size : {}", moduleReferences.size(), - yangResourceIds.size()); - } - return yangResourceIds; - } - - private String getCombinedSelectSqlQuery(final Collection<ModuleReference> moduleReferences) { - final StringJoiner sqlQueryJoiner = new StringJoiner(" UNION ALL "); - moduleReferences.forEach(moduleReference -> - sqlQueryJoiner.add(String.format("SELECT id FROM yang_resource WHERE module_name='%s' and revision='%s'", - moduleReference.getModuleName(), - moduleReference.getRevision())) - ); - return sqlQueryJoiner.toString(); - } -} diff --git a/cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceRepository.java b/cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceRepository.java index 628502f846..e36e376bc6 100644 --- a/cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceRepository.java +++ b/cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceRepository.java @@ -32,8 +32,10 @@ import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @Repository -public interface YangResourceRepository extends JpaRepository<YangResourceEntity, Integer>, - YangResourceNativeRepository, SchemaSetYangResourceRepository { +public interface YangResourceRepository extends JpaRepository<YangResourceEntity, Integer> { + + YangResourceEntity findByModuleNameAndRevision(@Param("moduleName") String moduleName, + @Param("revision") String revision); List<YangResourceEntity> findAllByChecksumIn(Collection<String> checksums); @@ -88,10 +90,6 @@ public interface YangResourceRepository extends JpaRepository<YangResourceEntity @Param("moduleName") String moduleName, @Param("revision") String revision); @Modifying - @Query(value = "DELETE FROM schema_set_yang_resources WHERE schema_set_id = :schemaSetId", nativeQuery = true) - void deleteSchemaSetYangResourceForSchemaSetId(@Param("schemaSetId") int schemaSetId); - - @Modifying @Query(value = """ DELETE FROM yang_resource WHERE NOT EXISTS (SELECT 1 FROM schema_set_yang_resources WHERE schema_set_yang_resources.yang_resource_id = yang_resource.id) diff --git a/cps-ri/src/test/groovy/org/onap/cps/ri/CpsModulePersistenceServiceImplSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/ri/CpsModulePersistenceServiceImplSpec.groovy index 2915bc8e8c..9abfdbeb33 100644 --- a/cps-ri/src/test/groovy/org/onap/cps/ri/CpsModulePersistenceServiceImplSpec.groovy +++ b/cps-ri/src/test/groovy/org/onap/cps/ri/CpsModulePersistenceServiceImplSpec.groovy @@ -78,8 +78,8 @@ class CpsModulePersistenceServiceImplSpec extends Specification { and: 'persisting yang resource raises db constraint exception (in case of concurrent requests for example)' mockYangResourceRepository.saveAll(_) >> { throw dbException } when: 'attempt to store schema set ' - def newYangResourcesNameToContentMap = [(yangResourceName):yangResourceContent] - objectUnderTest.storeSchemaSet('my-dataspace', 'my-schema-set', newYangResourcesNameToContentMap) + def newYangResourceContentPerName = [(yangResourceName):yangResourceContent] + objectUnderTest.createSchemaSet('my-dataspace', 'my-schema-set', newYangResourceContentPerName) then: 'an #expectedThrownException is thrown' def e = thrown(expectedThrownException) assert e.getMessage().contains(expectedThrownExceptionMessage) @@ -96,7 +96,7 @@ class CpsModulePersistenceServiceImplSpec extends Specification { def schemaSetEntity = new SchemaSetEntity(id: 1) mockSchemaSetRepository.getByDataspaceAndName(_, _) >> schemaSetEntity when: 'schema set update is requested' - objectUnderTest.updateSchemaSetFromModules('my-dataspace', 'my-schemaset', [:], [new ModuleReference('some module name', 'some revision name')]) + objectUnderTest.updateSchemaSetFromNewAndExistingModules('my-dataspace', 'my-schemaset', [:], [new ModuleReference('some module name', 'some revision name')]) then: 'no exception is thrown ' noExceptionThrown() } 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 345bc8825b..41713746b7 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 @@ -314,13 +314,13 @@ public interface CpsDataService { * @param dataspaceName source dataspace name * @param sourceAnchorName source anchor name * @param xpath xpath - * @param yangResourcesNameToContentMap YANG resources (files) map where key is a name and value is content + * @param yangResourceContentPerName YANG resources (files) map where key is a name and value is content * @param targetData target data to be compared in JSON string format * @param fetchDescendantsOption defines the scope of data to fetch: defaulted to INCLUDE_ALL_DESCENDANTS * @return list containing {@link DeltaReport} objects */ List<DeltaReport> getDeltaByDataspaceAnchorAndPayload(String dataspaceName, String sourceAnchorName, String xpath, - Map<String, String> yangResourcesNameToContentMap, + Map<String, String> yangResourceContentPerName, String targetData, FetchDescendantsOption fetchDescendantsOption); 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 c6b8c60ab9..2494be4021 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 @@ -40,21 +40,21 @@ public interface CpsModuleService { * * @param dataspaceName dataspace name * @param schemaSetName schema set name - * @param yangResourcesNameToContentMap yang resources (files) as a mep where key is resource name + * @param yangResourceContentPerName yang resources (files) as a mep where key is resource name * and value is content */ void createSchemaSet(String dataspaceName, String schemaSetName, - Map<String, String> yangResourcesNameToContentMap); + Map<String, String> yangResourceContentPerName); /** * Create or upgrade a schema set from new modules and existing modules or only existing modules. - * @param dataspaceName Dataspace name - * @param schemaSetName schema set name - * @param newModuleNameToContentMap YANG resources map where key is a module name and value is content - * @param allModuleReferences All YANG resource module references + * @param dataspaceName Dataspace name + * @param schemaSetName schema set name + * @param yangResourceContentPerName YANG resources map where key is a name and value is content + * @param allModuleReferences All YANG resource module references */ void createSchemaSetFromModules(String dataspaceName, String schemaSetName, - Map<String, String> newModuleNameToContentMap, + Map<String, String> yangResourceContentPerName, Collection<ModuleReference> allModuleReferences); /** diff --git a/cps-service/src/main/java/org/onap/cps/impl/CpsDataServiceImpl.java b/cps-service/src/main/java/org/onap/cps/impl/CpsDataServiceImpl.java index 71e6f79bb7..9f70ac9132 100644 --- a/cps-service/src/main/java/org/onap/cps/impl/CpsDataServiceImpl.java +++ b/cps-service/src/main/java/org/onap/cps/impl/CpsDataServiceImpl.java @@ -230,7 +230,7 @@ public class CpsDataServiceImpl implements CpsDataService { @Override public List<DeltaReport> getDeltaByDataspaceAnchorAndPayload(final String dataspaceName, final String sourceAnchorName, final String xpath, - final Map<String, String> yangResourcesNameToContentMap, + final Map<String, String> yangResourceContentPerName, final String targetData, final FetchDescendantsOption fetchDescendantsOption) { @@ -243,7 +243,7 @@ public class CpsDataServiceImpl implements CpsDataService { new ArrayList<>(rebuildSourceDataNodes(xpath, sourceAnchor, sourceDataNodes)); final Collection<DataNode> targetDataNodes = - new ArrayList<>(buildTargetDataNodes(sourceAnchor, xpath, yangResourcesNameToContentMap, targetData)); + new ArrayList<>(buildTargetDataNodes(sourceAnchor, xpath, yangResourceContentPerName, targetData)); return cpsDeltaService.getDeltaReports(sourceDataNodesRebuilt, targetDataNodes); } @@ -380,12 +380,12 @@ public class CpsDataServiceImpl implements CpsDataService { } private Collection<DataNode> buildTargetDataNodes(final Anchor sourceAnchor, final String xpath, - final Map<String, String> yangResourcesNameToContentMap, + final Map<String, String> yangResourceContentPerName, final String targetData) { - if (yangResourcesNameToContentMap.isEmpty()) { + if (yangResourceContentPerName.isEmpty()) { return buildDataNodesWithAnchorAndXpath(sourceAnchor, xpath, targetData, ContentType.JSON); } else { - return buildDataNodesWithYangResourceAndXpath(yangResourcesNameToContentMap, xpath, + return buildDataNodesWithYangResourceAndXpath(yangResourceContentPerName, xpath, targetData, ContentType.JSON); } } @@ -454,12 +454,12 @@ public class CpsDataServiceImpl implements CpsDataService { } private Collection<DataNode> buildDataNodesWithParentNodeXpath( - final Map<String, String> yangResourcesNameToContentMap, final String xpath, + final Map<String, String> yangResourceContentPerName, final String xpath, final String nodeData, final ContentType contentType) { if (isRootNodeXpath(xpath)) { final ContainerNode containerNode = yangParser.parseData(contentType, nodeData, - yangResourcesNameToContentMap, PARENT_NODE_XPATH_FOR_ROOT_NODE_XPATH); + yangResourceContentPerName, PARENT_NODE_XPATH_FOR_ROOT_NODE_XPATH); final Collection<DataNode> dataNodes = new DataNodeBuilder() .withContainerNode(containerNode) .buildCollection(); @@ -470,7 +470,7 @@ public class CpsDataServiceImpl implements CpsDataService { } final String normalizedParentNodeXpath = CpsPathUtil.getNormalizedXpath(xpath); final ContainerNode containerNode = - yangParser.parseData(contentType, nodeData, yangResourcesNameToContentMap, normalizedParentNodeXpath); + yangParser.parseData(contentType, nodeData, yangResourceContentPerName, normalizedParentNodeXpath); final Collection<DataNode> dataNodes = new DataNodeBuilder() .withParentNodeXpath(normalizedParentNodeXpath) .withContainerNode(containerNode) @@ -496,18 +496,18 @@ public class CpsDataServiceImpl implements CpsDataService { } private Collection<DataNode> buildDataNodesWithYangResourceAndXpath( - final Map<String, String> yangResourcesNameToContentMap, final String xpath, + final Map<String, String> yangResourceContentPerName, final String xpath, final String nodeData, final ContentType contentType) { if (!isRootNodeXpath(xpath)) { final String parentNodeXpath = CpsPathUtil.getNormalizedParentXpath(xpath); if (parentNodeXpath.isEmpty()) { - return buildDataNodesWithParentNodeXpath(yangResourcesNameToContentMap, ROOT_NODE_XPATH, + return buildDataNodesWithParentNodeXpath(yangResourceContentPerName, ROOT_NODE_XPATH, nodeData, contentType); } - return buildDataNodesWithParentNodeXpath(yangResourcesNameToContentMap, parentNodeXpath, + return buildDataNodesWithParentNodeXpath(yangResourceContentPerName, parentNodeXpath, nodeData, contentType); } - return buildDataNodesWithParentNodeXpath(yangResourcesNameToContentMap, xpath, nodeData, contentType); + return buildDataNodesWithParentNodeXpath(yangResourceContentPerName, xpath, nodeData, contentType); } private static boolean isRootNodeXpath(final String xpath) { diff --git a/cps-service/src/main/java/org/onap/cps/impl/CpsModuleServiceImpl.java b/cps-service/src/main/java/org/onap/cps/impl/CpsModuleServiceImpl.java index b16abcc31f..e50325c739 100644 --- a/cps-service/src/main/java/org/onap/cps/impl/CpsModuleServiceImpl.java +++ b/cps-service/src/main/java/org/onap/cps/impl/CpsModuleServiceImpl.java @@ -57,21 +57,21 @@ public class CpsModuleServiceImpl implements CpsModuleService { @Timed(value = "cps.module.service.schemaset.create", description = "Time taken to create (and store) a schemaset") public void createSchemaSet(final String dataspaceName, final String schemaSetName, - final Map<String, String> yangResourcesNameToContentMap) { + final Map<String, String> yangResourceContentPerName) { cpsValidator.validateNameCharacters(dataspaceName); - cpsModulePersistenceService.storeSchemaSet(dataspaceName, schemaSetName, yangResourcesNameToContentMap); + cpsModulePersistenceService.createSchemaSet(dataspaceName, schemaSetName, yangResourceContentPerName); final YangTextSchemaSourceSet yangTextSchemaSourceSet = - timedYangTextSchemaSourceSetBuilder.getYangTextSchemaSourceSet(yangResourcesNameToContentMap); + timedYangTextSchemaSourceSetBuilder.getYangTextSchemaSourceSet(yangResourceContentPerName); yangTextSchemaSourceSetCache.updateCache(dataspaceName, schemaSetName, yangTextSchemaSourceSet); } @Override public void createSchemaSetFromModules(final String dataspaceName, final String schemaSetName, - final Map<String, String> newModuleNameToContentMap, + final Map<String, String> yangResourceContentPerName, final Collection<ModuleReference> allModuleReferences) { cpsValidator.validateNameCharacters(dataspaceName); - cpsModulePersistenceService.storeSchemaSetFromModules(dataspaceName, schemaSetName, - newModuleNameToContentMap, allModuleReferences); + cpsModulePersistenceService.createSchemaSetFromNewAndExistingModules(dataspaceName, schemaSetName, + yangResourceContentPerName, allModuleReferences); } @Override @@ -83,7 +83,7 @@ public class CpsModuleServiceImpl implements CpsModuleService { @Override public SchemaSet getSchemaSet(final String dataspaceName, final String schemaSetName) { cpsValidator.validateNameCharacters(dataspaceName); - final var yangTextSchemaSourceSet = yangTextSchemaSourceSetCache + final YangTextSchemaSourceSet yangTextSchemaSourceSet = yangTextSchemaSourceSetCache .get(dataspaceName, schemaSetName); return SchemaSet.builder().name(schemaSetName).dataspaceName(dataspaceName) .moduleReferences(yangTextSchemaSourceSet.getModuleReferences()).build(); @@ -130,15 +130,14 @@ public class CpsModuleServiceImpl implements CpsModuleService { @Override public void upgradeSchemaSetFromModules(final String dataspaceName, final String schemaSetName, - final Map<String, String> newModuleNameToContentMap, + final Map<String, String> newYangResourceContentPerModule, final Collection<ModuleReference> allModuleReferences) { cpsValidator.validateNameCharacters(dataspaceName); - cpsModulePersistenceService.updateSchemaSetFromModules(dataspaceName, schemaSetName, - newModuleNameToContentMap, allModuleReferences); + cpsModulePersistenceService.updateSchemaSetFromNewAndExistingModules(dataspaceName, schemaSetName, + newYangResourceContentPerModule, allModuleReferences); yangTextSchemaSourceSetCache.removeFromCache(dataspaceName, schemaSetName); } - @Override public Collection<ModuleReference> getYangResourceModuleReferences(final String dataspaceName) { cpsValidator.validateNameCharacters(dataspaceName); diff --git a/cps-service/src/main/java/org/onap/cps/init/AbstractModelLoader.java b/cps-service/src/main/java/org/onap/cps/init/AbstractModelLoader.java index e864633f25..a80239039a 100644 --- a/cps-service/src/main/java/org/onap/cps/init/AbstractModelLoader.java +++ b/cps-service/src/main/java/org/onap/cps/init/AbstractModelLoader.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation + * Copyright (C) 2023-2025 Nordix Foundation * Modifications Copyright (C) 2024 TechMahindra Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -77,7 +77,7 @@ public abstract class AbstractModelLoader implements ModelLoader { } catch (final AlreadyDefinedException alreadyDefinedException) { log.warn("Creating new schema set failed as schema set already exists"); } catch (final Exception exception) { - log.error("Creating schema set failed: {} ", exception.getMessage()); + log.error("Creating schema set {} failed: {} ", schemaSetName, exception.getMessage()); throw new ModelOnboardingException("Creating schema set failed", exception.getMessage()); } } 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 86ad50252d..02e1b6c754 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 @@ -36,34 +36,37 @@ public interface CpsModulePersistenceService { /** * Stores Schema Set. * - * @param dataspaceName dataspace name - * @param schemaSetName schema set name - * @param yangResourcesNameToContentMap YANG resources (files) map where key is a name and value is content + * @param dataspaceName dataspace name + * @param schemaSetName schema set name + * @param yangResourceContentPerName a map of YANG resources map where key is a name and value is content */ - void storeSchemaSet(String dataspaceName, String schemaSetName, Map<String, String> yangResourcesNameToContentMap); + void createSchemaSet(String dataspaceName, String schemaSetName, Map<String, String> yangResourceContentPerName); /** * Stores a new schema set from new modules and existing modules. * - * @param dataspaceName Dataspace name - * @param schemaSetName Schema set name - * @param newModuleNameToContentMap YANG resources map where key is a module name and value is content - * @param allModuleReferences All YANG resources module references + * @param dataspaceName dataspace name + * @param schemaSetName Schema set name + * @param newYangResourceContentPerName a map of only the new YANG resources + * the key is a name and value is its content + * @param allModuleReferences all YANG resources module references */ - void storeSchemaSetFromModules(String dataspaceName, String schemaSetName, - Map<String, String> newModuleNameToContentMap, Collection<ModuleReference> allModuleReferences); + void createSchemaSetFromNewAndExistingModules(String dataspaceName, String schemaSetName, + Map<String, String> newYangResourceContentPerName, + Collection<ModuleReference> allModuleReferences); /** * Update an existing schema set from new modules and existing modules. * - * @param dataspaceName Dataspace name + * @param dataspaceName dataspace name * @param schemaSetName Schema set name - * @param newModuleNameToContentMap YANG resources map where key is a module name and value is content - * @param allModuleReferences All YANG resources module references + * @param newYangResourcesPerName a map of only the new YANG resources + * the key is a module name and value is its content + * @param allModuleReferences all YANG resources module references */ - void updateSchemaSetFromModules(final String dataspaceName, final String schemaSetName, - final Map<String, String> newModuleNameToContentMap, - final Collection<ModuleReference> allModuleReferences); + void updateSchemaSetFromNewAndExistingModules(String dataspaceName, String schemaSetName, + Map<String, String> newYangResourcesPerName, + Collection<ModuleReference> allModuleReferences); /** * Checks whether a schema set exists in the specified dataspace. diff --git a/cps-service/src/main/java/org/onap/cps/utils/YangParser.java b/cps-service/src/main/java/org/onap/cps/utils/YangParser.java index 08f450e2f1..5dfeb2fb3f 100644 --- a/cps-service/src/main/java/org/onap/cps/utils/YangParser.java +++ b/cps-service/src/main/java/org/onap/cps/utils/YangParser.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation. + * Copyright (C) 2024-2025 Nordix Foundation. * Modifications Copyright (C) 2024 TechMahindra Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -71,17 +71,17 @@ public class YangParser { /** * Parses data into (normalized) ContainerNode according to schema context for the given yang resource. * - * @param nodeData data string - * @param yangResourcesNameToContentMap yang resource to content map - * @return the NormalizedNode object + * @param nodeData data string + * @param yangResourceContentPerName yang resource content per name + * @return the NormalizedNode object */ @Timed(value = "cps.utils.yangparser.nodedata.with.parent.with.yangResourceMap.parse", description = "Time taken to parse node data with a parent") public ContainerNode parseData(final ContentType contentType, final String nodeData, - final Map<String, String> yangResourcesNameToContentMap, + final Map<String, String> yangResourceContentPerName, final String parentNodeXpath) { - final SchemaContext schemaContext = getSchemaContext(yangResourcesNameToContentMap); + final SchemaContext schemaContext = getSchemaContext(yangResourceContentPerName); return yangParserHelper.parseData(contentType, nodeData, schemaContext, parentNodeXpath, VALIDATE_AND_PARSE); } @@ -114,8 +114,8 @@ public class YangParser { anchor.getSchemaSetName()).getSchemaContext(); } - private SchemaContext getSchemaContext(final Map<String, String> yangResourcesNameToContentMap) { - return timedYangTextSchemaSourceSetBuilder.getYangTextSchemaSourceSet(yangResourcesNameToContentMap) + private SchemaContext getSchemaContext(final Map<String, String> yangResourceContentPerName) { + return timedYangTextSchemaSourceSetBuilder.getYangTextSchemaSourceSet(yangResourceContentPerName) .getSchemaContext(); } diff --git a/cps-service/src/main/java/org/onap/cps/yang/TimedYangTextSchemaSourceSetBuilder.java b/cps-service/src/main/java/org/onap/cps/yang/TimedYangTextSchemaSourceSetBuilder.java index 013faff0c8..9b2ac944dc 100644 --- a/cps-service/src/main/java/org/onap/cps/yang/TimedYangTextSchemaSourceSetBuilder.java +++ b/cps-service/src/main/java/org/onap/cps/yang/TimedYangTextSchemaSourceSetBuilder.java @@ -30,8 +30,8 @@ public class TimedYangTextSchemaSourceSetBuilder { @Timed(value = "cps.yangtextschemasourceset.build", description = "Time taken to build a yang text schema source set") public YangTextSchemaSourceSet getYangTextSchemaSourceSet( - final Map<String, String> yangResourcesNameToContentMap) { - return YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap); + final Map<String, String> yangResourceContentPerName) { + return YangTextSchemaSourceSetBuilder.of(yangResourceContentPerName); } } diff --git a/cps-service/src/test/groovy/org/onap/cps/impl/CpsDataServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/impl/CpsDataServiceImplSpec.groovy index 34d2b7564a..abcda6c696 100644 --- a/cps-service/src/test/groovy/org/onap/cps/impl/CpsDataServiceImplSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/impl/CpsDataServiceImplSpec.groovy @@ -248,10 +248,10 @@ class CpsDataServiceImplSpec extends Specification { def 'Get delta between anchor and payload with user provided schema #scenario'() { given: 'user provided schema set ' - def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang') - setupSchemaSetMocksForDelta(yangResourcesNameToContentMap) + def yangResourceContentPerName = TestUtils.getYangResourcesAsMap('bookstore.yang') + setupSchemaSetMocksForDelta(yangResourceContentPerName) when: 'attempt to get delta between an anchor and a JSON payload' - objectUnderTest.getDeltaByDataspaceAnchorAndPayload(dataspaceName, anchorName, xpath, yangResourcesNameToContentMap, jsonData, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) + objectUnderTest.getDeltaByDataspaceAnchorAndPayload(dataspaceName, anchorName, xpath, yangResourceContentPerName, jsonData, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) then: 'dataspacename and anchor names are validated' 1 * mockCpsValidator.validateNameCharacters(['some-dataspace', 'some-anchor']) and: 'source data nodes are fetched using appropriate persistence layer method' @@ -285,10 +285,10 @@ class CpsDataServiceImplSpec extends Specification { def 'Delta between anchor and payload error scenario #scenario'() { given: 'schema set for given anchor and dataspace references bookstore model' - def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang') - setupSchemaSetMocksForDelta(yangResourcesNameToContentMap) + def yangResourceContentPerName = TestUtils.getYangResourcesAsMap('bookstore.yang') + setupSchemaSetMocksForDelta(yangResourceContentPerName) when: 'attempt to get delta between anchor and payload' - objectUnderTest.getDeltaByDataspaceAnchorAndPayload(dataspaceName, anchorName, xpath, yangResourcesNameToContentMap, jsonData, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) + objectUnderTest.getDeltaByDataspaceAnchorAndPayload(dataspaceName, anchorName, xpath, yangResourceContentPerName, jsonData, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) then: 'expected exception is thrown' thrown(DataValidationException) where: 'following parameters were used' @@ -654,11 +654,11 @@ class CpsDataServiceImplSpec extends Specification { mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext } - def setupSchemaSetMocksForDelta(Map<String, String> yangResourcesNameToContentMap) { + def setupSchemaSetMocksForDelta(Map<String, String> yangResourceContentPerName) { def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet) - mockTimedYangTextSchemaSourceSetBuilder.getYangTextSchemaSourceSet(yangResourcesNameToContentMap) >> mockYangTextSchemaSourceSet + mockTimedYangTextSchemaSourceSetBuilder.getYangTextSchemaSourceSet(yangResourceContentPerName) >> mockYangTextSchemaSourceSet mockYangTextSchemaSourceSetCache.get(_, _) >> mockYangTextSchemaSourceSet - def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap).getSchemaContext() + def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceContentPerName).getSchemaContext() mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext } diff --git a/cps-service/src/test/groovy/org/onap/cps/impl/CpsModuleServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/impl/CpsModuleServiceImplSpec.groovy index 041ce605c4..48db53c882 100644 --- a/cps-service/src/test/groovy/org/onap/cps/impl/CpsModuleServiceImplSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/impl/CpsModuleServiceImplSpec.groovy @@ -56,7 +56,7 @@ class CpsModuleServiceImplSpec extends Specification { when: 'Create schema set method is invoked' objectUnderTest.createSchemaSet('someDataspace', 'schemaSetName@with Special!Characters', [:]) then: 'Parameters are validated and processing is delegated to persistence service' - 1 * mockCpsModulePersistenceService.storeSchemaSet('someDataspace', 'schemaSetName@with Special!Characters', [:]) + 1 * mockCpsModulePersistenceService.createSchemaSet('someDataspace', 'schemaSetName@with Special!Characters', [:]) and: 'the CpsValidator is called on the dataspaceName' 1 * mockCpsValidator.validateNameCharacters('someDataspace') } @@ -68,16 +68,16 @@ class CpsModuleServiceImplSpec extends Specification { when: 'create schema set from modules method is invoked' objectUnderTest.createSchemaSetFromModules('someDataspaceName', 'someSchemaSetName', [newModule: 'newContent'], listOfExistingModulesModuleReference) then: 'processing is delegated to persistence service' - 1 * mockCpsModulePersistenceService.storeSchemaSetFromModules('someDataspaceName', 'someSchemaSetName', [newModule: 'newContent'], listOfExistingModulesModuleReference) + 1 * mockCpsModulePersistenceService.createSchemaSetFromNewAndExistingModules('someDataspaceName', 'someSchemaSetName', [newModule: 'newContent'], listOfExistingModulesModuleReference) and: 'the CpsValidator is called on the dataspaceName' 1 * mockCpsValidator.validateNameCharacters('someDataspaceName') } def 'Create schema set from invalid resources'() { given: 'Invalid yang resource as name-to-content map' - def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('invalid.yang') + def yangResourceContentPerName = TestUtils.getYangResourcesAsMap('invalid.yang') when: 'Create schema set method is invoked' - objectUnderTest.createSchemaSet('someDataspace', 'someSchemaSet', yangResourcesNameToContentMap) + objectUnderTest.createSchemaSet('someDataspace', 'someSchemaSet', yangResourceContentPerName) then: 'Model validation exception is thrown' thrown(ModelValidationException) } @@ -85,7 +85,7 @@ class CpsModuleServiceImplSpec extends Specification { def 'Create schema set with duplicate yang resource exception in persistence layer.'() { given: 'the persistence layer throws an duplicated yang resource exception' def originalException = new DuplicatedYangResourceException('name', '123', null) - mockCpsModulePersistenceService.storeSchemaSet(*_) >> { throw originalException } + mockCpsModulePersistenceService.createSchemaSet(*_) >> { throw originalException } when: 'attempt to create schema set' objectUnderTest.createSchemaSet('someDataspace', 'someSchemaSet', [:]) then: 'the same duplicated yang resource exception is thrown (up)' @@ -98,9 +98,9 @@ class CpsModuleServiceImplSpec extends Specification { def 'Get schema set by name and dataspace.'() { given: 'an already present schema set' - def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang') + def yangResourceContentPerName = TestUtils.getYangResourcesAsMap('bookstore.yang') and: 'yang resource cache returns the expected schema set' - mockYangTextSchemaSourceSetCache.get('someDataspace', 'schemaSetName@with Special!Characters') >> YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap) + mockYangTextSchemaSourceSetCache.get('someDataspace', 'schemaSetName@with Special!Characters') >> YangTextSchemaSourceSetBuilder.of(yangResourceContentPerName) when: 'get schema set method is invoked' def result = objectUnderTest.getSchemaSet('someDataspace', 'schemaSetName@with Special!Characters') then: 'the correct schema set is returned' diff --git a/cps-service/src/test/groovy/org/onap/cps/impl/E2ENetworkSliceSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/impl/E2ENetworkSliceSpec.groovy index 8171209947..db5b4f104e 100755 --- a/cps-service/src/test/groovy/org/onap/cps/impl/E2ENetworkSliceSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/impl/E2ENetworkSliceSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation. + * Copyright (C) 2021-2025 Nordix Foundation. * Modifications Copyright (C) 2021-2022 Bell Canada. * Modifications Copyright (C) 2021 Pantheon.tech * Modifications Copyright (C) 2022-2024 TechMahindra Ltd. @@ -66,32 +66,32 @@ class E2ENetworkSliceSpec extends Specification { def 'E2E model can be parsed by CPS.'() { given: 'Valid yang resource as name-to-content map' - def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap( + def yangResourceContentPerName = TestUtils.getYangResourcesAsMap( 'ietf/ietf-inet-types@2013-07-15.yang', 'ietf/ietf-yang-types@2013-07-15.yang', 'e2e/basic/ran-network2020-08-06.yang' ) when: 'Create schema set method is invoked' - cpsModuleServiceImpl.createSchemaSet(dataspaceName, schemaSetName, yangResourcesNameToContentMap) + cpsModuleServiceImpl.createSchemaSet(dataspaceName, schemaSetName, yangResourceContentPerName) then: 'Parameters are validated and processing is delegated to persistence service' - 1 * mockModuleStoreService.storeSchemaSet(dataspaceName, schemaSetName, yangResourcesNameToContentMap) + 1 * mockModuleStoreService.createSchemaSet(dataspaceName, schemaSetName, yangResourceContentPerName) } def 'E2E Coverage Area-Tracking Area & TA-Cell mapping model can be parsed by CPS.'() { given: 'Valid yang resource as name-to-content map' - def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap( + def yangResourceContentPerName = TestUtils.getYangResourcesAsMap( 'e2e/basic/cps-cavsta-onap-internal2021-01-28.yang') when: 'Create schema set method is invoked' - cpsModuleServiceImpl.createSchemaSet(dataspaceName, schemaSetName, yangResourcesNameToContentMap) + cpsModuleServiceImpl.createSchemaSet(dataspaceName, schemaSetName, yangResourceContentPerName) then: 'Parameters are validated and processing is delegated to persistence service' - 1 * mockModuleStoreService.storeSchemaSet(dataspaceName, schemaSetName, yangResourcesNameToContentMap) + 1 * mockModuleStoreService.createSchemaSet(dataspaceName, schemaSetName, yangResourceContentPerName) } def 'E2E Coverage Area-Tracking Area & TA-Cell mapping data can be parsed by CPS.'() { given: 'Valid yang resource as name-to-content map' - def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap( + def yangResourceContentPerName = TestUtils.getYangResourcesAsMap( 'e2e/basic/cps-cavsta-onap-internal2021-01-28.yang') - def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap).getSchemaContext() + def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceContentPerName).getSchemaContext() def dataNodeStored and : 'a valid json is provided for the model' def jsonData = TestUtils.getResourceFileContent('e2e/basic/cps-Cavsta-Data.txt') @@ -99,7 +99,7 @@ class E2ENetworkSliceSpec extends Specification { mockCpsAnchorService.getAnchor(dataspaceName, anchorName) >> new Anchor().builder().name(anchorName).schemaSetName(schemaSetName).dataspaceName(dataspaceName).build() mockYangTextSchemaSourceSetCache.get(dataspaceName, schemaSetName) >> - YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap) + YangTextSchemaSourceSetBuilder.of(yangResourceContentPerName) mockModuleStoreService.getYangSchemaResources(dataspaceName, schemaSetName) >> schemaContext when: 'saveData method is invoked' cpsDataServiceImpl.saveData(dataspaceName, anchorName, jsonData, noTimestamp) @@ -123,15 +123,15 @@ class E2ENetworkSliceSpec extends Specification { def 'E2E Coverage Area-Tracking Area & TA-Cell mapping data can be parsed for RAN inventory.'() { def dataNodeStored given: 'valid yang resource as name-to-content map' - def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap( + def yangResourceContentPerName = TestUtils.getYangResourcesAsMap( 'e2e/basic/cps-ran-inventory@2021-01-28.yang') - def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap).getSchemaContext() + def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceContentPerName).getSchemaContext() and : 'a valid json is provided for the model' def jsonData = TestUtils.getResourceFileContent('e2e/basic/cps-ran-inventory-data.json') and : 'all the further dependencies are mocked ' mockCpsAnchorService.getAnchor('someDataspace', 'someAnchor') >> new Anchor().builder().name('someAnchor').schemaSetName('someSchemaSet').dataspaceName(dataspaceName).build() - mockYangTextSchemaSourceSetCache.get('someDataspace', 'someSchemaSet') >> YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap) + mockYangTextSchemaSourceSetCache.get('someDataspace', 'someSchemaSet') >> YangTextSchemaSourceSetBuilder.of(yangResourceContentPerName) mockModuleStoreService.getYangSchemaResources('someDataspace', 'someSchemaSet') >> schemaContext when: 'saveData method is invoked' cpsDataServiceImpl.saveData('someDataspace', 'someAnchor', jsonData, noTimestamp) @@ -161,7 +161,7 @@ class E2ENetworkSliceSpec extends Specification { def 'E2E RAN Schema Model.'(){ given: 'yang resources' - def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap( + def yangResourceContentPerName = TestUtils.getYangResourcesAsMap( 'ietf/ietf-inet-types@2013-07-15.yang', 'ietf/ietf-yang-types@2013-07-15.yang', 'e2e/basic/cps-ran-schema-model@2021-05-19.yang' @@ -169,7 +169,7 @@ class E2ENetworkSliceSpec extends Specification { and : 'json data' def jsonData = TestUtils.getResourceFileContent('e2e/basic/cps-ran-schema-model-data-v4.json') expect: 'schema context is built with no exception indicating the schema set being valid ' - def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap).getSchemaContext() + def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceContentPerName).getSchemaContext() and: 'data is parsed with no exception indicating the model match' new YangParserHelper().parseData(ContentType.JSON, jsonData, schemaContext, '', false) != null } diff --git a/cps-service/src/test/groovy/org/onap/cps/impl/YangTextSchemaSourceSetCacheSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/impl/YangTextSchemaSourceSetCacheSpec.groovy index 6694e7712f..e71782ce4f 100644 --- a/cps-service/src/test/groovy/org/onap/cps/impl/YangTextSchemaSourceSetCacheSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/impl/YangTextSchemaSourceSetCacheSpec.groovy @@ -65,13 +65,13 @@ class YangTextSchemaSourceSetCacheSpec extends Specification { given: 'cache is empty' yangResourceCacheImpl.clear() and: 'a schema set exists' - def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang') - def expectedYangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap) + def yangResourceContentPerName = TestUtils.getYangResourcesAsMap('bookstore.yang') + def expectedYangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourceContentPerName) when: 'schema-set information is asked' def result = objectUnderTest.get('my-dataspace', 'my-schemaset') then: 'information fetched from cps module persistence' 1 * mockModuleStoreService.getYangSchemaResources('my-dataspace', 'my-schemaset') - >> yangResourcesNameToContentMap + >> yangResourceContentPerName and: 'stored in the cache' def cachedValue = getCachedValue('my-dataspace', 'my-schemaset') assert cachedValue.getModuleReferences() == expectedYangTextSchemaSourceSet.getModuleReferences() @@ -83,8 +83,8 @@ class YangTextSchemaSourceSetCacheSpec extends Specification { def 'Cache Hit: Respond from cache'() { given: 'a schema set exists' - def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang') - def expectedYangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap) + def yangResourceContentPerName = TestUtils.getYangResourcesAsMap('bookstore.yang') + def expectedYangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourceContentPerName) and: 'stored in cache' yangResourceCacheImpl.put(getCacheKey('my-dataspace', 'my-schemaset'), expectedYangTextSchemaSourceSet) when: 'schema-set information is asked' @@ -97,8 +97,8 @@ class YangTextSchemaSourceSetCacheSpec extends Specification { def 'Cache Update: when no data exist in the cache'() { given: 'a schema set exists' - def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang') - def yangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap) + def yangResourceContentPerName = TestUtils.getYangResourcesAsMap('bookstore.yang') + def yangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourceContentPerName) when: 'cache is updated' objectUnderTest.updateCache('my-dataspace', 'my-schemaset', yangTextSchemaSourceSet) then: 'cached value is same as expected' @@ -110,8 +110,8 @@ class YangTextSchemaSourceSetCacheSpec extends Specification { def 'Cache Evict:with invalid #scenario'() { given: 'a schema set exists in cache' - def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang') - def yangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap) + def yangResourceContentPerName = TestUtils.getYangResourcesAsMap('bookstore.yang') + def yangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourceContentPerName) yangResourceCacheImpl.put(getCacheKey('my-dataspace', 'my-schemaset'), yangTextSchemaSourceSet) def cachedValue = getCachedValue('my-dataspace', 'my-schemaset') assert cachedValue.getModuleReferences() == yangTextSchemaSourceSet.getModuleReferences() diff --git a/cps-service/src/test/groovy/org/onap/cps/utils/YangParserSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/utils/YangParserSpec.groovy index a2fadb7e9f..cb7a16cb84 100644 --- a/cps-service/src/test/groovy/org/onap/cps/utils/YangParserSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/utils/YangParserSpec.groovy @@ -40,7 +40,7 @@ class YangParserSpec extends Specification { def objectUnderTest = new YangParser(mockYangParserHelper, mockYangTextSchemaSourceSetCache, mockTimedYangTextSchemaSourceSetBuilder) def anchor = new Anchor(dataspaceName: 'my dataspace', schemaSetName: 'my schema') - def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang') + def yangResourceContentPerName = TestUtils.getYangResourcesAsMap('bookstore.yang') def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet) def mockSchemaContext = Mock(SchemaContext) def containerNodeFromYangUtils = Mock(ContainerNode) @@ -91,9 +91,9 @@ class YangParserSpec extends Specification { def 'Parsing data with yang resource to context map.'() { given: 'the schema source set for the yang resource map is returned' - mockTimedYangTextSchemaSourceSetBuilder.getYangTextSchemaSourceSet(yangResourcesNameToContentMap) >> mockYangTextSchemaSourceSet + mockTimedYangTextSchemaSourceSetBuilder.getYangTextSchemaSourceSet(yangResourceContentPerName) >> mockYangTextSchemaSourceSet when: 'parsing some json data' - def result = objectUnderTest.parseData(ContentType.JSON, 'some json', yangResourcesNameToContentMap, noParent) + def result = objectUnderTest.parseData(ContentType.JSON, 'some json', yangResourceContentPerName, noParent) then: 'the yang parser helper always returns a container node' 1 * mockYangParserHelper.parseData(ContentType.JSON, 'some json', mockSchemaContext, noParent, validateAndParse) >> containerNodeFromYangUtils and: 'the result is the same container node as return from yang utils' diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy index 3f7b25d2fa..27d85de034 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy @@ -44,6 +44,7 @@ import org.onap.cps.ncmp.impl.inventory.sync.ModuleSyncService import org.onap.cps.ncmp.impl.inventory.sync.ModuleSyncWatchdog import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher import org.onap.cps.ri.repository.DataspaceRepository +import org.onap.cps.ri.repository.SchemaSetRepository import org.onap.cps.ri.utils.SessionManager import org.onap.cps.utils.JsonObjectMapper import org.springframework.beans.factory.annotation.Autowired @@ -102,6 +103,12 @@ abstract class CpsIntegrationSpecBase extends Specification { SessionManager sessionManager @Autowired + DataspaceRepository dataspaceRepository + + @Autowired + SchemaSetRepository schemaSetRepository + + @Autowired ParameterizedCmHandleQueryService networkCmProxyCmHandleQueryService @Autowired @@ -204,18 +211,18 @@ abstract class CpsIntegrationSpecBase extends Specification { return nodeCount } - def getBookstoreYangResourcesNameToContentMap() { + def getBookstoreyangResourceContentPerName() { def bookstoreModelFileContent = readResourceDataFile('bookstore/bookstore.yang') def bookstoreTypesFileContent = readResourceDataFile('bookstore/bookstore-types.yang') return [bookstore: bookstoreModelFileContent, bookstoreTypes: bookstoreTypesFileContent] } def createStandardBookStoreSchemaSet(targetDataspace) { - cpsModuleService.createSchemaSet(targetDataspace, BOOKSTORE_SCHEMA_SET, getBookstoreYangResourcesNameToContentMap()) + cpsModuleService.createSchemaSet(targetDataspace, BOOKSTORE_SCHEMA_SET, getBookstoreyangResourceContentPerName()) } def createStandardBookStoreSchemaSet(targetDataspace, targetSchemaSet) { - cpsModuleService.createSchemaSet(targetDataspace, targetSchemaSet, getBookstoreYangResourcesNameToContentMap()) + cpsModuleService.createSchemaSet(targetDataspace, targetSchemaSet, getBookstoreyangResourceContentPerName()) } def dataspaceExists(dataspaceName) { diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy index c790521627..11c0ff2743 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy @@ -29,6 +29,7 @@ import org.springframework.http.HttpStatus import org.springframework.http.MediaType import java.util.regex.Matcher +import java.util.stream.Collectors import static org.onap.cps.integration.base.CpsIntegrationSpecBase.readResourceDataFile @@ -81,7 +82,7 @@ class DmiDispatcher extends Dispatcher { // get module resources for a CM-handle case ~'^/dmi/v1/ch/(.*)/moduleResources$': def cmHandleId = Matcher.lastMatcher[0][1] - return getModuleResourcesResponse(cmHandleId) + return getModuleResourcesResponse(request, cmHandleId) // pass-through data operation for a CM-handle case ~'^/dmi/v1/ch/(.*)/data/ds/(.*)$': @@ -124,8 +125,13 @@ class DmiDispatcher extends Dispatcher { return mockResponseWithBody(HttpStatus.OK, moduleReferences) } - def getModuleResourcesResponse(cmHandleId) { - def moduleResources = '[' + getModuleNamesForCmHandle(cmHandleId).collect { + def getModuleResourcesResponse(request, cmHandleId) { + def moduleResourcesRequest = jsonSlurper.parseText(request.getBody().readUtf8()) + def requestedModuleNames = moduleResourcesRequest.get('data').get('modules').collect{it.get('name')} + def candidateModuleNames = getModuleNamesForCmHandle(cmHandleId) + def moduleNames = candidateModuleNames.stream().filter(candidate -> requestedModuleNames.contains(candidate)).toList() + + def moduleResources = '[' + moduleNames.collect { MODULE_RESOURCES_RESPONSE_TEMPLATE.replaceAll("<MODULE_NAME>", it) }.join(',') + ']' return mockResponseWithBody(HttpStatus.OK, moduleResources) diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/ModuleServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/ModuleServiceIntegrationSpec.groovy index c787b4209e..49201e8f22 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/ModuleServiceIntegrationSpec.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/ModuleServiceIntegrationSpec.groovy @@ -53,8 +53,8 @@ class ModuleServiceIntegrationSpec extends FunctionalSpecBase { } """ - def newYangResourcesNameToContentMap = [:] - def moduleReferences = [] + def yangResourceContentPerName = [:] + def allModuleReferences = [] def noNewModules = [:] def bookstoreModelFileContent = readResourceDataFile('bookstore/bookstore.yang') def bookstoreTypesFileContent = readResourceDataFile('bookstore/bookstore-types.yang') @@ -67,9 +67,9 @@ class ModuleServiceIntegrationSpec extends FunctionalSpecBase { def 'Create new schema set from yang resources with #scenario'() { given: 'a new schema set with #numberOfModules modules' - populateNewYangResourcesNameToContentMapAndAllModuleReferences(numberOfNewModules) + populateYangResourceContentPerNameAndAllModuleReferences(numberOfNewModules) when: 'the new schema set is created' - objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet', newYangResourcesNameToContentMap) + objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet', yangResourceContentPerName) then: 'the number of module references has increased by #numberOfNewModules' def yangResourceModuleReferences = objectUnderTest.getYangResourceModuleReferences(FUNCTIONAL_TEST_DATASPACE_1) originalNumberOfModuleReferences + numberOfNewModules == yangResourceModuleReferences.size() @@ -93,39 +93,43 @@ class ModuleServiceIntegrationSpec extends FunctionalSpecBase { def 'Create new schema set from modules with #scenario'() { given: 'a new schema set with #numberOfNewModules modules' - populateNewYangResourcesNameToContentMapAndAllModuleReferences(numberOfNewModules) + populateYangResourceContentPerNameAndAllModuleReferences(numberOfNewModules) and: 'add existing module references (optional)' - moduleReferences.addAll(existingModuleReferences) + allModuleReferences.addAll(existingModuleReferences) when: 'the new schema set is created' def schemaSetName = "NewSchemaWith${numberOfNewModules}Modules" - objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, newYangResourcesNameToContentMap, moduleReferences) + objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, yangResourceContentPerName, allModuleReferences) and: 'associated with a new anchor' cpsAnchorService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, 'newAnchor') then: 'the new anchor has the correct number of modules' def yangResourceModuleReferences = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'newAnchor') assert expectedNumberOfModulesForAnchor == yangResourceModuleReferences.size() + and: 'the schema set has the correct number of modules too' + def dataspaceEntity = dataspaceRepository.getByName(FUNCTIONAL_TEST_DATASPACE_1) + def schemaSetEntity = schemaSetRepository.getByDataspaceAndName(dataspaceEntity, schemaSetName) + assert expectedNumberOfModulesForAnchor == schemaSetEntity.yangResources.size() cleanup: objectUnderTest.deleteSchemaSetsWithCascade(FUNCTIONAL_TEST_DATASPACE_1, [ schemaSetName.toString() ]) where: 'the following module references are provided' scenario | numberOfNewModules | existingModuleReferences || expectedNumberOfModulesForAnchor 'empty schema set' | 0 | [ ] || 0 - 'one existing module' | 0 | [bookStoreModuleReference ] || 1 + 'one existing module' | 0 | [ bookStoreModuleReference ] || 1 'two new modules' | 2 | [ ] || 2 - 'two new modules, one existing' | 2 | [bookStoreModuleReference ] || 3 + 'two new modules, one existing' | 2 | [ bookStoreModuleReference ] || 3 'over max batch size #modules' | 101 | [ ] || 101 'two valid, one invalid module' | 2 | [ new ModuleReference('NOT EXIST','IRRELEVANT') ] || 2 } def 'Duplicate schema content.'() { given: 'a map of yang resources' - populateNewYangResourcesNameToContentMapAndAllModuleReferences(1) + populateYangResourceContentPerNameAndAllModuleReferences(1) when: 'a new schema set is created' - objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchema1', newYangResourcesNameToContentMap) + objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchema1', yangResourceContentPerName) then: 'the dataspace has one new module (reference)' def numberOfModuleReferencesAfterFirstSchemaSetHasBeenAdded = objectUnderTest.getYangResourceModuleReferences(FUNCTIONAL_TEST_DATASPACE_1).size() assert numberOfModuleReferencesAfterFirstSchemaSetHasBeenAdded == originalNumberOfModuleReferences + 1 when: 'a second new schema set is created' - objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchema2', newYangResourcesNameToContentMap) + objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchema2', yangResourceContentPerName) then: 'the dataspace has no additional module (reference)' assert numberOfModuleReferencesAfterFirstSchemaSetHasBeenAdded == objectUnderTest.getYangResourceModuleReferences(FUNCTIONAL_TEST_DATASPACE_1).size() cleanup: @@ -134,8 +138,8 @@ class ModuleServiceIntegrationSpec extends FunctionalSpecBase { def 'Attempt to create schema set, error scenario: #scenario.'() { when: 'attempt to store schema set #schemaSetName in dataspace #dataspaceName' - populateNewYangResourcesNameToContentMapAndAllModuleReferences(0) - objectUnderTest.createSchemaSet(dataspaceName, schemaSetName, newYangResourcesNameToContentMap) + populateYangResourceContentPerNameAndAllModuleReferences(0) + objectUnderTest.createSchemaSet(dataspaceName, schemaSetName, yangResourceContentPerName) then: 'an #expectedException is thrown' thrown(expectedException) where: 'the following data is used' @@ -146,7 +150,7 @@ class ModuleServiceIntegrationSpec extends FunctionalSpecBase { def 'Attempt to create duplicate schema set from modules.'() { when: 'attempt to store duplicate schema set from modules' - objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_SCHEMA_SET, newYangResourcesNameToContentMap, []) + objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_SCHEMA_SET, yangResourceContentPerName, []) then: 'an Already Defined Exception is thrown' thrown(AlreadyDefinedException) } @@ -192,12 +196,12 @@ class ModuleServiceIntegrationSpec extends FunctionalSpecBase { def 'Identifying new module references with #scenario'() { when: 'identifyNewModuleReferences is called' - def result = objectUnderTest.identifyNewModuleReferences(moduleReferences) + def result = objectUnderTest.identifyNewModuleReferences(allModuleReferences) then: 'the correct module references are returned' assert result.size() == expectedResult.size() assert result.containsAll(expectedResult) where: 'the following data is used' - scenario | moduleReferences || expectedResult + scenario | allModuleReferences || expectedResult 'just new module references' | [new ModuleReference('new1', 'r1'), new ModuleReference('new2', 'r1')] || [new ModuleReference('new1', 'r1'), new ModuleReference('new2', 'r1')] 'one new module,one existing reference' | [new ModuleReference('new1', 'r1'), bookStoreModuleReference] || [new ModuleReference('new1', 'r1')] 'no new module references' | [bookStoreModuleReference] || [] @@ -216,8 +220,8 @@ class ModuleServiceIntegrationSpec extends FunctionalSpecBase { def 'Retrieve all schema sets.'() { given: 'an extra schema set is stored' - populateNewYangResourcesNameToContentMapAndAllModuleReferences(1) - objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchema1', newYangResourcesNameToContentMap) + populateYangResourceContentPerNameAndAllModuleReferences(1) + objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchema1', yangResourceContentPerName) when: 'all schema sets are retrieved' def result = objectUnderTest.getSchemaSets(FUNCTIONAL_TEST_DATASPACE_1) then: 'the result contains all expected schema sets' @@ -233,8 +237,8 @@ class ModuleServiceIntegrationSpec extends FunctionalSpecBase { def 'Delete schema sets with(out) cascade.'() { given: 'a schema set' - populateNewYangResourcesNameToContentMapAndAllModuleReferences(1) - objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet', newYangResourcesNameToContentMap) + populateYangResourceContentPerNameAndAllModuleReferences(1) + objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet', yangResourceContentPerName) and: 'optionally create anchor for the schema set' if (associateWithAnchor) { cpsAnchorService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet', 'newAnchor') @@ -261,11 +265,11 @@ class ModuleServiceIntegrationSpec extends FunctionalSpecBase { def 'Delete schema sets with shared resources.'() { given: 'a new schema set' - populateNewYangResourcesNameToContentMapAndAllModuleReferences(1) - objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet1', newYangResourcesNameToContentMap) + populateYangResourceContentPerNameAndAllModuleReferences(1) + objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet1', yangResourceContentPerName) and: 'another schema set which shares one yang resource (module)' - populateNewYangResourcesNameToContentMapAndAllModuleReferences(2) - objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet2', newYangResourcesNameToContentMap) + populateYangResourceContentPerNameAndAllModuleReferences(2) + objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet2', yangResourceContentPerName) when: 'all schema sets are retrieved' def moduleRevisions = objectUnderTest.getYangResourceModuleReferences(FUNCTIONAL_TEST_DATASPACE_1).revision then: 'both modules (revisions) are present' @@ -299,23 +303,23 @@ class ModuleServiceIntegrationSpec extends FunctionalSpecBase { U P G R A D E */ - def 'Upgrade schema set (with existing and new modules, no matching module set tag in NCMP)'() { + def 'Upgrade schema set [with existing and new modules, no matching module set tag in NCMP]'() { given: 'an anchor and schema set with 2 modules (to be upgraded)' - populateNewYangResourcesNameToContentMapAndAllModuleReferences('original', 2) - objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', newYangResourcesNameToContentMap, []) + populateYangResourceContentPerNameAndAllModuleReferences('original', 2) + objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', yangResourceContentPerName, allModuleReferences) cpsAnchorService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', 'targetAnchor') def yangResourceModuleReferencesBeforeUpgrade = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'targetAnchor') assert yangResourceModuleReferencesBeforeUpgrade.size() == 2 assert yangResourceModuleReferencesBeforeUpgrade.containsAll([new ModuleReference('original_0','2000-01-01'),new ModuleReference('original_1','2001-01-01')]) and: 'two new 2 modules (from node)' - populateNewYangResourcesNameToContentMapAndAllModuleReferences('new', 2) + populateYangResourceContentPerNameAndAllModuleReferences('new', 2) def newModuleReferences = [new ModuleReference('new_0','2000-01-01'),new ModuleReference('new_1','2001-01-01')] and: 'a list of all module references (normally retrieved from node)' - def allModuleReferences = [] - allModuleReferences.add(bookStoreModuleReference) - allModuleReferences.addAll(newModuleReferences) + def allOtherModuleReferences = [] + allOtherModuleReferences.add(bookStoreModuleReference) + allOtherModuleReferences.addAll(newModuleReferences) when: 'the schema set is upgraded' - objectUnderTest.upgradeSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', newYangResourcesNameToContentMap, allModuleReferences) + objectUnderTest.upgradeSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', yangResourceContentPerName, allOtherModuleReferences) then: 'the new anchor has the correct new and existing modules' def yangResourceModuleReferencesAfterUpgrade = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'targetAnchor') assert yangResourceModuleReferencesAfterUpgrade.size() == 3 @@ -325,18 +329,19 @@ class ModuleServiceIntegrationSpec extends FunctionalSpecBase { objectUnderTest.deleteSchemaSetsWithCascade(FUNCTIONAL_TEST_DATASPACE_1, ['targetSchema']) } - def 'Upgrade existing schema set from another anchor (used in NCMP for matching module set tag)'() { + def 'Upgrade existing schema set from another anchor [used in NCMP for matching module set tag]'() { given: 'an anchor and schema set with 1 module (target)' - populateNewYangResourcesNameToContentMapAndAllModuleReferences('target', 1) - objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', newYangResourcesNameToContentMap, []) + populateYangResourceContentPerNameAndAllModuleReferences('target', 1) + objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', yangResourceContentPerName, allModuleReferences) cpsAnchorService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', 'targetAnchor') def moduleReferencesBeforeUpgrade = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'targetAnchor') assert moduleReferencesBeforeUpgrade.size() == 1 and: 'another anchor and schema set with 2 other modules (source for upgrade)' - populateNewYangResourcesNameToContentMapAndAllModuleReferences('source', 2) - objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'sourceSchema', newYangResourcesNameToContentMap, []) + populateYangResourceContentPerNameAndAllModuleReferences('source', 2) + objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'sourceSchema', yangResourceContentPerName, allModuleReferences) cpsAnchorService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, 'sourceSchema', 'sourceAnchor') - assert objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'sourceAnchor').size() == 2 + def yangResourcesModuleReferences = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'sourceAnchor') + assert yangResourcesModuleReferences.size() == 2 when: 'the target schema is upgraded using the module references from the source anchor' def moduleReferencesFromSourceAnchor = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'sourceAnchor') objectUnderTest.upgradeSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', noNewModules, moduleReferencesFromSourceAnchor) @@ -354,17 +359,19 @@ class ModuleServiceIntegrationSpec extends FunctionalSpecBase { H E L P E R M E T H O D S */ - def populateNewYangResourcesNameToContentMapAndAllModuleReferences(numberOfModules) { - populateNewYangResourcesNameToContentMapAndAllModuleReferences('name', numberOfModules) + def populateYangResourceContentPerNameAndAllModuleReferences(numberOfModules) { + populateYangResourceContentPerNameAndAllModuleReferences('name', numberOfModules) } - def populateNewYangResourcesNameToContentMapAndAllModuleReferences(namePrefix, numberOfModules) { + def populateYangResourceContentPerNameAndAllModuleReferences(namePrefix, numberOfModules) { + yangResourceContentPerName.clear() + allModuleReferences.clear() numberOfModules.times { def uniqueName = namePrefix + '_' + it def uniqueRevision = String.valueOf(2000 + it) + '-01-01' - moduleReferences.add(new ModuleReference(uniqueName, uniqueRevision)) + allModuleReferences.add(new ModuleReference(uniqueName, uniqueRevision)) def uniqueContent = NEW_RESOURCE_CONTENT.replace(NEW_RESOURCE_REVISION, uniqueRevision).replace('module test_module', 'module '+uniqueName) - newYangResourcesNameToContentMap.put(uniqueRevision, uniqueContent) + yangResourceContentPerName.put(uniqueName, uniqueContent) } } diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/CpsModuleServicePerfTest.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/CpsModuleServicePerfTest.groovy index a37bb6ad4d..d8553419ce 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/CpsModuleServicePerfTest.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/CpsModuleServicePerfTest.groovy @@ -47,15 +47,15 @@ class CpsModuleServicePerfTest extends CpsPerfTestBase { def 'Store new schema set with many modules'() { when: 'a new schema set with 200 modules is stored' - def newYangResourcesNameToContentMap = [:] + def newYangResourceContentPerName = [:] (1..200).each { def year = 2000 + it def resourceName = "module${it}".toString() def moduleName = "stores${it}" def content = NEW_RESOURCE_CONTENT.replace('2020',String.valueOf(year)).replace('stores',moduleName) - newYangResourcesNameToContentMap.put(resourceName, content) + newYangResourceContentPerName.put(resourceName, content) } - objectUnderTest.createSchemaSet(CPS_PERFORMANCE_TEST_DATASPACE, 'perfSchemaSet', newYangResourcesNameToContentMap) + objectUnderTest.createSchemaSet(CPS_PERFORMANCE_TEST_DATASPACE, 'perfSchemaSet', newYangResourceContentPerName) then: 'the schema set is persisted correctly' def result = cpsModuleService.getSchemaSet(CPS_PERFORMANCE_TEST_DATASPACE, 'perfSchemaSet') result.moduleReferences.size() == 200 |