Merge "Added API to get all schema sets for a given dataspace."
authorToine Siebelink <toine.siebelink@est.tech>
Fri, 9 Dec 2022 15:33:12 +0000 (15:33 +0000)
committerGerrit Code Review <gerrit@onap.org>
Fri, 9 Dec 2022 15:33:12 +0000 (15:33 +0000)
13 files changed:
cps-rest/docs/openapi/cpsAdmin.yml
cps-rest/docs/openapi/openapi.yml
cps-rest/src/main/java/org/onap/cps/rest/controller/AdminRestController.java
cps-rest/src/test/groovy/org/onap/cps/rest/controller/AdminRestControllerSpec.groovy
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java
cps-ri/src/main/java/org/onap/cps/spi/repository/SchemaSetRepository.java
cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceIntegrationSpec.groovy
cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java
cps-service/src/main/java/org/onap/cps/spi/exceptions/SchemaSetNotFoundException.java
cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
docs/api/swagger/cps/openapi.yaml

index e887ef2..595f6d7 100644 (file)
@@ -91,6 +91,31 @@ schemaSet:
         $ref: 'components.yml#/components/responses/Conflict'
       '500':
         $ref: 'components.yml#/components/responses/InternalServerError'
+  get:
+    description: Read all schema sets, given a dataspace
+    tags:
+      - cps-admin
+    summary: Get schema sets
+    operationId: getSchemaSets
+    parameters:
+      - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
+    responses:
+      '200':
+        description: OK
+        content:
+          application/json:
+            schema:
+              type: array
+              items:
+                $ref: 'components.yml#/components/schemas/SchemaSetDetails'
+      '400':
+        $ref: 'components.yml#/components/responses/BadRequest'
+      '401':
+        $ref: 'components.yml#/components/responses/Unauthorized'
+      '403':
+        $ref: 'components.yml#/components/responses/Forbidden'
+      '500':
+        $ref: 'components.yml#/components/responses/InternalServerError'
 
 schemaSetBySchemaSetName:
   get:
index e170295..e02d6a6 100644 (file)
@@ -84,4 +84,4 @@ paths:
     $ref: 'cpsQuery.yml#/nodesByDataspaceAndAnchorAndCpsPath'
 
 security:
-  - basicAuth: []
\ No newline at end of file
+  - basicAuth: []
index a29f8d2..285a15c 100755 (executable)
@@ -109,6 +109,20 @@ public class AdminRestController implements CpsAdminApi {
         return new ResponseEntity<>(schemaSetDetails, HttpStatus.OK);
     }
 
+    /**
+     * Get list of schema sets for a given dataspace name.
+     *
+     * @param dataspaceName dataspace name
+     * @return a {@Link ResponseEntity} of schema sets & {@link HttpStatus} OK
+     */
+    @Override
+    public ResponseEntity<List<SchemaSetDetails>> getSchemaSets(final String dataspaceName) {
+        final Collection<SchemaSet> schemaSets = cpsModuleService.getSchemaSets(dataspaceName);
+        final List<SchemaSetDetails> schemaSetDetails = schemaSets.stream().map(cpsRestInputMapper::toSchemaSetDetails)
+                .collect(Collectors.toList());
+        return new ResponseEntity<>(schemaSetDetails, HttpStatus.OK);
+    }
+
     /**
      * Delete a {@link SchemaSet} based on given dataspace name & schemaset name.
      *
index e9612fc..7120ce4 100755 (executable)
@@ -278,6 +278,21 @@ class AdminRestControllerSpec extends Specification {
             response.getContentAsString().contains(schemaSetName)
     }
 
+    def 'Get all schema sets for a given dataspace name.'() {
+        given: 'service method returns all schema sets for a dataspace'
+            mockCpsModuleService.getSchemaSets(dataspaceName) >>
+                [new SchemaSet(name: schemaSetName, dataspaceName: dataspaceName),
+                new SchemaSet(name: "test-schemaset", dataspaceName: dataspaceName)]
+        and: 'an endpoint'
+            def schemaSetEndpoint = "$basePath/v1/dataspaces/$dataspaceName/schema-sets"
+        when: 'get schema sets API is invoked'
+            def response = mvc.perform(get(schemaSetEndpoint)).andReturn().response
+        then: 'the correct schema sets is returned'
+            assert response.status == HttpStatus.OK.value()
+            assert response.getContentAsString() == '[{"dataspaceName":"my_dataspace","moduleReferences":[],"name":' +
+                   '"my_schema_set"},{"dataspaceName":"my_dataspace","moduleReferences":[],"name":"test-schemaset"}]'
+    }
+
     def 'Create Anchor.'() {
         given: 'request parameters'
             def requestParams = new LinkedMultiValueMap<>()
index 8008e03..03f021e 100755 (executable)
@@ -3,6 +3,7 @@
  *  Copyright (C) 2020-2022 Nordix Foundation
  *  Modifications Copyright (C) 2020-2022 Bell Canada.
  *  Modifications Copyright (C) 2021 Pantheon.tech
+ *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -55,6 +56,7 @@ import org.onap.cps.spi.exceptions.DuplicatedYangResourceException;
 import org.onap.cps.spi.exceptions.ModelValidationException;
 import org.onap.cps.spi.model.ModuleDefinition;
 import org.onap.cps.spi.model.ModuleReference;
+import org.onap.cps.spi.model.SchemaSet;
 import org.onap.cps.spi.repository.DataspaceRepository;
 import org.onap.cps.spi.repository.ModuleReferenceRepository;
 import org.onap.cps.spi.repository.SchemaSetRepository;
@@ -154,6 +156,14 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
         }
     }
 
+    @Override
+    public Collection<SchemaSet> getSchemaSetsByDataspaceName(final String dataspaceName) {
+        final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+        final List<SchemaSetEntity> schemaSetEntities = schemaSetRepository.getByDataspace(dataspaceEntity);
+        return schemaSetEntities.stream()
+                .map(CpsModulePersistenceServiceImpl::toSchemaSet).collect(Collectors.toList());
+    }
+
     @Override
     @Transactional
     // A retry is made to store the schema set if it fails because of duplicated yang resource exception that
@@ -364,4 +374,9 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
                 yangResourceEntity.getRevision(),
                 yangResourceEntity.getContent());
     }
+
+    private static SchemaSet toSchemaSet(final SchemaSetEntity schemaSetEntity) {
+        return SchemaSet.builder().name(schemaSetEntity.getName())
+                .dataspaceName(schemaSetEntity.getDataspace().getName()).build();
+    }
 }
index a15ce62..8cecb0a 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2020 Pantheon.tech
+ *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 package org.onap.cps.spi.repository;
 
+import java.util.Collection;
+import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 import javax.validation.constraints.NotNull;
 import org.onap.cps.spi.entities.DataspaceEntity;
 import org.onap.cps.spi.entities.SchemaSetEntity;
@@ -33,6 +37,13 @@ public interface SchemaSetRepository extends JpaRepository<SchemaSetEntity, Inte
     Optional<SchemaSetEntity> findByDataspaceAndName(@NotNull DataspaceEntity dataspaceEntity,
         @NotNull String schemaSetName);
 
+    /**
+     * Gets schema sets by dataspace.
+     * @param dataspaceEntity dataspace entity
+     * @return list of schema set entity
+     */
+    Collection<SchemaSetEntity> findByDataspace(@NotNull DataspaceEntity dataspaceEntity);
+
     Integer countByDataspace(@NotNull DataspaceEntity dataspaceEntity);
 
     /**
@@ -48,4 +59,15 @@ public interface SchemaSetRepository extends JpaRepository<SchemaSetEntity, Inte
         return findByDataspaceAndName(dataspaceEntity, schemaSetName)
             .orElseThrow(() -> new SchemaSetNotFoundException(dataspaceEntity.getName(), schemaSetName));
     }
+
+    /**
+     * Gets all schema sets for a given dataspace.
+     *
+     * @param dataspaceEntity dataspace entity
+     * @return list of schema set entity
+     * @throws SchemaSetNotFoundException if SchemaSet not found
+     */
+    default List<SchemaSetEntity> getByDataspace(@NotNull final DataspaceEntity dataspaceEntity) {
+        return findByDataspace(dataspaceEntity).stream().collect(Collectors.toList());
+    }
 }
index f9ebc52..bcb0807 100644 (file)
@@ -2,6 +2,7 @@
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021-2022 Nordix Foundation
  *  Modifications Copyright (C) 2021-2022 Bell Canada.
+ *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the 'License');
  *  you may not use this file except in compliance with the License.
@@ -28,6 +29,7 @@ import org.onap.cps.spi.exceptions.DataspaceNotFoundException
 import org.onap.cps.spi.exceptions.SchemaSetNotFoundException
 import org.onap.cps.spi.model.ModuleDefinition
 import org.onap.cps.spi.model.ModuleReference
+import org.onap.cps.spi.model.SchemaSet
 import org.onap.cps.spi.repository.AnchorRepository
 import org.onap.cps.spi.repository.SchemaSetRepository
 import org.onap.cps.spi.repository.SchemaSetYangResourceRepositoryImpl
@@ -208,6 +210,14 @@ class CpsModulePersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase
                 existingResourceRevision, existingResourceContent, existingResourceChecksum)
     }
 
+    @Sql([CLEAR_DATA, SET_DATA])
+    def 'Retrieve schema sets for a given dataspace name'() {
+        when: 'the schema set resources for a given dataspace name is retrieved'
+            def result = objectUnderTest.getSchemaSetsByDataspaceName(DATASPACE_NAME)
+        then: 'the correct resources are returned'
+             result.contains(new SchemaSet(name: 'SCHEMA-SET-001', dataspaceName: 'DATASPACE-001'))
+    }
+
     @Sql([CLEAR_DATA, SET_DATA])
     def 'Delete schema set'() {
         when: 'a schema set is deleted with cascade-prohibited option'
index 6b17e82..b1f90d6 100644 (file)
@@ -2,6 +2,7 @@
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2020-2022 Nordix Foundation
  *  Modifications Copyright (C) 2020-2021 Pantheon.tech
+ *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -65,6 +66,14 @@ public interface CpsModuleService {
      */
     SchemaSet getSchemaSet(String dataspaceName, String schemaSetName);
 
+    /**
+     * Retrieve all schema sets in the given dataspace.
+     *
+     * @param dataspaceName dataspace name
+     * @return all SchemaSets
+     */
+    Collection<SchemaSet> getSchemaSets(String dataspaceName);
+
     /**
      * Deletes Schema Set.
      *
index b4890f4..a04dd2a 100644 (file)
@@ -3,6 +3,7 @@
  *  Copyright (C) 2020-2022 Nordix Foundation
  *  Modifications Copyright (C) 2020-2021 Pantheon.tech
  *  Modifications Copyright (C) 2022 Bell Canada
+ *  Modifications Copyright (C) 2022 TechMahindra Ltd
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -35,6 +36,7 @@ import org.onap.cps.spi.model.ModuleDefinition;
 import org.onap.cps.spi.model.ModuleReference;
 import org.onap.cps.spi.model.SchemaSet;
 import org.onap.cps.spi.utils.CpsValidator;
+import org.onap.cps.yang.YangTextSchemaSourceSet;
 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -77,6 +79,15 @@ public class CpsModuleServiceImpl implements CpsModuleService {
             .moduleReferences(yangTextSchemaSourceSet.getModuleReferences()).build();
     }
 
+    @Override
+    public Collection<SchemaSet> getSchemaSets(final String dataspaceName) {
+        cpsValidator.validateNameCharacters(dataspaceName);
+        final Collection<SchemaSet> schemaSets =
+            cpsModulePersistenceService.getSchemaSetsByDataspaceName(dataspaceName);
+        schemaSets.forEach(schemaSet -> setModuleReferences(schemaSet, dataspaceName));
+        return schemaSets;
+    }
+
     @Override
     @Transactional
     public void deleteSchemaSet(final String dataspaceName, final String schemaSetName,
@@ -124,4 +135,9 @@ public class CpsModuleServiceImpl implements CpsModuleService {
         return CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED == cascadeDeleteAllowed;
     }
 
+    private void setModuleReferences(final SchemaSet schemaSet, final String dataspaceName) {
+        final YangTextSchemaSourceSet yangTextSchemaSourceSet = yangTextSchemaSourceSetCache
+            .get(dataspaceName, schemaSet.getName());
+        schemaSet.setModuleReferences(yangTextSchemaSourceSet.getModuleReferences());
+    }
 }
index aaf6b38..f5dc8ac 100755 (executable)
@@ -2,6 +2,7 @@
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2020-2022 Nordix Foundation
  *  Modifications Copyright (C) 2020-2022 Bell Canada.
+ *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -25,6 +26,7 @@ import java.util.Collection;
 import java.util.Map;
 import org.onap.cps.spi.model.ModuleDefinition;
 import org.onap.cps.spi.model.ModuleReference;
+import org.onap.cps.spi.model.SchemaSet;
 
 /**
  * Service to manage modules.
@@ -51,6 +53,14 @@ public interface CpsModulePersistenceService {
     void storeSchemaSetFromModules(String dataspaceName, String schemaSetName,
         Map<String, String> newModuleNameToContentMap, Collection<ModuleReference> allModuleReferences);
 
+    /**
+     * Get all schema sets for a given dataspace.
+     *
+     * @param dataspaceName dataspace name.
+     * @return List of schema sets
+     */
+    Collection<SchemaSet> getSchemaSetsByDataspaceName(String dataspaceName);
+
     /**
      * Deletes Schema Set.
      *
index cf63f92..218918f 100644 (file)
@@ -38,4 +38,5 @@ public class SchemaSetNotFoundException extends CpsAdminException {
         super("Schema Set not found.",
                 String.format("Schema Set with name %s was not found for dataspace %s.", schemaSetName, dataspaceName));
     }
+
 }
index 690578e..358a6fb 100644 (file)
@@ -3,6 +3,7 @@
  *  Copyright (C) 2020-2022 Nordix Foundation
  *  Modifications Copyright (C) 2020-2021 Pantheon.tech
  *  Modifications Copyright (C) 2020-2022 Bell Canada.
+ *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -30,6 +31,8 @@ import org.onap.cps.spi.exceptions.SchemaSetInUseException
 import org.onap.cps.spi.utils.CpsValidator
 import org.onap.cps.spi.model.Anchor
 import org.onap.cps.spi.model.ModuleReference
+import org.onap.cps.spi.model.SchemaSet
+import org.onap.cps.yang.YangTextSchemaSourceSet
 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
 import spock.lang.Specification
 import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED
@@ -91,6 +94,25 @@ class CpsModuleServiceImplSpec extends Specification {
             1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someSchemaSet')
     }
 
+    def 'Get schema sets by dataspace name.'() {
+        given: 'two already present schema sets'
+            def moduleReference = new ModuleReference('sample1', '2022-12-07')
+            def sampleSchemaSet1 = new SchemaSet('testSchemaSet1', 'testDataspace', [moduleReference])
+            def sampleSchemaSet2 = new SchemaSet('testSchemaSet2', 'testDataspace', [moduleReference])
+        and: 'the persistence service returns the created schema sets'
+            mockCpsModulePersistenceService.getSchemaSetsByDataspaceName('testDataspace') >> [sampleSchemaSet1, sampleSchemaSet2]
+        and: 'yang resource cache always returns a schema source set'
+            def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet)
+            mockYangTextSchemaSourceSetCache.get('testDataspace', _) >> mockYangTextSchemaSourceSet
+        when: 'get schema sets method is invoked'
+            def result = objectUnderTest.getSchemaSets('testDataspace')
+        then: 'the correct schema sets are returned'
+            assert result.size() == 2
+            assert result.containsAll(sampleSchemaSet1, sampleSchemaSet2)
+        and: 'the Cps Validator is called on the dataspaceName'
+            1 * mockCpsValidator.validateNameCharacters('testDataspace')
+    }
+
     def 'Delete schema-set when cascade is allowed.'() {
         given: '#numberOfAnchors anchors are associated with schemaset'
             def associatedAnchors = createAnchors(numberOfAnchors)
index 8ea0d7b..09ccbe1 100644 (file)
@@ -651,6 +651,69 @@ paths:
                 status: 500
                 message: Internal Server Error
                 details: Internal Server Error occurred
+    get:
+      tags:
+      - cps-admin
+      summary: Get schema sets for a given dataspace
+      description: "Read schema sets for a given dataspace"
+      operationId: getSchemaSets
+      parameters:
+        - name: dataspace-name
+          in: path
+          description: dataspace-name
+          required: true
+          schema:
+            type: string
+            example: my-dataspace
+      responses:
+        "200":
+          description: OK
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/SchemaSetDetails'
+        "400":
+          description: Bad Request
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 400
+                message: Bad Request
+                details: The provided request is not valid
+        "401":
+          description: Unauthorized
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 401
+                message: Unauthorized request
+                details: This request is unauthorized
+        "403":
+          description: Forbidden
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 403
+                message: Request Forbidden
+                details: This request is forbidden
+        "500":
+          description: Internal Server Error
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 500
+                message: Internal Server Error
+                details: Internal Server Error occurred
   /v1/dataspaces/{dataspace-name}/schema-sets/{schema-set-name}:
     get:
       tags: