Merge "Publish trust level notification event"
[cps.git] / cps-ncmp-service / src / main / java / org / onap / cps / ncmp / api / impl / events / lcm / LcmEventsCmHandleStateHandlerImpl.java
1 /*
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2022-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
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.cps.ncmp.api.impl.events.lcm;
22
23 import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.ADVISED;
24 import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETED;
25 import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.LOCKED;
26 import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.READY;
27
28 import io.micrometer.core.annotation.Timed;
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.HashMap;
32 import java.util.LinkedHashMap;
33 import java.util.List;
34 import java.util.Map;
35 import lombok.Getter;
36 import lombok.NoArgsConstructor;
37 import lombok.RequiredArgsConstructor;
38 import lombok.Setter;
39 import lombok.extern.slf4j.Slf4j;
40 import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
41 import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
42 import org.onap.cps.ncmp.api.impl.inventory.CompositeStateUtils;
43 import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
44 import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
45 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
46 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
47 import org.springframework.stereotype.Service;
48
49 @Slf4j
50 @Service
51 @RequiredArgsConstructor
52 public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleStateHandler {
53
54     private final InventoryPersistence inventoryPersistence;
55     private final LcmEventsCmHandleStateHandlerAsyncHelper lcmEventsCmHandleStateHandlerAsyncHelper;
56
57     @Override
58     public void updateCmHandleState(final YangModelCmHandle updatedYangModelCmHandle,
59             final CmHandleState targetCmHandleState) {
60
61         final CompositeState compositeState = updatedYangModelCmHandle.getCompositeState();
62
63         if (isCompositeStateSame(compositeState, targetCmHandleState)) {
64             log.debug("CmHandle with id : {} already in state : {}", updatedYangModelCmHandle.getId(),
65                     targetCmHandleState);
66         } else {
67             final YangModelCmHandle currentYangModelCmHandle = YangModelCmHandle.deepCopyOf(updatedYangModelCmHandle);
68             updateToSpecifiedCmHandleState(updatedYangModelCmHandle, targetCmHandleState);
69             persistCmHandle(updatedYangModelCmHandle, currentYangModelCmHandle);
70             lcmEventsCmHandleStateHandlerAsyncHelper.publishLcmEventAsynchronously(
71                     toNcmpServiceCmHandle(updatedYangModelCmHandle),
72                     toNcmpServiceCmHandle(currentYangModelCmHandle));
73         }
74     }
75
76     @Override
77     @Timed(value = "cps.ncmp.cmhandle.state.update.batch",
78             description = "Time taken to update a batch of cm handle states")
79     public void updateCmHandleStateBatch(final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle) {
80         final Collection<CmHandleTransitionPair> cmHandleTransitionPairs =
81                 prepareCmHandleTransitionBatch(cmHandleStatePerCmHandle);
82         persistCmHandleBatch(cmHandleTransitionPairs);
83         lcmEventsCmHandleStateHandlerAsyncHelper.publishLcmEventBatchAsynchronously(cmHandleTransitionPairs);
84     }
85
86     @Override
87     public void initiateStateAdvised(final Collection<YangModelCmHandle> yangModelCmHandles) {
88         final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle = new HashMap<>(yangModelCmHandles.size());
89         for (final YangModelCmHandle yangModelCmHandle : yangModelCmHandles) {
90             cmHandleStatePerCmHandle.put(yangModelCmHandle, ADVISED);
91         }
92         updateCmHandleStateBatch(cmHandleStatePerCmHandle);
93     }
94
95     private Collection<CmHandleTransitionPair> prepareCmHandleTransitionBatch(
96             final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle) {
97         final List<CmHandleTransitionPair> cmHandleTransitionPairs = new ArrayList<>(cmHandleStatePerCmHandle.size());
98         cmHandleStatePerCmHandle.forEach((yangModelCmHandle, targetCmHandleState) -> {
99
100             final CompositeState compositeState = yangModelCmHandle.getCompositeState();
101
102             if (isCompositeStateSame(compositeState, targetCmHandleState)) {
103                 log.debug("CmHandle with id : {} already in state : {}", yangModelCmHandle.getId(),
104                         targetCmHandleState);
105             } else {
106                 final CmHandleTransitionPair cmHandleTransitionPair = new CmHandleTransitionPair();
107                 cmHandleTransitionPair.setCurrentYangModelCmHandle(YangModelCmHandle.deepCopyOf(yangModelCmHandle));
108                 updateToSpecifiedCmHandleState(yangModelCmHandle, targetCmHandleState);
109                 cmHandleTransitionPair.setTargetYangModelCmHandle(yangModelCmHandle);
110                 cmHandleTransitionPairs.add(cmHandleTransitionPair);
111             }
112         });
113         return cmHandleTransitionPairs;
114     }
115
116
117     private void persistCmHandle(final YangModelCmHandle targetYangModelCmHandle,
118             final YangModelCmHandle currentYangModelCmHandle) {
119         if (isNew(currentYangModelCmHandle.getCompositeState())) {
120             log.debug("Registering a new cm handle {}", targetYangModelCmHandle.getId());
121             inventoryPersistence.saveCmHandle(targetYangModelCmHandle);
122         } else if (isDeleted(targetYangModelCmHandle.getCompositeState())) {
123             log.info("CmHandle with Id : {} is DELETED", targetYangModelCmHandle.getId());
124         } else {
125             inventoryPersistence.saveCmHandleState(targetYangModelCmHandle.getId(),
126                     targetYangModelCmHandle.getCompositeState());
127         }
128     }
129
130     private void persistCmHandleBatch(final Collection<CmHandleTransitionPair> cmHandleTransitionPairs) {
131
132         final List<YangModelCmHandle> newCmHandles = new ArrayList<>();
133         final Map<String, CompositeState> compositeStatePerCmHandleId = new LinkedHashMap<>();
134
135         cmHandleTransitionPairs.forEach(cmHandleTransitionPair -> {
136             if (isNew(cmHandleTransitionPair.getCurrentYangModelCmHandle().getCompositeState()
137             )) {
138                 newCmHandles.add(cmHandleTransitionPair.getTargetYangModelCmHandle());
139             } else if (!isDeleted(cmHandleTransitionPair.getTargetYangModelCmHandle().getCompositeState())) {
140                 compositeStatePerCmHandleId.put(cmHandleTransitionPair.getTargetYangModelCmHandle().getId(),
141                         cmHandleTransitionPair.getTargetYangModelCmHandle().getCompositeState());
142             }
143         });
144
145         inventoryPersistence.saveCmHandleBatch(newCmHandles);
146         inventoryPersistence.saveCmHandleStateBatch(compositeStatePerCmHandleId);
147
148     }
149
150     private void updateToSpecifiedCmHandleState(final YangModelCmHandle yangModelCmHandle,
151             final CmHandleState targetCmHandleState) {
152
153         if (READY == targetCmHandleState) {
154             setInitialStates(yangModelCmHandle);
155         } else if (ADVISED == targetCmHandleState) {
156             if (yangModelCmHandle.getCompositeState() == null) {
157                 registerNewCmHandle(yangModelCmHandle);
158             } else if (yangModelCmHandle.getCompositeState().getCmHandleState() == LOCKED) {
159                 retryCmHandle(yangModelCmHandle);
160             }
161         } else {
162             setCmHandleState(yangModelCmHandle, targetCmHandleState);
163         }
164     }
165
166     private void setInitialStates(final YangModelCmHandle yangModelCmHandle) {
167         CompositeStateUtils.setInitialDataStoreSyncState().accept(yangModelCmHandle.getCompositeState());
168         CompositeStateUtils.setCompositeState(READY).accept(yangModelCmHandle.getCompositeState());
169     }
170
171     private void retryCmHandle(final YangModelCmHandle yangModelCmHandle) {
172         CompositeStateUtils.setCompositeStateForRetry().accept(yangModelCmHandle.getCompositeState());
173     }
174
175     private void registerNewCmHandle(final YangModelCmHandle yangModelCmHandle) {
176         yangModelCmHandle.setCompositeState(new CompositeState());
177         setCmHandleState(yangModelCmHandle, ADVISED);
178     }
179
180     private void setCmHandleState(final YangModelCmHandle yangModelCmHandle, final CmHandleState targetCmHandleState) {
181         CompositeStateUtils.setCompositeState(targetCmHandleState).accept(yangModelCmHandle.getCompositeState());
182     }
183
184     private boolean isNew(final CompositeState existingCompositeState) {
185         return (existingCompositeState == null);
186     }
187
188     private boolean isDeleted(final CompositeState targetCompositeState) {
189         return targetCompositeState.getCmHandleState() == DELETED;
190     }
191
192     private boolean isCompositeStateSame(final CompositeState compositeState, final CmHandleState targetCmHandleState) {
193         return (compositeState != null && compositeState.getCmHandleState() == targetCmHandleState);
194     }
195
196     private NcmpServiceCmHandle toNcmpServiceCmHandle(final YangModelCmHandle yangModelCmHandle) {
197         return YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle(yangModelCmHandle);
198     }
199
200     @Getter
201     @Setter
202     @NoArgsConstructor
203     static class CmHandleTransitionPair {
204
205         private YangModelCmHandle currentYangModelCmHandle;
206         private YangModelCmHandle targetYangModelCmHandle;
207     }
208 }