aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToine Siebelink <toine.siebelink@est.tech>2021-02-01 15:36:38 +0000
committerGerrit Code Review <gerrit@onap.org>2021-02-01 15:36:38 +0000
commit30da8a9ea8f8f77ab5976097749caffbd16c4a93 (patch)
treeef77789b0409c2d0b6e6aa3af74e7353f4de9579
parent850e3ecdecbedd30e65ae7cbaa81fc5301766f45 (diff)
parent74753d923b77d87b17e8221ecc86a084446648b7 (diff)
Merge "Attach a (JSON) data instance for a container with children to a given Anchor"
-rw-r--r--cps-rest/docs/api/swagger/cpsData.yml43
-rw-r--r--cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java18
-rw-r--r--cps-rest/src/test/groovy/org/onap/cps/rest/controller/AdminRestControllerSpec.groovy4
-rw-r--r--cps-rest/src/test/groovy/org/onap/cps/rest/exceptions/CpsRestExceptionHandlerSpec.groovy4
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/CpsDataService.java13
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java63
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java8
-rw-r--r--cps-service/src/main/java/org/onap/cps/utils/YangUtils.java17
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy11
9 files changed, 136 insertions, 45 deletions
diff --git a/cps-rest/docs/api/swagger/cpsData.yml b/cps-rest/docs/api/swagger/cpsData.yml
index c33cf168e..dcdb99adc 100644
--- a/cps-rest/docs/api/swagger/cpsData.yml
+++ b/cps-rest/docs/api/swagger/cpsData.yml
@@ -20,46 +20,47 @@ nodesByDataspaceAndAnchor:
$ref: 'components.yaml#/components/responses/NotFound'
x-codegen-request-body-name: xpath
-nodesByDataspace:
- get:
+ post:
tags:
- cps-data
- summary: Get all nodes for a given dataspace using an xpath or schema node identifier - DRAFT
- operationId: getNode
+ summary: Create a node for a given anchor for the given dataspace
+ operationId: createNode
parameters:
- $ref: 'components.yaml#/components/parameters/dataspaceNameInPath'
+ - $ref: 'components.yaml#/components/parameters/anchorNameInPath'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: string
responses:
- 200:
- $ref: 'components.yaml#/components/responses/Ok'
+ 201:
+ $ref: 'components.yaml#/components/responses/Created'
400:
$ref: 'components.yaml#/components/responses/BadRequest'
401:
$ref: 'components.yaml#/components/responses/Unauthorized'
403:
$ref: 'components.yaml#/components/responses/Forbidden'
- 404:
- $ref: 'components.yaml#/components/responses/NotFound'
- x-codegen-request-body-name: requestBody
- post:
+nodesByDataspace:
+ get:
tags:
- cps-data
- summary: Create a node for a given anchor for the given dataspace - DRAFT
- operationId: createNode
+ summary: Get all nodes for a given dataspace using an xpath or schema node identifier - DRAFT
+ operationId: getNode
parameters:
- $ref: 'components.yaml#/components/parameters/dataspaceNameInPath'
- requestBody:
- content:
- multipart/form-data:
- schema:
- $ref: 'components.yaml#/components/schemas/MultipartFile'
- required: true
responses:
- 201:
- $ref: 'components.yaml#/components/responses/Created'
+ 200:
+ $ref: 'components.yaml#/components/responses/Ok'
400:
$ref: 'components.yaml#/components/responses/BadRequest'
401:
$ref: 'components.yaml#/components/responses/Unauthorized'
403:
- $ref: 'components.yaml#/components/responses/Forbidden' \ No newline at end of file
+ $ref: 'components.yaml#/components/responses/Forbidden'
+ 404:
+ $ref: 'components.yaml#/components/responses/NotFound'
+ x-codegen-request-body-name: requestBody \ No newline at end of file
diff --git a/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java b/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java
index 2ecbd4f54..07f555383 100644
--- a/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java
+++ b/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java
@@ -20,28 +20,27 @@
package org.onap.cps.rest.controller;
import javax.validation.Valid;
-import org.modelmapper.ModelMapper;
-import org.onap.cps.api.CpsAdminService;
+import javax.validation.constraints.NotNull;
+import org.onap.cps.api.CpsDataService;
import org.onap.cps.rest.api.CpsDataApi;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("${rest.api.base-path}")
public class DataRestController implements CpsDataApi {
@Autowired
- private CpsAdminService cpsAdminService;
-
- @Autowired
- private ModelMapper modelMapper;
+ private CpsDataService cpsDataService;
@Override
- public ResponseEntity<String> createNode(@Valid final MultipartFile multipartFile, final String dataspaceName) {
- return null;
+ public ResponseEntity<String> createNode(@Valid final String jsonData, @NotNull final String dataspaceName,
+ @NotNull @Valid final String anchorName) {
+ cpsDataService.saveData(dataspaceName, anchorName, jsonData);
+ return new ResponseEntity<>(HttpStatus.CREATED);
}
@Override
@@ -53,4 +52,5 @@ public class DataRestController implements CpsDataApi {
public ResponseEntity<Object> getNodeByDataspaceAndAnchor(final String dataspaceName, final String anchorName) {
return null;
}
+
}
diff --git a/cps-rest/src/test/groovy/org/onap/cps/rest/controller/AdminRestControllerSpec.groovy b/cps-rest/src/test/groovy/org/onap/cps/rest/controller/AdminRestControllerSpec.groovy
index 540d6224a..c1c7c5dcd 100644
--- a/cps-rest/src/test/groovy/org/onap/cps/rest/controller/AdminRestControllerSpec.groovy
+++ b/cps-rest/src/test/groovy/org/onap/cps/rest/controller/AdminRestControllerSpec.groovy
@@ -22,6 +22,7 @@ package org.onap.cps.rest.controller
import org.modelmapper.ModelMapper
import org.onap.cps.api.CpsAdminService
+import org.onap.cps.api.CpsDataService
import org.onap.cps.api.CpsModuleService
import org.onap.cps.spi.exceptions.DataspaceAlreadyDefinedException
import org.onap.cps.spi.exceptions.SchemaSetInUseException
@@ -56,6 +57,9 @@ class AdminRestControllerSpec extends Specification {
CpsAdminService mockCpsAdminService = Mock()
@SpringBean
+ CpsDataService mockCpsDataService = Mock()
+
+ @SpringBean
ModelMapper modelMapper = Mock()
@Autowired
diff --git a/cps-rest/src/test/groovy/org/onap/cps/rest/exceptions/CpsRestExceptionHandlerSpec.groovy b/cps-rest/src/test/groovy/org/onap/cps/rest/exceptions/CpsRestExceptionHandlerSpec.groovy
index edc484b14..7dbf6bc9a 100644
--- a/cps-rest/src/test/groovy/org/onap/cps/rest/exceptions/CpsRestExceptionHandlerSpec.groovy
+++ b/cps-rest/src/test/groovy/org/onap/cps/rest/exceptions/CpsRestExceptionHandlerSpec.groovy
@@ -22,6 +22,7 @@ package org.onap.cps.rest.exceptions
import groovy.json.JsonSlurper
import org.modelmapper.ModelMapper
import org.onap.cps.api.CpsAdminService
+import org.onap.cps.api.CpsDataService
import org.onap.cps.api.CpsModuleService
import org.onap.cps.spi.exceptions.AnchorAlreadyDefinedException
import org.onap.cps.spi.exceptions.CpsException
@@ -56,6 +57,9 @@ class CpsRestExceptionHandlerSpec extends Specification {
CpsModuleService mockCpsModuleService = Mock()
@SpringBean
+ CpsDataService mockCpsDataService = Mock()
+
+ @SpringBean
ModelMapper modelMapper = Mock()
@Autowired
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 ebeeb9a82..a8f49655a 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
@@ -19,9 +19,20 @@
package org.onap.cps.api;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.onap.cps.spi.exceptions.DataValidationException;
+
/*
* Datastore interface for handling CPS data.
*/
public interface CpsDataService {
-
+ /**
+ * Persists data for the given anchor and dataspace.
+ *
+ * @param dataspaceName dataspace name
+ * @param anchorName anchor name
+ * @param jsonData json data
+ * @throws DataValidationException when json data is invalid
+ */
+ void saveData(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull String jsonData);
}
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
new file mode 100644
index 000000000..2a1e18b6d
--- /dev/null
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
@@ -0,0 +1,63 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation
+ * Modifications Copyright (C) 2020 Bell Canada. All rights reserved.
+ * ================================================================================
+ * 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.api.impl;
+
+import org.onap.cps.api.CpsAdminService;
+import org.onap.cps.api.CpsDataService;
+import org.onap.cps.api.CpsModuleService;
+import org.onap.cps.spi.CpsDataPersistenceService;
+import org.onap.cps.spi.model.Anchor;
+import org.onap.cps.spi.model.DataNode;
+import org.onap.cps.spi.model.DataNodeBuilder;
+import org.onap.cps.utils.YangUtils;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class CpsDataServiceImpl implements CpsDataService {
+
+ @Autowired
+ private CpsDataPersistenceService cpsDataPersistenceService;
+
+ @Autowired
+ private CpsAdminService cpsAdminService;
+
+ @Autowired
+ private CpsModuleService cpsModuleService;
+
+ @Autowired
+ private YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache;
+
+ @Override
+ public void saveData(final String dataspaceName, final String anchorName, final String jsonData) {
+ final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
+ final SchemaContext schemaContext = getSchemaContext(dataspaceName, anchor.getSchemaSetName());
+ final NormalizedNode normalizedNode = YangUtils.parseJsonData(jsonData, schemaContext);
+ final DataNode dataNode = new DataNodeBuilder().withNormalizedNodeTree(normalizedNode).build();
+ cpsDataPersistenceService.storeDataNode(dataspaceName, anchor.getName(), dataNode);
+ }
+
+ private SchemaContext getSchemaContext(final String dataspaceName, final String schemaSetName) {
+ return yangTextSchemaSourceSetCache.get(dataspaceName, schemaSetName).getSchemaContext();
+ }
+} \ No newline at end of file
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
index 427ddd6c6..990b7bb93 100644
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
@@ -40,9 +40,9 @@ public class CpsModuleServiceImpl implements CpsModuleService {
@Override
public void createSchemaSet(final String dataspaceName, final String schemaSetName,
- final Map<String, String> yangResourcesNameToContentMap) {
+ final Map<String, String> yangResourcesNameToContentMap) {
final YangTextSchemaSourceSet yangTextSchemaSourceSet
- = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap);
+ = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap);
cpsModulePersistenceService.storeSchemaSet(dataspaceName, schemaSetName, yangResourcesNameToContentMap);
yangTextSchemaSourceSetCache.updateCache(dataspaceName, schemaSetName, yangTextSchemaSourceSet);
}
@@ -50,9 +50,9 @@ public class CpsModuleServiceImpl implements CpsModuleService {
@Override
public SchemaSet getSchemaSet(final String dataspaceName, final String schemaSetName) {
final YangTextSchemaSourceSet yangTextSchemaSourceSet = yangTextSchemaSourceSetCache
- .get(dataspaceName, schemaSetName);
+ .get(dataspaceName, schemaSetName);
return SchemaSet.builder().name(schemaSetName).dataspaceName(dataspaceName)
- .moduleReferences(yangTextSchemaSourceSet.getModuleReferences()).build();
+ .moduleReferences(yangTextSchemaSourceSet.getModuleReferences()).build();
}
@Override
diff --git a/cps-service/src/main/java/org/onap/cps/utils/YangUtils.java b/cps-service/src/main/java/org/onap/cps/utils/YangUtils.java
index 1244d54af..1ba94328d 100644
--- a/cps-service/src/main/java/org/onap/cps/utils/YangUtils.java
+++ b/cps-service/src/main/java/org/onap/cps/utils/YangUtils.java
@@ -27,6 +27,7 @@ import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.spi.exceptions.DataValidationException;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
@@ -52,17 +53,21 @@ public class YangUtils {
* @param schemaContext the SchemaContext for the given data
* @return the NormalizedNode representing the json data
*/
- public static NormalizedNode parseJsonData(final String jsonData, final SchemaContext schemaContext)
- throws IOException {
+ public static NormalizedNode parseJsonData(final String jsonData, final SchemaContext schemaContext) {
final JSONCodecFactory jsonCodecFactory = JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02
.getShared(schemaContext);
final NormalizedNodeResult normalizedNodeResult = new NormalizedNodeResult();
final NormalizedNodeStreamWriter normalizedNodeStreamWriter = ImmutableNormalizedNodeStreamWriter
.from(normalizedNodeResult);
- try (final JsonParserStream jsonParserStream = JsonParserStream
- .create(normalizedNodeStreamWriter, jsonCodecFactory)) {
- final JsonReader jsonReader = new JsonReader(new StringReader(jsonData));
- jsonParserStream.parse(jsonReader);
+ try {
+ try (final JsonParserStream jsonParserStream = JsonParserStream
+ .create(normalizedNodeStreamWriter, jsonCodecFactory)) {
+ final JsonReader jsonReader = new JsonReader(new StringReader(jsonData));
+ jsonParserStream.parse(jsonReader);
+ }
+ } catch (final IOException e) {
+ throw new DataValidationException("Failed to parse json data.", String
+ .format("Exception occurred on parsing string %s.", jsonData), e);
}
return normalizedNodeResult.getResult();
}
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
index 5f2168aeb..261d17493 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
@@ -22,6 +22,7 @@ package org.onap.cps.api.impl
import org.onap.cps.TestUtils
import org.onap.cps.api.CpsAdminService
+import org.onap.cps.spi.CpsDataPersistenceService
import org.onap.cps.spi.CpsModulePersistenceService
import org.onap.cps.spi.exceptions.ModelValidationException
import org.onap.cps.spi.model.ModuleReference
@@ -46,6 +47,8 @@ class CpsModuleServiceImplSpec extends Specification {
CpsModulePersistenceService mockModuleStoreService = Mock()
@SpringBean
CpsAdminService mockCpsAdminService = Mock()
+ @SpringBean
+ CpsDataPersistenceService mockDataPersistenceService = Mock()
@Autowired
CpsModuleServiceImpl objectUnderTest = new CpsModuleServiceImpl()
@SpringBean
@@ -93,14 +96,14 @@ class CpsModuleServiceImplSpec extends Specification {
}
@Unroll
- def 'Delete set by name and dataspace with #cascadeDeleteOption.'(){
+ def 'Delete set by name and dataspace with #cascadeDeleteOption.'() {
when: 'schema set deletion is requested'
objectUnderTest.deleteSchemaSet(dataspaceName, schemaSetname, cascadeDeleteOption)
then: 'persistence service method is invoked with same parameters'
mockModuleStoreService.deleteSchemaSet(dataspaceName, schemaSetname, cascadeDeleteOption)
where: 'following parameters are used'
- dataspaceName | schemaSetname | cascadeDeleteOption
- 'dataspace-1' | 'schemas-set-1' | CASCADE_DELETE_ALLOWED
- 'dataspace-2' | 'schemas-set-2' | CASCADE_DELETE_PROHIBITED
+ dataspaceName | schemaSetname | cascadeDeleteOption
+ 'dataspace-1' | 'schemas-set-1' | CASCADE_DELETE_ALLOWED
+ 'dataspace-2' | 'schemas-set-2' | CASCADE_DELETE_PROHIBITED
}
}