aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrajesh.kumar <rk00747546@techmahindra.com>2024-12-24 13:40:06 +0530
committerrajesh.kumar <rk00747546@techmahindra.com>2025-03-05 11:19:34 +0530
commita6e58e73589e12cd52992bdf6177971dc88dd4c5 (patch)
tree1f6b732ee0ac323c4ac08cb948a37d0f88ecb783
parent4c645ef7d6e5a76a7d26991c247533cb75e64e22 (diff)
Add APIs to control notification subscription
- Add API for notification subscription - Add API for notification unsubscription - Add API for getting notification subscription information Issue-ID: CPS-2428 Change-Id: I56c34400dc73c71b936a51260efd241224dccdba Signed-off-by: rajesh.kumar <rk00747546@techmahindra.com>
-rw-r--r--cps-rest/docs/openapi/components.yml22
-rw-r--r--cps-rest/docs/openapi/cpsAdminV2.yml74
-rw-r--r--cps-rest/docs/openapi/openapi.yml5
-rwxr-xr-xcps-rest/src/main/java/org/onap/cps/rest/controller/AdminRestController.java28
-rwxr-xr-xcps-rest/src/test/groovy/org/onap/cps/rest/controller/AdminRestControllerSpec.groovy62
-rw-r--r--cps-rest/src/test/groovy/org/onap/cps/rest/exceptions/CpsRestExceptionHandlerSpec.groovy6
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/CpsNotificationService.java35
-rw-r--r--cps-service/src/main/java/org/onap/cps/events/CpsDataUpdateEventsService.java11
-rw-r--r--cps-service/src/main/java/org/onap/cps/impl/CpsNotificationServiceImpl.java140
-rw-r--r--cps-service/src/main/java/org/onap/cps/init/CpsNotificationSubscriptionModelLoader.java2
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/events/CpsDataUpdateEventsServiceSpec.groovy10
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/impl/CpsNotificationServiceImplSpec.groovy166
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/init/CpsNotificationSubscriptionModelLoaderSpec.groovy8
-rw-r--r--cps-service/src/test/resources/cps-notification-subscriptions@2024-07-03.yang48
-rw-r--r--docs/api/swagger/cps/openapi.yaml224
15 files changed, 821 insertions, 20 deletions
diff --git a/cps-rest/docs/openapi/components.yml b/cps-rest/docs/openapi/components.yml
index 1a7e4308d9..43a311872a 100644
--- a/cps-rest/docs/openapi/components.yml
+++ b/cps-rest/docs/openapi/components.yml
@@ -1,7 +1,7 @@
# ============LICENSE_START=======================================================
# Copyright (c) 2021-2022 Bell Canada.
# Modifications Copyright (C) 2021-2023 Nordix Foundation
-# Modifications Copyright (C) 2022-2024 TechMahindra Ltd.
+# Modifications Copyright (C) 2022-2025 TechMahindra Ltd.
# Modifications Copyright (C) 2022 Deutsche Telekom AG
# ================================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -157,7 +157,12 @@ components:
name: "Funny"
target-data:
name: "Comic"
-
+ NotificationSubscriptionsDataSample:
+ value:
+ cps-notification-subscriptions:dataspaces:
+ dataspace:
+ - name: dataspace01
+ - name: dataspace02
parameters:
dataspaceNameInQuery:
name: dataspace-name
@@ -236,6 +241,19 @@ components:
value: /shops/bookstore
list attributes xpath:
value: /shops/bookstore/categories[@code=1]
+ notificationSubscriptionXpathInQuery:
+ name: xpath
+ in: query
+ description: For more details on xpath, please refer https://docs.onap.org/projects/onap-cps/en/latest/xpath.html
+ required: true
+ schema:
+ type: string
+ default: /dataspaces
+ examples:
+ subscription by dataspace xpath:
+ value: /dataspaces/dataspace[@name='dataspace01']
+ subscription by anchor xpath:
+ value: /dataspaces/dataspace[@name='dataspace01']/anchors/anchor[@name='anchor01']
requiredXpathInQuery:
name: xpath
in: query
diff --git a/cps-rest/docs/openapi/cpsAdminV2.yml b/cps-rest/docs/openapi/cpsAdminV2.yml
index e501ad8b15..af2572a1f0 100644
--- a/cps-rest/docs/openapi/cpsAdminV2.yml
+++ b/cps-rest/docs/openapi/cpsAdminV2.yml
@@ -1,5 +1,5 @@
# ============LICENSE_START=======================================================
-# Copyright (C) 2022 TechMahindra Ltd.
+# Copyright (C) 2022-2025 TechMahindra Ltd.
# ================================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -87,3 +87,75 @@ schemaSet:
$ref: 'components.yml#/components/responses/Conflict'
'500':
$ref: 'components.yml#/components/responses/InternalServerError'
+
+notificationSubscription:
+ get:
+ description: Get cps notification subscription
+ tags:
+ - cps-admin
+ summary: Get cps notification subscription
+ operationId: getNotificationSubscription
+ parameters:
+ - $ref: 'components.yml#/components/parameters/notificationSubscriptionXpathInQuery'
+ responses:
+ '200':
+ description: OK
+ content:
+ application/json:
+ schema:
+ $ref: 'components.yml#/components/examples/NotificationSubscriptionsDataSample'
+ '400':
+ $ref: 'components.yml#/components/responses/BadRequest'
+ '403':
+ $ref: 'components.yml#/components/responses/Forbidden'
+ '409':
+ $ref: 'components.yml#/components/responses/Conflict'
+ '500':
+ $ref: 'components.yml#/components/responses/InternalServerError'
+ post:
+ description: Create cps notification subscription
+ tags:
+ - cps-admin
+ summary: Create cps notification subscription
+ operationId: createNotificationSubscription
+ parameters:
+ - $ref: 'components.yml#/components/parameters/notificationSubscriptionXpathInQuery'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ examples:
+ dataSample:
+ $ref: 'components.yml#/components/examples/NotificationSubscriptionsDataSample'
+ responses:
+ '201':
+ $ref: 'components.yml#/components/responses/CreatedV2'
+ '400':
+ $ref: 'components.yml#/components/responses/BadRequest'
+ '403':
+ $ref: 'components.yml#/components/responses/Forbidden'
+ '409':
+ $ref: 'components.yml#/components/responses/Conflict'
+ '500':
+ $ref: 'components.yml#/components/responses/InternalServerError'
+ delete:
+ description: Delete cps notification subscription
+ tags:
+ - cps-admin
+ summary: Delete cps notification subscription
+ operationId: deleteNotificationSubscription
+ parameters:
+ - $ref: 'components.yml#/components/parameters/notificationSubscriptionXpathInQuery'
+ responses:
+ '204':
+ $ref: 'components.yml#/components/responses/NoContent'
+ '400':
+ $ref: 'components.yml#/components/responses/BadRequest'
+ '403':
+ $ref: 'components.yml#/components/responses/Forbidden'
+ '409':
+ $ref: 'components.yml#/components/responses/Conflict'
+ '500':
+ $ref: 'components.yml#/components/responses/InternalServerError' \ No newline at end of file
diff --git a/cps-rest/docs/openapi/openapi.yml b/cps-rest/docs/openapi/openapi.yml
index c85bf7cac7..09c454b1da 100644
--- a/cps-rest/docs/openapi/openapi.yml
+++ b/cps-rest/docs/openapi/openapi.yml
@@ -2,7 +2,7 @@
# Copyright (C) 2021-2025 Nordix Foundation
# Modifications Copyright (C) 2021 Pantheon.tech
# Modifications Copyright (C) 2021 Bell Canada.
-# Modifications Copyright (C) 2022-2024 TechMahindra Ltd.
+# Modifications Copyright (C) 2022-2025 TechMahindra Ltd.
# ================================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -115,5 +115,8 @@ paths:
/v2/dataspaces/{dataspace-name}/nodes/query:
$ref: 'cpsQueryV2.yml#/nodesByDataspaceAndCpsPath'
+ /v2/notification-subscription:
+ $ref: 'cpsAdminV2.yml#/notificationSubscription'
+
security:
- basicAuth: []
diff --git a/cps-rest/src/main/java/org/onap/cps/rest/controller/AdminRestController.java b/cps-rest/src/main/java/org/onap/cps/rest/controller/AdminRestController.java
index 4c6bd6cdc5..01a9746af0 100755
--- a/cps-rest/src/main/java/org/onap/cps/rest/controller/AdminRestController.java
+++ b/cps-rest/src/main/java/org/onap/cps/rest/controller/AdminRestController.java
@@ -3,7 +3,7 @@
* Copyright (C) 2020-2025 Nordix Foundation
* Modifications Copyright (C) 2020-2021 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
- * Modifications Copyright (C) 2022 TechMahindra Ltd.
+ * Modifications Copyright (C) 2022-2025 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,11 +31,13 @@ import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.onap.cps.api.CpsAnchorService;
import org.onap.cps.api.CpsDataspaceService;
import org.onap.cps.api.CpsModuleService;
+import org.onap.cps.api.CpsNotificationService;
import org.onap.cps.api.model.Anchor;
import org.onap.cps.api.model.Dataspace;
import org.onap.cps.api.model.SchemaSet;
@@ -43,6 +45,7 @@ import org.onap.cps.rest.api.CpsAdminApi;
import org.onap.cps.rest.model.AnchorDetails;
import org.onap.cps.rest.model.DataspaceDetails;
import org.onap.cps.rest.model.SchemaSetDetails;
+import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -58,6 +61,8 @@ public class AdminRestController implements CpsAdminApi {
private final CpsModuleService cpsModuleService;
private final CpsRestInputMapper cpsRestInputMapper;
private final CpsAnchorService cpsAnchorService;
+ private final CpsNotificationService cpsNotificationService;
+ private final JsonObjectMapper jsonObjectMapper;
/**
* Create a dataspace.
@@ -280,4 +285,25 @@ public class AdminRestController implements CpsAdminApi {
final DataspaceDetails dataspaceDetails = cpsRestInputMapper.toDataspaceDetails(dataspace);
return new ResponseEntity<>(dataspaceDetails, HttpStatus.OK);
}
+
+ @Override
+ public ResponseEntity<Void> createNotificationSubscription(final String xpath,
+ final Object notificationSubscriptionAsJson) {
+ cpsNotificationService.createNotificationSubscription(
+ jsonObjectMapper.asJsonString(notificationSubscriptionAsJson), xpath);
+ return new ResponseEntity<>(HttpStatus.CREATED);
+ }
+
+ @Override
+ public ResponseEntity<Void> deleteNotificationSubscription(final String xpath) {
+ cpsNotificationService.deleteNotificationSubscription(xpath);
+ return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+ }
+
+ @Override
+ public ResponseEntity<Object> getNotificationSubscription(final String xpath) {
+ final List<Map<String, Object>> dataMaps = cpsNotificationService.getNotificationSubscription(xpath);
+ return new ResponseEntity<>(jsonObjectMapper.asJsonString(dataMaps), HttpStatus.OK);
+ }
+
}
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 0d189783fd..6d1ca40cd9 100755
--- 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
@@ -3,7 +3,7 @@
* Copyright (C) 2020-2021 Pantheon.tech
* Modifications Copyright (C) 2020-2021 Bell Canada.
* Modifications Copyright (C) 2021-2025 Nordix Foundation
- * Modifications Copyright (C) 2022 TechMahindra Ltd.
+ * Modifications Copyright (C) 2022-2025 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,15 +23,26 @@
package org.onap.cps.rest.controller
+import com.fasterxml.jackson.databind.ObjectMapper
+
+import static org.onap.cps.api.parameters.CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put
+
import org.mapstruct.factory.Mappers
import org.onap.cps.api.CpsAnchorService
import org.onap.cps.api.CpsDataspaceService
import org.onap.cps.api.CpsModuleService
+import org.onap.cps.api.CpsNotificationService
import org.onap.cps.api.exceptions.AlreadyDefinedException
import org.onap.cps.api.exceptions.SchemaSetInUseException
import org.onap.cps.api.model.Anchor
import org.onap.cps.api.model.Dataspace
import org.onap.cps.api.model.SchemaSet
+import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
@@ -63,8 +74,15 @@ class AdminRestControllerSpec extends Specification {
CpsAnchorService mockCpsAnchorService = Mock()
@SpringBean
+ CpsNotificationService mockCpsNotificationService = Mock()
+
+ @SpringBean
CpsRestInputMapper cpsRestInputMapper = Mappers.getMapper(CpsRestInputMapper)
+ @SpringBean
+ JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+
+
@Autowired
MockMvc mvc
@@ -393,6 +411,48 @@ class AdminRestControllerSpec extends Specification {
response.status == HttpStatus.NO_CONTENT.value()
}
+ def 'Add notification subscription'() {
+ given: 'an endpoint and its payload'
+ def notificationSubscriptionEndpoint = "$basePath/v2/notification-subscription"
+ def xpath = '/dataspaces'
+ def jsonPayload = '{"dataspace":[{"name":"ds01"}]}'
+ when: 'post request is performed'
+ def response =
+ mvc.perform(
+ post(notificationSubscriptionEndpoint)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(jsonPayload))
+ .andReturn().response
+ then: 'notification service method is invoked with expected parameter'
+ 1 * mockCpsNotificationService.createNotificationSubscription(jsonPayload, xpath)
+ and: 'HTTP response code indicates success'
+ response.status == HttpStatus.CREATED.value()
+ }
+
+ def 'delete notification subscription'() {
+ given: 'an endpoint and xpath'
+ def notificationSubscriptionEndpoint = "$basePath/v2/notification-subscription"
+ def xpath = '/dataspaces'
+ when: 'delete request is performed'
+ def response = mvc.perform(delete(notificationSubscriptionEndpoint).param('xpath', xpath)).andReturn().response
+ then: 'notification service method is invoked with expected parameter'
+ 1 * mockCpsNotificationService.deleteNotificationSubscription(xpath)
+ and: 'HTTP response code indicates success'
+ response.status == HttpStatus.NO_CONTENT.value()
+ }
+
+ def 'Get notification subscription.'() {
+ given: 'an endpoint and xpath'
+ def notificationSubscriptionEndpoint = "$basePath/v2/notification-subscription"
+ def xpath = '/dataspaces'
+ when: 'get notification subscription is invoked'
+ def response = mvc.perform(get(notificationSubscriptionEndpoint).param('xpath', xpath)).andReturn().response
+ then: 'HTTP response code indicates success'
+ response.status == HttpStatus.OK.value()
+ and: 'notification service is called with proper parameters'
+ 1 * mockCpsNotificationService.getNotificationSubscription(xpath)
+ }
+
def createMultipartFile(filename, content) {
return new MockMultipartFile("file", filename, "text/plain", content.getBytes())
}
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 f0fc4cca62..4e1d27cda2 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
@@ -3,7 +3,7 @@
* Copyright (C) 2020 Pantheon.tech
* Modifications Copyright (C) 2021-2023 Nordix Foundation
* Modifications Copyright (C) 2021 Bell Canada.
- * Modifications Copyright (C) 2022 TechMahindra Ltd.
+ * Modifications Copyright (C) 2022-2025 TechMahindra Ltd.
* Modifications Copyright (C) 2022 Deutsche Telekom AG
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,6 +30,7 @@ import org.onap.cps.api.CpsDataspaceService
import org.onap.cps.api.CpsAnchorService
import org.onap.cps.api.CpsDataService
import org.onap.cps.api.CpsModuleService
+import org.onap.cps.api.CpsNotificationService
import org.onap.cps.api.CpsQueryService
import org.onap.cps.rest.controller.CpsRestInputMapper
import org.onap.cps.api.exceptions.AlreadyDefinedException
@@ -87,6 +88,9 @@ class CpsRestExceptionHandlerSpec extends Specification {
@SpringBean
PrefixResolver prefixResolver = Mock()
+ @SpringBean
+ CpsNotificationService mockCpsNotificationService = Mock()
+
@Autowired
MockMvc mvc
diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsNotificationService.java b/cps-service/src/main/java/org/onap/cps/api/CpsNotificationService.java
new file mode 100644
index 0000000000..ae437753c0
--- /dev/null
+++ b/cps-service/src/main/java/org/onap/cps/api/CpsNotificationService.java
@@ -0,0 +1,35 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025 TechMahindra Ltd.
+ * ================================================================================
+ * 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;
+
+import java.util.List;
+import java.util.Map;
+
+public interface CpsNotificationService {
+
+ void createNotificationSubscription(String notificationSubscriptionAsJson, String xpath);
+
+ void deleteNotificationSubscription(String xpath);
+
+ boolean isNotificationEnabled(String dataspaceName, String anchorName);
+
+ List<Map<String, Object>> getNotificationSubscription(String xpath);
+}
diff --git a/cps-service/src/main/java/org/onap/cps/events/CpsDataUpdateEventsService.java b/cps-service/src/main/java/org/onap/cps/events/CpsDataUpdateEventsService.java
index f1b5ff8d10..50441adac5 100644
--- a/cps-service/src/main/java/org/onap/cps/events/CpsDataUpdateEventsService.java
+++ b/cps-service/src/main/java/org/onap/cps/events/CpsDataUpdateEventsService.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2024 TechMahindra Ltd.
+ * Copyright (C) 2024-2025 TechMahindra Ltd.
* Copyright (C) 2024 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,6 +28,7 @@ import java.util.HashMap;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.api.CpsNotificationService;
import org.onap.cps.api.model.Anchor;
import org.onap.cps.events.model.CpsDataUpdatedEvent;
import org.onap.cps.events.model.Data;
@@ -43,6 +44,8 @@ public class CpsDataUpdateEventsService {
private final EventsPublisher<CpsDataUpdatedEvent> eventsPublisher;
+ private final CpsNotificationService cpsNotificationService;
+
@Value("${app.cps.data-updated.topic:cps-data-updated-events}")
private String topicName;
@@ -63,7 +66,7 @@ public class CpsDataUpdateEventsService {
@Timed(value = "cps.dataupdate.events.publish", description = "Time taken to publish Data Update event")
public void publishCpsDataUpdateEvent(final Anchor anchor, final String xpath,
final Operation operation, final OffsetDateTime observedTimestamp) {
- if (notificationsEnabled && cpsChangeEventNotificationsEnabled) {
+ if (notificationsEnabled && cpsChangeEventNotificationsEnabled && isNotificationEnabledForAnchor(anchor)) {
final CpsDataUpdatedEvent cpsDataUpdatedEvent = createCpsDataUpdatedEvent(anchor,
observedTimestamp, xpath, operation);
final String updateEventId = anchor.getDataspaceName() + ":" + anchor.getName();
@@ -78,6 +81,10 @@ public class CpsDataUpdateEventsService {
}
}
+ private boolean isNotificationEnabledForAnchor(final Anchor anchor) {
+ return cpsNotificationService.isNotificationEnabled(anchor.getDataspaceName(), anchor.getName());
+ }
+
private CpsDataUpdatedEvent createCpsDataUpdatedEvent(final Anchor anchor, final OffsetDateTime observedTimestamp,
final String xpath,
final Operation rootNodeOperation) {
diff --git a/cps-service/src/main/java/org/onap/cps/impl/CpsNotificationServiceImpl.java b/cps-service/src/main/java/org/onap/cps/impl/CpsNotificationServiceImpl.java
new file mode 100644
index 0000000000..5030ad04c6
--- /dev/null
+++ b/cps-service/src/main/java/org/onap/cps/impl/CpsNotificationServiceImpl.java
@@ -0,0 +1,140 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025 TechMahindra Ltd.
+ * ================================================================================
+ * 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.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.api.CpsAnchorService;
+import org.onap.cps.api.CpsNotificationService;
+import org.onap.cps.api.exceptions.DataNodeNotFoundException;
+import org.onap.cps.api.model.Anchor;
+import org.onap.cps.api.model.DataNode;
+import org.onap.cps.api.parameters.FetchDescendantsOption;
+import org.onap.cps.cpspath.parser.CpsPathUtil;
+import org.onap.cps.spi.CpsDataPersistenceService;
+import org.onap.cps.utils.ContentType;
+import org.onap.cps.utils.DataMapUtils;
+import org.onap.cps.utils.PrefixResolver;
+import org.onap.cps.utils.YangParser;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class CpsNotificationServiceImpl implements CpsNotificationService {
+
+ private final CpsAnchorService cpsAnchorService;
+
+ private final CpsDataPersistenceService cpsDataPersistenceService;
+
+ private final YangParser yangParser;
+
+ private final PrefixResolver prefixResolver;
+
+ private static final String ADMIN_DATASPACE = "CPS-Admin";
+ private static final String ANCHOR_NAME = "cps-notification-subscriptions";
+ private static final String DATASPACE_SUBSCRIPTION_XPATH_FORMAT = "/dataspaces/dataspace[@name='%s']";
+ private static final String ANCHORS_SUBSCRIPTION_XPATH_FORMAT = "/dataspaces/dataspace[@name='%s']/anchors";
+ private static final String ANCHOR_SUBSCRIPTION_XPATH_FORMAT =
+ "/dataspaces/dataspace[@name='%s']/anchors/anchor[@name='%s']";
+
+ @Override
+ public void createNotificationSubscription(final String notificationSubscriptionAsJson, final String xpath) {
+
+ final Anchor anchor = cpsAnchorService.getAnchor(ADMIN_DATASPACE, ANCHOR_NAME);
+ final Collection<DataNode> dataNodes =
+ buildDataNodesWithParentNodeXpath(anchor, xpath, notificationSubscriptionAsJson, ContentType.JSON);
+ cpsDataPersistenceService.addListElements(ADMIN_DATASPACE, ANCHOR_NAME, xpath,
+ dataNodes);
+ }
+
+ @Override
+ public void deleteNotificationSubscription(final String xpath) {
+ cpsDataPersistenceService.deleteDataNode(ADMIN_DATASPACE, ANCHOR_NAME, xpath);
+ }
+
+ @Override
+ public List<Map<String, Object>> getNotificationSubscription(final String xpath) {
+ final Collection<DataNode> dataNodes =
+ cpsDataPersistenceService.getDataNodes(ADMIN_DATASPACE, ANCHOR_NAME, xpath,
+ FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS);
+ final List<Map<String, Object>> dataMaps = new ArrayList<>(dataNodes.size());
+ final Anchor anchor = cpsAnchorService.getAnchor(ADMIN_DATASPACE, ANCHOR_NAME);
+ for (final DataNode dataNode: dataNodes) {
+ final String prefix = prefixResolver.getPrefix(anchor, dataNode.getXpath());
+ final Map<String, Object> dataMap = DataMapUtils.toDataMapWithIdentifier(dataNode, prefix);
+ dataMaps.add(dataMap);
+ }
+ return dataMaps;
+ }
+
+ @Override
+ public boolean isNotificationEnabled(final String dataspaceName, final String anchorName) {
+ return (isNotificationEnabledForAnchor(dataspaceName, anchorName)
+ || notificationEnabledForAllAnchors(dataspaceName));
+ }
+
+ private boolean isNotificationEnabledForAnchor(final String dataspaceName, final String anchorName) {
+ final String xpath = String.format(ANCHOR_SUBSCRIPTION_XPATH_FORMAT, dataspaceName, anchorName);
+ return isNotificationEnabledForXpath(xpath);
+ }
+
+ private boolean isNotificationEnabledForXpath(final String xpath) {
+ try {
+ cpsDataPersistenceService.getDataNodes(ADMIN_DATASPACE, ANCHOR_NAME, xpath,
+ FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS);
+ } catch (final DataNodeNotFoundException e) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean notificationEnabledForAllAnchors(final String dataspaceName) {
+ final String dataspaceSubscriptionXpath = String.format(DATASPACE_SUBSCRIPTION_XPATH_FORMAT, dataspaceName);
+ return (isNotificationEnabledForXpath(dataspaceSubscriptionXpath)
+ && noIndividualAnchorEnabledInDataspace(dataspaceName));
+ }
+
+ private boolean noIndividualAnchorEnabledInDataspace(final String dataspaceName) {
+ final String xpathForAnchors = String.format(ANCHORS_SUBSCRIPTION_XPATH_FORMAT, dataspaceName);
+ return !isNotificationEnabledForXpath(xpathForAnchors);
+ }
+
+
+ private Collection<DataNode> buildDataNodesWithParentNodeXpath(final Anchor anchor, final String parentNodeXpath,
+ final String nodeData,
+ final ContentType contentType) {
+
+ final String normalizedParentNodeXpath = CpsPathUtil.getNormalizedXpath(parentNodeXpath);
+ final ContainerNode containerNode =
+ yangParser.parseData(contentType, nodeData, anchor, normalizedParentNodeXpath);
+ final Collection<DataNode> dataNodes = new DataNodeBuilder()
+ .withParentNodeXpath(normalizedParentNodeXpath)
+ .withContainerNode(containerNode)
+ .buildCollection();
+ return dataNodes;
+ }
+} \ No newline at end of file
diff --git a/cps-service/src/main/java/org/onap/cps/init/CpsNotificationSubscriptionModelLoader.java b/cps-service/src/main/java/org/onap/cps/init/CpsNotificationSubscriptionModelLoader.java
index 0b7d1609ff..bf60f8d49a 100644
--- a/cps-service/src/main/java/org/onap/cps/init/CpsNotificationSubscriptionModelLoader.java
+++ b/cps-service/src/main/java/org/onap/cps/init/CpsNotificationSubscriptionModelLoader.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2024 TechMahindra Ltd.
+ * Copyright (C) 2024-2025 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/cps-service/src/test/groovy/org/onap/cps/events/CpsDataUpdateEventsServiceSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/events/CpsDataUpdateEventsServiceSpec.groovy
index 5dee8fc28b..6d9ff12060 100644
--- a/cps-service/src/test/groovy/org/onap/cps/events/CpsDataUpdateEventsServiceSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/events/CpsDataUpdateEventsServiceSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2024 TechMahindra Ltd.
+ * Copyright (C) 2024-2025 TechMahindra Ltd.
* Copyright (C) 2024 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,6 +25,7 @@ import static org.onap.cps.events.model.Data.Operation.CREATE
import static org.onap.cps.events.model.Data.Operation.DELETE
import static org.onap.cps.events.model.Data.Operation.UPDATE
+import org.onap.cps.api.CpsNotificationService
import com.fasterxml.jackson.databind.ObjectMapper
import io.cloudevents.CloudEvent
import io.cloudevents.core.CloudEventUtils
@@ -41,8 +42,13 @@ import java.time.OffsetDateTime
class CpsDataUpdateEventsServiceSpec extends Specification {
def mockEventsPublisher = Mock(EventsPublisher)
def objectMapper = new ObjectMapper();
+ def mockCpsNotificationService = Mock(CpsNotificationService)
- def objectUnderTest = new CpsDataUpdateEventsService(mockEventsPublisher)
+ def objectUnderTest = new CpsDataUpdateEventsService(mockEventsPublisher, mockCpsNotificationService)
+
+ def setup() {
+ mockCpsNotificationService.isNotificationEnabled('dataspace01', 'anchor01') >> true
+ }
def 'Create and Publish cps update event where events are #scenario'() {
given: 'an anchor, operation and observed timestamp'
diff --git a/cps-service/src/test/groovy/org/onap/cps/impl/CpsNotificationServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/impl/CpsNotificationServiceImplSpec.groovy
new file mode 100644
index 0000000000..0f563272d1
--- /dev/null
+++ b/cps-service/src/test/groovy/org/onap/cps/impl/CpsNotificationServiceImplSpec.groovy
@@ -0,0 +1,166 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025 TechMahindra Ltd.
+ * ================================================================================
+ * 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.impl
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import org.onap.cps.api.CpsAnchorService
+import org.onap.cps.api.exceptions.DataNodeNotFoundException
+import org.onap.cps.api.exceptions.DataValidationException
+import org.onap.cps.api.model.Anchor
+import org.onap.cps.api.parameters.FetchDescendantsOption;
+import org.onap.cps.spi.CpsDataPersistenceService
+import org.onap.cps.utils.JsonObjectMapper
+import org.onap.cps.utils.PrefixResolver
+import org.onap.cps.utils.YangParser
+import org.onap.cps.TestUtils
+import org.onap.cps.utils.YangParserHelper
+import org.onap.cps.yang.TimedYangTextSchemaSourceSetBuilder
+import org.onap.cps.yang.YangTextSchemaSourceSet
+import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
+import org.springframework.test.context.ContextConfiguration
+
+import spock.lang.Specification
+
+@ContextConfiguration(classes = [ObjectMapper, JsonObjectMapper])
+class CpsNotificationServiceImplSpec extends Specification {
+
+ def dataspaceName = 'CPS-Admin'
+ def anchorName = 'cps-notification-subscriptions'
+ def schemaSetName = 'cps-notification-subscriptions'
+ def anchor = new Anchor(anchorName, dataspaceName, schemaSetName)
+
+ def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService)
+ def mockCpsAnchorService = Mock(CpsAnchorService)
+ def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
+ def mockTimedYangTextSchemaSourceSetBuilder = Mock(TimedYangTextSchemaSourceSetBuilder)
+ def yangParser = new YangParser(new YangParserHelper(), mockYangTextSchemaSourceSetCache, mockTimedYangTextSchemaSourceSetBuilder)
+ def mockPrefixResolver = Mock(PrefixResolver)
+ def objectUnderTest = new CpsNotificationServiceImpl(mockCpsAnchorService, mockCpsDataPersistenceService, yangParser, mockPrefixResolver)
+
+ def 'add notification subscription for list of dataspaces'() {
+ given: 'details for notification subscription and subscription root node xpath'
+ def notificationSubscriptionAsjson = '{"dataspace":[{"name":"ds01"},{"name":"ds02"}]}'
+ def xpath = '/dataspaces'
+ and: 'schema set for given anchor and dataspace references notification subscription model'
+ setupSchemaSetMocks('cps-notification-subscriptions@2024-07-03.yang')
+ and: 'anchor is provided'
+ mockCpsAnchorService.getAnchor(dataspaceName, anchorName) >> anchor
+ when: 'create notification subscription is called'
+ objectUnderTest.createNotificationSubscription(notificationSubscriptionAsjson, xpath)
+ then: 'the persistence service is called once with the correct parameters'
+ 1 * mockCpsDataPersistenceService.addListElements('CPS-Admin', 'cps-notification-subscriptions', xpath, { dataNodeCollection ->
+ {
+ assert dataNodeCollection.size() == 2
+ assert dataNodeCollection.collect { it.getXpath() }
+ .containsAll(['/dataspaces/dataspace[@name=\'ds01\']', '/dataspaces/dataspace[@name=\'ds02\']'])
+ }
+ })
+ }
+
+ def 'add notification subscription fails with exception'() {
+ given: 'details for notification subscription'
+ def jsonData = '{"dataspace":[{"name":"ds01"},{"name":"ds02"}]}'
+ and: 'schema set for given anchor and dataspace references invalid data model'
+ setupSchemaSetMocks('test-tree.yang')
+ and: 'anchor is provided'
+ mockCpsAnchorService.getAnchor(dataspaceName, anchorName) >> anchor
+ when: 'create notification subscription is called'
+ objectUnderTest.createNotificationSubscription(jsonData, '/somepath')
+ then: 'data validation exception is thrown '
+ thrown(DataValidationException)
+ }
+
+ def 'delete notification subscription for given xpath'() {
+ given: 'details for notification subscription'
+ def xpath = '/some/path'
+ when: 'delete notification subscription is called'
+ objectUnderTest.deleteNotificationSubscription(xpath)
+ then: 'the persistence service is called once with the correct parameters'
+ 1 * mockCpsDataPersistenceService.deleteDataNode(dataspaceName, anchorName, xpath)
+ }
+
+ def 'get notification subscription for given xpath'() {
+ given: 'details for notification subscription'
+ def xpath = '/some/path'
+ and: 'persistence service returns data nodes for subscribed data'
+ mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName,
+ xpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >>
+ [new DataNodeBuilder().withXpath('/some/path').withLeaves([leaf: 'dataspace', leafList: ['ds01', 'ds02']]).build()]
+ when: 'delete notification subscription is called'
+ def result = objectUnderTest.getNotificationSubscription(xpath)
+ then: 'the result is a json representation of the data node(s) returned by the data persistence service'
+ assert result.get(0).toString() == '{path={leaf=dataspace, leafList=[ds01, ds02]}}'
+ }
+
+ def 'is notification enabled for given anchor'() {
+ given: 'data nodes available for given anchor'
+ mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName, "/dataspaces", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >>
+ [new DataNodeBuilder().withXpath('/xpath-1').build()]
+ when: 'is notification enabled is called'
+ boolean isNotificationEnabled = objectUnderTest.isNotificationEnabled(dataspaceName, anchorName)
+ then: 'the notification is enabled'
+ assert isNotificationEnabled
+ }
+
+ def 'is notification disabled for given anchor'() {
+ given: 'data nodes not available for given anchor'
+ mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName, "/dataspaces/dataspace[@name='ds01']/anchors/anchor[@name='anchor-01']", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >>
+ { throw new DataNodeNotFoundException(dataspaceName, anchorName) }
+ when: 'is notification enabled is called'
+ boolean isNotificationEnabled = objectUnderTest.isNotificationEnabled('ds01', 'anchor-01')
+ then: 'the notification is disabled'
+ assert !isNotificationEnabled
+ }
+
+ def 'is notification enabled for all anchors in a dataspace'() {
+ given: 'data nodes available for given dataspace'
+ mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName, "/dataspaces/dataspace[@name='ds01']", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >>
+ [new DataNodeBuilder().withXpath('/xpath-1').build()]
+ and: 'data nodes not available for any specific anchor'
+ mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName, "/dataspaces/dataspace[@name='ds01']/anchors", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >>
+ { throw new DataNodeNotFoundException(dataspaceName, anchorName) }
+ when: 'is notification enabled is called'
+ boolean isNotificationEnabled = objectUnderTest.notificationEnabledForAllAnchors('ds01')
+ then: 'the notification is enabled'
+ assert isNotificationEnabled
+ }
+
+ def 'is notification disabled for all anchors in a dataspace'() {
+ given: 'data nodes available for given dataspace'
+ mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName, "/dataspaces/dataspace[@name='ds01']", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >>
+ [new DataNodeBuilder().withXpath('/xpath-1').build()]
+ and: 'data nodes also available for any specific anchor'
+ mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName, "/dataspaces/dataspace[@name='ds01']/anchors", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >>
+ [new DataNodeBuilder().withXpath('/xpath-1').build()]
+ when: 'is notification enabled is called'
+ boolean isNotificationEnabled = objectUnderTest.notificationEnabledForAllAnchors('ds01')
+ then: 'the notification is disabled'
+ assert !isNotificationEnabled
+ }
+
+ def setupSchemaSetMocks(String... yangResources) {
+ def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet)
+ mockYangTextSchemaSourceSetCache.get(dataspaceName, schemaSetName) >> mockYangTextSchemaSourceSet
+ def yangResourceNameToContent = TestUtils.getYangResourcesAsMap(yangResources)
+ def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent).getSchemaContext()
+ mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext
+ }
+}
diff --git a/cps-service/src/test/groovy/org/onap/cps/init/CpsNotificationSubscriptionModelLoaderSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/init/CpsNotificationSubscriptionModelLoaderSpec.groovy
index 0d515f90ac..1e2dc54424 100644
--- a/cps-service/src/test/groovy/org/onap/cps/init/CpsNotificationSubscriptionModelLoaderSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/init/CpsNotificationSubscriptionModelLoaderSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2024 TechMahindra Ltd.
+ * Copyright (C) 2024-2025 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -78,10 +78,4 @@ class CpsNotificationSubscriptionModelLoaderSpec extends Specification {
and: 'the data service to create a top level datanode is called once'
1 * mockCpsDataService.saveData(CPS_DATASPACE_NAME, ANCHOR_NAME, '{"dataspaces":{}}', _)
}
-
- private void assertLogContains(String message) {
- def logs = loggingListAppender.list.toString()
- assert logs.contains(message)
- }
-
}
diff --git a/cps-service/src/test/resources/cps-notification-subscriptions@2024-07-03.yang b/cps-service/src/test/resources/cps-notification-subscriptions@2024-07-03.yang
new file mode 100644
index 0000000000..1cab7923ea
--- /dev/null
+++ b/cps-service/src/test/resources/cps-notification-subscriptions@2024-07-03.yang
@@ -0,0 +1,48 @@
+module cps-notification-subscriptions {
+ yang-version 1.1;
+ namespace "org:onap:cps";
+
+ prefix cps-notification-subscriptions;
+
+ revision "2024-08-05" {
+ description
+ "First release of cps notification subscriptions model";
+ }
+ container dataspaces {
+
+ list dataspace {
+ key "name";
+
+ leaf name {
+ type string;
+ }
+
+ container anchors {
+
+ list anchor {
+ key "name";
+
+ leaf name {
+ type string;
+ }
+
+ container xpaths {
+
+ list xpath {
+ key "path";
+ leaf path {
+ type string;
+ }
+ }
+ }
+ }
+ }
+ leaf-list subscriptionIds {
+ type string;
+ }
+ leaf topic {
+ type string;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/docs/api/swagger/cps/openapi.yaml b/docs/api/swagger/cps/openapi.yaml
index 330c2ca7f7..154548797b 100644
--- a/docs/api/swagger/cps/openapi.yaml
+++ b/docs/api/swagger/cps/openapi.yaml
@@ -332,7 +332,7 @@ paths:
- cps-admin
/{apiVersion}/admin/dataspaces/{dataspace-name}/actions/clean:
post:
- description: Clean the dataspace (remove orphaned modules)
+ description: Clean the dataspace (remove orphaned schema sets and modules)
operationId: cleanDataspace
parameters:
- description: apiVersion
@@ -2562,6 +2562,208 @@ paths:
tags:
- cps-query
x-codegen-request-body-name: xpath
+ /v2/notification-subscription:
+ delete:
+ description: Delete cps notification subscription
+ operationId: deleteNotificationSubscription
+ parameters:
+ - description: "For more details on xpath, please refer https://docs.onap.org/projects/onap-cps/en/latest/xpath.html"
+ examples:
+ subscription by dataspace xpath:
+ value: "/dataspaces/dataspace[@name='dataspace01']"
+ subscription by anchor xpath:
+ value: "/dataspaces/dataspace[@name='dataspace01']/anchors/anchor[@name='anchor01']"
+ in: query
+ name: xpath
+ required: true
+ schema:
+ default: /dataspaces
+ type: string
+ responses:
+ "204":
+ content: {}
+ description: No Content
+ "400":
+ content:
+ application/json:
+ example:
+ status: 400
+ message: Bad Request
+ details: The provided request is not valid
+ schema:
+ $ref: '#/components/schemas/ErrorMessage'
+ description: Bad Request
+ "403":
+ content:
+ application/json:
+ example:
+ status: 403
+ message: Request Forbidden
+ details: This request is forbidden
+ schema:
+ $ref: '#/components/schemas/ErrorMessage'
+ description: Forbidden
+ "409":
+ content:
+ application/json:
+ example:
+ status: 409
+ message: Conflicting request
+ details: The request cannot be processed as the resource is in use.
+ schema:
+ $ref: '#/components/schemas/ErrorMessage'
+ description: Conflict
+ "500":
+ content:
+ application/json:
+ example:
+ status: 500
+ message: Internal Server Error
+ details: Internal Server Error occurred
+ schema:
+ $ref: '#/components/schemas/ErrorMessage'
+ description: Internal Server Error
+ summary: Delete cps notification subscription
+ tags:
+ - cps-admin
+ get:
+ description: Get cps notification subscription
+ operationId: getNotificationSubscription
+ parameters:
+ - description: "For more details on xpath, please refer https://docs.onap.org/projects/onap-cps/en/latest/xpath.html"
+ examples:
+ subscription by dataspace xpath:
+ value: "/dataspaces/dataspace[@name='dataspace01']"
+ subscription by anchor xpath:
+ value: "/dataspaces/dataspace[@name='dataspace01']/anchors/anchor[@name='anchor01']"
+ in: query
+ name: xpath
+ required: true
+ schema:
+ default: /dataspaces
+ type: string
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotificationSubscriptionsDataSample'
+ description: OK
+ "400":
+ content:
+ application/json:
+ example:
+ status: 400
+ message: Bad Request
+ details: The provided request is not valid
+ schema:
+ $ref: '#/components/schemas/ErrorMessage'
+ description: Bad Request
+ "403":
+ content:
+ application/json:
+ example:
+ status: 403
+ message: Request Forbidden
+ details: This request is forbidden
+ schema:
+ $ref: '#/components/schemas/ErrorMessage'
+ description: Forbidden
+ "409":
+ content:
+ application/json:
+ example:
+ status: 409
+ message: Conflicting request
+ details: The request cannot be processed as the resource is in use.
+ schema:
+ $ref: '#/components/schemas/ErrorMessage'
+ description: Conflict
+ "500":
+ content:
+ application/json:
+ example:
+ status: 500
+ message: Internal Server Error
+ details: Internal Server Error occurred
+ schema:
+ $ref: '#/components/schemas/ErrorMessage'
+ description: Internal Server Error
+ summary: Get cps notification subscription
+ tags:
+ - cps-admin
+ post:
+ description: Create cps notification subscription
+ operationId: createNotificationSubscription
+ parameters:
+ - description: "For more details on xpath, please refer https://docs.onap.org/projects/onap-cps/en/latest/xpath.html"
+ examples:
+ subscription by dataspace xpath:
+ value: "/dataspaces/dataspace[@name='dataspace01']"
+ subscription by anchor xpath:
+ value: "/dataspaces/dataspace[@name='dataspace01']/anchors/anchor[@name='anchor01']"
+ in: query
+ name: xpath
+ required: true
+ schema:
+ default: /dataspaces
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ dataSample:
+ $ref: '#/components/examples/NotificationSubscriptionsDataSample'
+ value: null
+ schema:
+ type: object
+ required: true
+ responses:
+ "201":
+ description: Created without response body
+ "400":
+ content:
+ application/json:
+ example:
+ status: 400
+ message: Bad Request
+ details: The provided request is not valid
+ schema:
+ $ref: '#/components/schemas/ErrorMessage'
+ description: Bad Request
+ "403":
+ content:
+ application/json:
+ example:
+ status: 403
+ message: Request Forbidden
+ details: This request is forbidden
+ schema:
+ $ref: '#/components/schemas/ErrorMessage'
+ description: Forbidden
+ "409":
+ content:
+ application/json:
+ example:
+ status: 409
+ message: Conflicting request
+ details: The request cannot be processed as the resource is in use.
+ schema:
+ $ref: '#/components/schemas/ErrorMessage'
+ description: Conflict
+ "500":
+ content:
+ application/json:
+ example:
+ status: 500
+ message: Internal Server Error
+ details: Internal Server Error occurred
+ schema:
+ $ref: '#/components/schemas/ErrorMessage'
+ description: Internal Server Error
+ summary: Create cps notification subscription
+ tags:
+ - cps-admin
components:
examples:
dataSample:
@@ -2615,6 +2817,12 @@ components:
name: SciFi
- code: 2
name: kids
+ NotificationSubscriptionsDataSample:
+ value:
+ cps-notification-subscriptions:dataspaces:
+ dataspace:
+ - name: dataspace01
+ - name: dataspace02
parameters:
dataspaceNameInQuery:
description: dataspace-name
@@ -2795,6 +3003,19 @@ components:
schema:
example: 10
type: integer
+ notificationSubscriptionXpathInQuery:
+ description: "For more details on xpath, please refer https://docs.onap.org/projects/onap-cps/en/latest/xpath.html"
+ examples:
+ subscription by dataspace xpath:
+ value: "/dataspaces/dataspace[@name='dataspace01']"
+ subscription by anchor xpath:
+ value: "/dataspaces/dataspace[@name='dataspace01']/anchors/anchor[@name='anchor01']"
+ in: query
+ name: xpath
+ required: true
+ schema:
+ default: /dataspaces
+ type: string
responses:
Created:
content:
@@ -2956,6 +3177,7 @@ components:
type: string
title: Module reference object
type: object
+ NotificationSubscriptionsDataSample: {}
getDeltaByDataspaceAnchorAndPayload_request:
properties:
json: