2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2023 Nordix Foundation
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.cps.ncmp.api.impl.deprecated.subscriptions;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.List;
27 import java.util.Optional;
28 import java.util.stream.Collectors;
29 import lombok.extern.slf4j.Slf4j;
30 import org.onap.cps.api.CpsDataService;
31 import org.onap.cps.api.CpsModuleService;
32 import org.onap.cps.ncmp.api.impl.inventory.NcmpPersistenceImpl;
33 import org.onap.cps.ncmp.api.impl.utils.DataNodeHelper;
34 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelSubscriptionEvent;
35 import org.onap.cps.spi.FetchDescendantsOption;
36 import org.onap.cps.spi.model.DataNode;
37 import org.onap.cps.spi.utils.CpsValidator;
38 import org.onap.cps.utils.JsonObjectMapper;
39 import org.springframework.stereotype.Component;
43 public class SubscriptionPersistenceImpl extends NcmpPersistenceImpl implements SubscriptionPersistence {
45 private static final String SUBSCRIPTION_ANCHOR_NAME = "AVC-Subscriptions";
46 private static final String SUBSCRIPTION_REGISTRY_PARENT = "/subscription-registry";
48 public SubscriptionPersistenceImpl(final JsonObjectMapper jsonObjectMapper, final CpsDataService cpsDataService,
49 final CpsModuleService cpsModuleService, final CpsValidator cpsValidator) {
50 super(jsonObjectMapper, cpsDataService, cpsModuleService, cpsValidator);
55 public void saveSubscriptionEvent(final YangModelSubscriptionEvent yangModelSubscriptionEvent) {
56 final String clientId = yangModelSubscriptionEvent.getClientId();
57 final String subscriptionName = yangModelSubscriptionEvent.getSubscriptionName();
59 final Collection<DataNode> dataNodes = cpsDataService.getDataNodes(NCMP_DATASPACE_NAME,
60 SUBSCRIPTION_ANCHOR_NAME, SUBSCRIPTION_REGISTRY_PARENT, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS);
62 if (isSubscriptionRegistryEmptyOrNonExist(dataNodes, clientId, subscriptionName)) {
63 saveSubscriptionEventYangModel(createSubscriptionEventJsonData(
64 jsonObjectMapper.asJsonString(yangModelSubscriptionEvent)));
66 findDeltaCmHandlesAddOrUpdateInDatabase(yangModelSubscriptionEvent, clientId, subscriptionName, dataNodes);
70 private void findDeltaCmHandlesAddOrUpdateInDatabase(final YangModelSubscriptionEvent yangModelSubscriptionEvent,
71 final String clientId, final String subscriptionName,
72 final Collection<DataNode> dataNodes) {
73 final Map<String, Map<String, String>> cmHandleIdToStatusAndDetailsAsMapNew =
74 extractCmHandleFromYangModelAsMap(yangModelSubscriptionEvent);
75 final Map<String, Map<String, String>> cmHandleIdToStatusAndDetailsAsMapOriginal =
76 DataNodeHelper.cmHandleIdToStatusAndDetailsAsMapFromDataNode(dataNodes);
78 final Map<String, Map<String, String>> newTargetCmHandles = mapDifference(cmHandleIdToStatusAndDetailsAsMapNew,
79 cmHandleIdToStatusAndDetailsAsMapOriginal);
80 traverseCmHandleList(newTargetCmHandles, clientId, subscriptionName, true);
82 final Map<String, Map<String, String>> existingTargetCmHandles =
83 mapDifference(cmHandleIdToStatusAndDetailsAsMapNew, newTargetCmHandles);
84 traverseCmHandleList(existingTargetCmHandles, clientId, subscriptionName, false);
87 private static Map<String, Map<String, String>> extractCmHandleFromYangModelAsMap(
88 final YangModelSubscriptionEvent yangModelSubscriptionEvent) {
89 return yangModelSubscriptionEvent.getPredicates().getTargetCmHandles()
92 (result, cmHandle) -> {
93 final String cmHandleId = cmHandle.getCmHandleId();
94 final SubscriptionStatus status = cmHandle.getStatus();
95 final String details = cmHandle.getDetails();
97 if (cmHandleId != null && status != null) {
98 result.put(cmHandleId, new HashMap<>());
99 result.get(cmHandleId).put("status", status.toString());
100 result.get(cmHandleId).put("details", details == null ? "" : details);
107 private void traverseCmHandleList(final Map<String, Map<String, String>> cmHandleMap,
108 final String clientId,
109 final String subscriptionName,
110 final boolean isAddListElementOperation) {
111 final List<YangModelSubscriptionEvent.TargetCmHandle> cmHandleList = targetCmHandlesAsList(cmHandleMap);
112 for (final YangModelSubscriptionEvent.TargetCmHandle targetCmHandle : cmHandleList) {
113 final String targetCmHandleAsJson =
114 createTargetCmHandleJsonData(jsonObjectMapper.asJsonString(targetCmHandle));
115 addOrReplaceCmHandlePredicateListElement(targetCmHandleAsJson, clientId, subscriptionName,
116 isAddListElementOperation);
120 private boolean isSubscriptionRegistryEmptyOrNonExist(final Collection<DataNode> dataNodes,
121 final String clientId, final String subscriptionName) {
122 final Optional<DataNode> dataNodeFirst = dataNodes.stream().findFirst();
123 return ((dataNodeFirst.isPresent() && dataNodeFirst.get().getChildDataNodes().isEmpty())
124 || getCmHandlesForSubscriptionEvent(clientId, subscriptionName).isEmpty());
127 private void addOrReplaceCmHandlePredicateListElement(final String targetCmHandleAsJson,
128 final String clientId,
129 final String subscriptionName,
130 final boolean isAddListElementOperation) {
131 if (isAddListElementOperation) {
132 log.info("targetCmHandleAsJson to be added into DB {}", targetCmHandleAsJson);
133 cpsDataService.saveListElements(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME,
134 createCmHandleXpathPredicates(clientId, subscriptionName), targetCmHandleAsJson, NO_TIMESTAMP);
136 log.info("targetCmHandleAsJson to be updated into DB {}", targetCmHandleAsJson);
137 cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME,
138 createCmHandleXpathPredicates(clientId, subscriptionName), targetCmHandleAsJson, NO_TIMESTAMP);
142 private void saveSubscriptionEventYangModel(final String subscriptionEventJsonData) {
143 log.info("SubscriptionEventJsonData to be saved into DB {}", subscriptionEventJsonData);
144 cpsDataService.saveListElements(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME,
145 SUBSCRIPTION_REGISTRY_PARENT, subscriptionEventJsonData, NO_TIMESTAMP);
149 public Collection<DataNode> getDataNodesForSubscriptionEvent() {
150 return cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME,
151 SUBSCRIPTION_REGISTRY_PARENT, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS);
155 public Collection<DataNode> getCmHandlesForSubscriptionEvent(final String clientId, final String subscriptionName) {
156 return cpsDataService.getDataNodesForMultipleXpaths(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME,
157 List.of(createCmHandleXpath(clientId, subscriptionName)),
158 FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS);
161 private static List<YangModelSubscriptionEvent.TargetCmHandle> targetCmHandlesAsList(
162 final Map<String, Map<String, String>> newCmHandles) {
163 return newCmHandles.entrySet().stream().map(entry -> {
164 final String cmHandleId = entry.getKey();
165 final Map<String, String> statusAndDetailsMap = entry.getValue();
166 final String status = statusAndDetailsMap.get("status");
167 final String details = statusAndDetailsMap.get("details");
168 return new YangModelSubscriptionEvent.TargetCmHandle(cmHandleId, SubscriptionStatus.fromString(status),
170 }).collect(Collectors.toList());
173 private static String createSubscriptionEventJsonData(final String yangModelSubscriptionAsJson) {
174 return "{\"subscription\":[" + yangModelSubscriptionAsJson + "]}";
177 private static String createTargetCmHandleJsonData(final String targetCmHandleAsJson) {
178 return "{\"targetCmHandles\":[" + targetCmHandleAsJson + "]}";
181 private static String createCmHandleXpathPredicates(final String clientId, final String subscriptionName) {
182 return "/subscription-registry/subscription[@clientID='" + clientId
183 + "' and @subscriptionName='" + subscriptionName + "']/predicates";
186 private static String createCmHandleXpath(final String clientId, final String subscriptionName) {
187 return "/subscription-registry/subscription[@clientID='" + clientId
188 + "' and @subscriptionName='" + subscriptionName + "']";
191 private static <K, L, M> Map<K, Map<L, M>> mapDifference(final Map<K, Map<L, M>> left,
192 final Map<K, Map<L, M>> right) {
193 final Map<K, Map<L, M>> difference = new HashMap<>();
194 difference.putAll(left);
195 difference.putAll(right);
196 difference.entrySet().removeAll(right.entrySet());