Use DB for checking Alternate IDs
[cps.git] / cps-ncmp-service / src / main / java / org / onap / cps / ncmp / api / impl / inventory / InventoryPersistenceImpl.java
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2022-2024 Nordix Foundation
4  *  Modifications Copyright (C) 2022 Bell Canada
5  *  Modifications Copyright (C) 2023 TechMahindra Ltd.
6  *  ================================================================================
7  *  Licensed under the Apache License, Version 2.0 (the "License");
8  *  you may not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS,
15  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  *
19  *  SPDX-License-Identifier: Apache-2.0
20  *  ============LICENSE_END=========================================================
21  */
22
23 package org.onap.cps.ncmp.api.impl.inventory;
24
25 import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS;
26
27 import com.google.common.collect.Lists;
28 import java.time.OffsetDateTime;
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 import lombok.extern.slf4j.Slf4j;
36 import org.onap.cps.api.CpsAnchorService;
37 import org.onap.cps.api.CpsDataService;
38 import org.onap.cps.api.CpsModuleService;
39 import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
40 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
41 import org.onap.cps.spi.FetchDescendantsOption;
42 import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
43 import org.onap.cps.spi.exceptions.DataValidationException;
44 import org.onap.cps.spi.model.DataNode;
45 import org.onap.cps.spi.model.ModuleDefinition;
46 import org.onap.cps.spi.model.ModuleReference;
47 import org.onap.cps.spi.utils.CpsValidator;
48 import org.onap.cps.utils.JsonObjectMapper;
49 import org.springframework.stereotype.Component;
50
51 @Slf4j
52 @Component
53 public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements InventoryPersistence {
54
55     private static final int CMHANDLE_BATCH_SIZE = 100;
56
57     private final CpsModuleService cpsModuleService;
58     private final CpsAnchorService cpsAnchorService;
59     private final CpsValidator cpsValidator;
60     private final CmHandleQueries cmHandleQueries;
61
62     /**
63      * initialize an inventory persistence object.
64      *
65      * @param jsonObjectMapper json mapper object
66      * @param cpsDataService   cps data service instance
67      * @param cpsModuleService cps module service instance
68      * @param cpsValidator     cps validation service instance
69      * @param cpsAnchorService  cps anchor service instance
70      */
71     public InventoryPersistenceImpl(final JsonObjectMapper jsonObjectMapper, final CpsDataService cpsDataService,
72                                     final CpsModuleService cpsModuleService, final CpsValidator cpsValidator,
73                                     final CpsAnchorService cpsAnchorService, final CmHandleQueries cmHandleQueries) {
74         super(jsonObjectMapper, cpsDataService, cpsModuleService, cpsValidator);
75         this.cpsModuleService = cpsModuleService;
76         this.cpsAnchorService = cpsAnchorService;
77         this.cpsValidator = cpsValidator;
78         this.cmHandleQueries = cmHandleQueries;
79     }
80
81
82     @Override
83     public CompositeState getCmHandleState(final String cmHandleId) {
84         final DataNode stateAsDataNode = cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
85                         getXPathForCmHandleById(cmHandleId) + "/state", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
86                 .iterator().next();
87         cpsValidator.validateNameCharacters(cmHandleId);
88         return new CompositeStateBuilder().fromDataNode(stateAsDataNode).build();
89     }
90
91     @Override
92     public void saveCmHandleState(final String cmHandleId, final CompositeState compositeState) {
93         final String cmHandleJsonData = createStateJsonData(jsonObjectMapper.asJsonString(compositeState));
94         cpsDataService.updateDataNodeAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
95                 getXPathForCmHandleById(cmHandleId), cmHandleJsonData, OffsetDateTime.now());
96     }
97
98     @Override
99     public void saveCmHandleStateBatch(final Map<String, CompositeState> cmHandleStatePerCmHandleId) {
100         final Map<String, String> cmHandlesJsonDataMap = new HashMap<>();
101         cmHandleStatePerCmHandleId.forEach((cmHandleId, compositeState) -> cmHandlesJsonDataMap.put(
102                 getXPathForCmHandleById(cmHandleId),
103                 createStateJsonData(jsonObjectMapper.asJsonString(compositeState))));
104         cpsDataService.updateDataNodesAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
105                 cmHandlesJsonDataMap, OffsetDateTime.now());
106     }
107
108     @Override
109     public YangModelCmHandle getYangModelCmHandle(final String cmHandleId) {
110         cpsValidator.validateNameCharacters(cmHandleId);
111         final DataNode dataNode = getCmHandleDataNodeByCmHandleId(cmHandleId).iterator().next();
112         return YangDataConverter.convertCmHandleToYangModel(dataNode, cmHandleId);
113     }
114
115     @Override
116     public Collection<YangModelCmHandle> getYangModelCmHandles(final Collection<String> cmHandleIds) {
117         final Collection<String> validCmHandleIds = new ArrayList<>(cmHandleIds.size());
118         cmHandleIds.forEach(cmHandleId -> {
119             try {
120                 cpsValidator.validateNameCharacters(cmHandleId);
121                 validCmHandleIds.add(cmHandleId);
122             } catch (final DataValidationException dataValidationException) {
123                 log.error("DataValidationException in CmHandleId {} to be ignored",
124                         dataValidationException.getMessage());
125             }
126         });
127         return YangDataConverter.convertDataNodesToYangModelCmHandles(getCmHandleDataNodes(validCmHandleIds));
128     }
129
130     @Override
131     public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleId(final String cmHandleId) {
132         return cpsModuleService.getModuleDefinitionsByAnchorName(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId);
133     }
134
135     @Override
136     public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleAndModule(final String cmHandleId,
137                                                                                 final String moduleName,
138                                                                                 final String moduleRevision) {
139         cpsValidator.validateNameCharacters(cmHandleId, moduleName);
140         return cpsModuleService.getModuleDefinitionsByAnchorAndModule(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
141                     cmHandleId, moduleName, moduleRevision);
142     }
143
144     @Override
145     public Collection<ModuleReference> getYangResourcesModuleReferences(final String cmHandleId) {
146         cpsValidator.validateNameCharacters(cmHandleId);
147         return cpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId);
148     }
149
150     @Override
151     public void saveCmHandle(final YangModelCmHandle yangModelCmHandle) {
152         saveCmHandleBatch(Collections.singletonList(yangModelCmHandle));
153     }
154
155     @Override
156     public void saveCmHandleBatch(final List<YangModelCmHandle> yangModelCmHandles) {
157         for (final List<YangModelCmHandle> yangModelCmHandleBatch :
158                 Lists.partition(yangModelCmHandles, CMHANDLE_BATCH_SIZE)) {
159             final String cmHandlesJsonData = createCmHandlesJsonData(yangModelCmHandleBatch);
160             cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
161                     NCMP_DMI_REGISTRY_PARENT, cmHandlesJsonData, NO_TIMESTAMP);
162         }
163     }
164
165     @Override
166     public Collection<DataNode> getCmHandleDataNodeByCmHandleId(final String cmHandleId) {
167         return this.getDataNode(getXPathForCmHandleById(cmHandleId));
168     }
169
170     @Override
171     public DataNode getCmHandleDataNodeByAlternateId(final String alternateId) {
172         final String xPathForCmHandleByAlternateId = getXPathForCmHandleByAlternateId(alternateId);
173         final Collection<DataNode> dataNodes = cmHandleQueries
174             .queryNcmpRegistryByCpsPath(xPathForCmHandleByAlternateId, OMIT_DESCENDANTS);
175         if (dataNodes.isEmpty()) {
176             throw new DataNodeNotFoundException(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
177                 xPathForCmHandleByAlternateId);
178         }
179         return dataNodes.iterator().next();
180     }
181
182     @Override
183     public Collection<DataNode> getCmHandleDataNodes(final Collection<String> cmHandleIds) {
184         final Collection<String> xpaths = new ArrayList<>(cmHandleIds.size());
185         cmHandleIds.forEach(cmHandleId -> xpaths.add(getXPathForCmHandleById(cmHandleId)));
186         return this.getDataNodes(xpaths);
187     }
188
189     @Override
190     public Collection<String> getCmHandleIdsWithGivenModules(final Collection<String> moduleNamesForQuery) {
191         return cpsAnchorService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNamesForQuery);
192     }
193
194     private static String getXPathForCmHandleById(final String cmHandleId) {
195         return NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']";
196     }
197
198     private static String getXPathForCmHandleByAlternateId(final String alternateId) {
199         return NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@alternate-id='" + alternateId + "']";
200     }
201
202     private static String createStateJsonData(final String state) {
203         return "{\"state\":" + state + "}";
204     }
205
206     private String createCmHandlesJsonData(final List<YangModelCmHandle> yangModelCmHandles) {
207         return "{\"cm-handles\":" + jsonObjectMapper.asJsonString(yangModelCmHandles) + "}";
208     }
209 }