From a1c6e6ac56f9e53f08b329ce7f5069514c62fc77 Mon Sep 17 00:00:00 2001 From: niamhcore Date: Thu, 21 Oct 2021 15:19:04 +0100 Subject: Add get cm handles by modules names - persistence layer - Add sql query to anchor repository - Add sql query to yang resource repository Issue-ID: CPS-644 Signed-off-by: niamhcore Change-Id: I85ab1fcb343e6be77628695153d8d9f303dc3112 --- .../spi/impl/CpsAdminPersistenceServiceImpl.java | 33 ++++++++++++++++ .../onap/cps/spi/repository/AnchorRepository.java | 16 ++++++++ .../cps/spi/repository/YangResourceRepository.java | 33 +++++++++++----- .../spi/impl/CpsAdminPersistenceServiceSpec.groovy | 35 +++++++++++++++++ .../resources/data/anchors-schemaset-modules.sql | 45 ++++++++++++++++++++++ 5 files changed, 153 insertions(+), 9 deletions(-) create mode 100644 cps-ri/src/test/resources/data/anchors-schemaset-modules.sql (limited to 'cps-ri') diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java index 2776c4d67..2b63169d4 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java @@ -23,6 +23,7 @@ package org.onap.cps.spi.impl; import java.util.Collection; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; import javax.transaction.Transactional; @@ -30,11 +31,13 @@ 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.exceptions.AlreadyDefinedException; +import org.onap.cps.spi.exceptions.ModuleNamesNotFoundException; import org.onap.cps.spi.model.Anchor; import org.onap.cps.spi.repository.AnchorRepository; import org.onap.cps.spi.repository.DataspaceRepository; import org.onap.cps.spi.repository.FragmentRepository; import org.onap.cps.spi.repository.SchemaSetRepository; +import org.onap.cps.spi.repository.YangResourceRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Component; @@ -54,6 +57,9 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic @Autowired private FragmentRepository fragmentRepository; + @Autowired + private YangResourceRepository yangResourceRepository; + @Override public void createDataspace(final String dataspaceName) { try { @@ -87,6 +93,14 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic return anchorEntities.stream().map(CpsAdminPersistenceServiceImpl::toAnchor).collect(Collectors.toList()); } + @Override + public Collection getAnchors(final String dataspaceName, final Collection inputModuleNames) { + validateDataspaceAndModuleNames(dataspaceName, inputModuleNames); + final Collection anchorEntities = + anchorRepository.getAnchorsByDataspaceNameAndModuleNames(dataspaceName, inputModuleNames); + return anchorEntities.stream().map(CpsAdminPersistenceServiceImpl::toAnchor).collect(Collectors.toSet()); + } + @Override public Anchor getAnchor(final String dataspaceName, final String anchorName) { return toAnchor(getAnchorEntity(dataspaceName, anchorName)); @@ -112,4 +126,23 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic .schemaSetName(anchorEntity.getSchemaSet().getName()) .build(); } + + private void validateDataspaceAndModuleNames(final String dataspaceName, + final Collection inputModuleNames) { + final Collection retrievedModuleNames = + yangResourceRepository.findAllModuleReferences(dataspaceName, inputModuleNames) + .stream().map(module -> module.getModuleName()) + .collect(Collectors.toList()); + if (retrievedModuleNames.isEmpty()) { + dataspaceRepository.getByName(dataspaceName); + } + if (inputModuleNames.size() > retrievedModuleNames.size()) { + final List moduleNamesNotFound = inputModuleNames.stream() + .filter(moduleName -> !retrievedModuleNames.contains(moduleName)) + .collect(Collectors.toList()); + if (!moduleNamesNotFound.isEmpty()) { + throw new ModuleNamesNotFoundException(dataspaceName, moduleNamesNotFound); + } + } + } } diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java index 030555545..6d4cb3c71 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2021 Pantheon.tech + * Modifications Copyright (C) 2021 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +28,8 @@ import org.onap.cps.spi.entities.DataspaceEntity; import org.onap.cps.spi.entities.SchemaSetEntity; import org.onap.cps.spi.exceptions.AnchorNotFoundException; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; public interface AnchorRepository extends JpaRepository { @@ -41,4 +44,17 @@ public interface AnchorRepository extends JpaRepository { Collection findAllByDataspace(@NotNull DataspaceEntity dataspaceEntity); Collection findAllBySchemaSet(@NotNull SchemaSetEntity schemaSetEntity); + + @Query(value = "SELECT DISTINCT\n" + + "anchor.*\n" + + "FROM\n" + + "yang_resource\n" + + "JOIN schema_set_yang_resources ON " + + "schema_set_yang_resources.yang_resource_id = yang_resource.id\n" + + "JOIN schema_set ON schema_set.id = schema_set_yang_resources.schema_set_id\n" + + "JOIN anchor ON anchor.schema_set_id = schema_set.id\n" + + "JOIN dataspace ON dataspace.id = anchor.dataspace_id AND dataspace.name = :dataspaceName\n" + + "WHERE yang_resource.module_Name IN (:moduleNames)", nativeQuery = true) + Collection getAnchorsByDataspaceNameAndModuleNames(@Param("dataspaceName") String dataspaceName, + @Param("moduleNames") Collection moduleNames); } \ No newline at end of file diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java index 764e2dfc7..3f5c43dec 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java @@ -20,6 +20,7 @@ package org.onap.cps.spi.repository; +import java.util.Collection; import java.util.List; import java.util.Set; import javax.validation.constraints.NotNull; @@ -41,11 +42,11 @@ public interface YangResourceRepository extends JpaRepository findAllModuleReferences(@Param("dataspaceName") String dataspaceName); @@ -54,18 +55,32 @@ public interface YangResourceRepository extends JpaRepository findAllModuleReferences( @Param("dataspaceName") String dataspaceName, @Param("anchorName") String anchorName); + @Query(value = "SELECT DISTINCT\n" + + "yang_resource.*\n" + + "FROM\n" + + "dataspace\n" + + "JOIN schema_set ON schema_set.dataspace_id = dataspace.id\n" + + "JOIN schema_set_yang_resources ON schema_set_yang_resources.schema_set_id = " + + "schema_set.id\n" + + "JOIN yang_resource ON yang_resource.id = schema_set_yang_resources.yang_resource_id\n" + + "WHERE\n" + + "dataspace.name = :dataspaceName and yang_resource.module_Name IN (:moduleNames)", nativeQuery = true) + Set findAllModuleReferences(@Param("dataspaceName") String dataspaceName, + @Param("moduleNames") Collection moduleNames); + + @Query(value = "SELECT id FROM yang_resource WHERE module_name=:name and revision=:revision", nativeQuery = true) Long getIdByModuleNameAndRevision(@Param("name") String moduleName, @Param("revision") String revision); diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy index cff8d5632..c37651089 100644 --- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy @@ -26,6 +26,7 @@ import org.onap.cps.spi.exceptions.AlreadyDefinedException import org.onap.cps.spi.exceptions.AnchorNotFoundException import org.onap.cps.spi.exceptions.DataspaceNotFoundException import org.onap.cps.spi.exceptions.SchemaSetNotFoundException +import org.onap.cps.spi.exceptions.ModuleNamesNotFoundException import org.onap.cps.spi.model.Anchor import org.springframework.beans.factory.annotation.Autowired import org.springframework.test.context.jdbc.Sql @@ -37,6 +38,7 @@ class CpsAdminPersistenceServiceSpec extends CpsPersistenceSpecBase { static final String SET_DATA = '/data/anchor.sql' + static final String SAMPLE_DATA_FOR_ANCHORS_WITH_MODULES = '/data/anchors-schemaset-modules.sql' static final String EMPTY_DATASPACE_NAME = 'DATASPACE-002' static final Integer DELETED_ANCHOR_ID = 3001 static final Long DELETED_FRAGMENT_ID = 4001 @@ -140,4 +142,37 @@ class CpsAdminPersistenceServiceSpec extends CpsPersistenceSpecBase { 'dataspace does not exist' | 'unknown' | 'not-relevant' || DataspaceNotFoundException 'anchor does not exists' | DATASPACE_NAME | 'unknown' || AnchorNotFoundException } + + @Sql([CLEAR_DATA, SAMPLE_DATA_FOR_ANCHORS_WITH_MODULES]) + def 'Get anchors that have #scenario.'() { + when: 'all anchor are retrieved for the given dataspace name and module names' + def anchors = objectUnderTest.getAnchors('DATASPACE-001', inputModuleNames) + then: 'the expected anchors are returned' + anchors.size() == expectedAnchors.size() + anchors.containsAll(expectedAnchors) + where: 'the following data is used' + scenario | inputModuleNames || expectedAnchors + 'one module' | ['MODULE-NAME-001'] || [buildAnchor('ANCHOR1', 'DATASPACE-001', 'SCHEMA-SET-001')] + 'two modules' | ['MODULE-NAME-001', 'MODULE-NAME-002'] || [buildAnchor('ANCHOR1', 'DATASPACE-001', 'SCHEMA-SET-001'), buildAnchor('ANCHOR2', 'DATASPACE-001', 'SCHEMA-SET-002'), buildAnchor('ANCHOR3', 'DATASPACE-001', 'SCHEMA-SET-004')] + 'a module attached to multiple anchors' | ['MODULE-NAME-003'] || [buildAnchor('ANCHOR1', 'DATASPACE-001', 'SCHEMA-SET-001'), buildAnchor('ANCHOR2', 'DATASPACE-001', 'SCHEMA-SET-002')] + 'same module with different revisions' | ['MODULE-NAME-002'] || [buildAnchor('ANCHOR2', 'DATASPACE-001', 'SCHEMA-SET-002'), buildAnchor('ANCHOR3', 'DATASPACE-001', 'SCHEMA-SET-004')] + } + + @Sql([CLEAR_DATA, SAMPLE_DATA_FOR_ANCHORS_WITH_MODULES]) + def 'Get all anchors for an #scenario.'() { + when: 'attempt to get anchors' + objectUnderTest.getAnchors(dataspaceName, moduleNames) + then: 'the correct exception is thrown with the relevant details' + def thrownException = thrown(expectedException) + thrownException.details.contains(expectedMessageDetails) + where: 'the following data is used' + scenario | dataspaceName | moduleNames || expectedException | expectedMessageDetails + 'existing module in an unknown dataspace' | 'db-does-not-exist' | ['does-not-matter'] || DataspaceNotFoundException | 'db-does-not-exist' + 'unknown module in an existing dataspace' | 'DATASPACE-001' | ['module-does-not-exist'] || ModuleNamesNotFoundException | 'module-does-not-exist' + 'unknown module and known module in an existing dataspace' | 'DATASPACE-001' | ['MODULE-NAME-001', 'module-does-not-exist'] || ModuleNamesNotFoundException | 'module-does-not-exist' + } + + def buildAnchor(def anchorName, def dataspaceName, def SchemaSetName) { + return Anchor.builder().name(anchorName).dataspaceName(dataspaceName).schemaSetName(SchemaSetName).build() + } } diff --git a/cps-ri/src/test/resources/data/anchors-schemaset-modules.sql b/cps-ri/src/test/resources/data/anchors-schemaset-modules.sql new file mode 100644 index 000000000..d2b67f5ae --- /dev/null +++ b/cps-ri/src/test/resources/data/anchors-schemaset-modules.sql @@ -0,0 +1,45 @@ +/* + ============LICENSE_START======================================================= + Copyright (C) 2021 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========================================================= +*/ + +INSERT INTO DATASPACE (ID, NAME) VALUES + (1001, 'DATASPACE-001'), (1002, 'DATASPACE-002'); + +INSERT INTO SCHEMA_SET (ID, NAME, DATASPACE_ID) VALUES + (2001, 'SCHEMA-SET-001', 1001), + (2002, 'SCHEMA-SET-002', 1002), + (2003, 'SCHEMA-SET-003', 1001), + (2004, 'SCHEMA-SET-004', 1001); + +INSERT INTO YANG_RESOURCE (ID, NAME, CONTENT, CHECKSUM, MODULE_NAME, REVISION) VALUES + (3001, 'module1@2020-02-02.yang', 'CONTENT-001', 'checksum1','MODULE-NAME-001',null), + (3002, 'module2@2020-02-02.yang', 'CONTENT-002', 'checksum2','MODULE-NAME-002','REVISION-002'), + (3003, 'module3@2020-02-02.yang', 'CONTENT-003', 'checksum3','MODULE-NAME-003','REVISION-003'), + (3004, 'module4@2020-02-02.yang', 'CONTENT-004', 'checksum4','MODULE-NAME-004','REVISION-004'), + (3005, 'module5@2020-03-02.yang', 'CONTENT-005', 'checksum5','MODULE-NAME-002','REVISION-003'); + +INSERT INTO SCHEMA_SET_YANG_RESOURCES (SCHEMA_SET_ID, YANG_RESOURCE_ID) VALUES + (2001, 3001), (2002, 3002), + (2001, 3003), (2002, 3003), + (2003, 3004), (2004, 3005); + +INSERT INTO ANCHOR (ID, NAME, DATASPACE_ID, SCHEMA_SET_ID) VALUES + (6001, 'ANCHOR1', 1001, 2001), + (6002, 'ANCHOR2', 1001, 2002), + (6003, 'ANCHOR3', 1001, 2004); -- cgit 1.2.3-korg