240cbe8915b60a39a406159d0c3f1d1f136f0306
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2023-2025 OpenInfra Foundation Europe. All rights reserved.
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.policy.clamp.acm.participant.intermediary.handler.cache;
22
23 import java.util.HashMap;
24 import java.util.LinkedHashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.UUID;
28 import java.util.concurrent.ConcurrentHashMap;
29 import lombok.Getter;
30 import lombok.NonNull;
31 import lombok.Setter;
32 import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto;
33 import org.onap.policy.clamp.acm.participant.intermediary.api.ElementState;
34 import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto;
35 import org.onap.policy.clamp.acm.participant.intermediary.parameters.ParticipantParameters;
36 import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
37 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
38 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
39 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition;
40 import org.onap.policy.clamp.models.acm.concepts.DeployState;
41 import org.onap.policy.clamp.models.acm.concepts.LockState;
42 import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy;
43 import org.onap.policy.clamp.models.acm.concepts.ParticipantRestartAc;
44 import org.onap.policy.clamp.models.acm.concepts.ParticipantSupportedElementType;
45 import org.onap.policy.clamp.models.acm.concepts.SubState;
46 import org.onap.policy.models.base.PfUtils;
47 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
48 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51 import org.springframework.stereotype.Component;
52
53 @Component
54 public class CacheProvider {
55
56     private static final Logger LOGGER = LoggerFactory.getLogger(CacheProvider.class);
57
58     @Getter
59     private final UUID participantId;
60
61     @Getter
62     @Setter
63     private boolean registered = false;
64
65     @Getter
66     private final UUID replicaId;
67
68     private final List<ParticipantSupportedElementType> supportedAcElementTypes;
69
70     @Getter
71     private final Map<UUID, AutomationComposition> automationCompositions = new ConcurrentHashMap<>();
72
73     @Getter
74     private final Map<UUID, AcDefinition> acElementsDefinitions = new ConcurrentHashMap<>();
75
76     @Getter
77     private final Map<UUID, UUID> msgIdentification = new ConcurrentHashMap<>();
78
79     @Getter
80     private final Map<UUID, AutomationCompositionMsg<?>> messagesOnHold = new HashMap<>();
81
82     /**
83      * Constructor.
84      *
85      * @param parameters the parameters of the participant
86      */
87     public CacheProvider(ParticipantParameters parameters) {
88         this.participantId = parameters.getIntermediaryParameters().getParticipantId();
89         this.supportedAcElementTypes = parameters.getIntermediaryParameters().getParticipantSupportedElementTypes();
90         this.replicaId = UUID.randomUUID();
91     }
92
93     public List<ParticipantSupportedElementType> getSupportedAcElementTypes() {
94         return PfUtils.mapList(supportedAcElementTypes, ParticipantSupportedElementType::new);
95     }
96
97     /**
98      * Get AutomationComposition by id.
99      *
100      * @param automationCompositionId the AutomationComposition Id
101      * @return the AutomationComposition
102      */
103     public AutomationComposition getAutomationComposition(@NonNull UUID automationCompositionId) {
104         return automationCompositions.get(automationCompositionId);
105     }
106
107     /**
108      * Remove AutomationComposition.
109      *
110      * @param automationCompositionId the AutomationComposition Id
111      */
112     public void removeAutomationComposition(@NonNull UUID automationCompositionId) {
113         automationCompositions.remove(automationCompositionId);
114     }
115
116     /**
117      * Add ElementDefinition.
118      *
119      * @param compositionId the composition Id
120      * @param list the list of AutomationCompositionElementDefinition to add
121      * @param revisionId the last Update
122      */
123     public void addElementDefinition(@NonNull UUID compositionId, List<AutomationCompositionElementDefinition> list,
124             UUID revisionId) {
125         var acDefinition = new AcDefinition();
126         acDefinition.setCompositionId(compositionId);
127         acDefinition.setRevisionId(revisionId);
128         for (var acElementDefinition : list) {
129             if (acElementDefinition.getAutomationCompositionElementToscaNodeTemplate() == null) {
130                 acElementDefinition.setAutomationCompositionElementToscaNodeTemplate(new ToscaNodeTemplate());
131             }
132             if (acElementDefinition.getAutomationCompositionElementToscaNodeTemplate().getProperties() == null) {
133                 acElementDefinition.getAutomationCompositionElementToscaNodeTemplate().setProperties(new HashMap<>());
134             }
135             acDefinition.getElements().put(acElementDefinition.getAcElementDefinitionId(), acElementDefinition);
136         }
137         acElementsDefinitions.put(compositionId, acDefinition);
138         LOGGER.info("Updated cache for the composition id {}", compositionId);
139     }
140
141     public void removeElementDefinition(@NonNull UUID compositionId) {
142         acElementsDefinitions.remove(compositionId);
143     }
144
145     /**
146      * Get CommonProperties.
147      *
148      * @param instanceId the Automation Composition Id
149      * @param acElementId the Automation Composition Element Id
150      * @return the common Properties as Map
151      */
152     public Map<String, Object> getCommonProperties(@NonNull UUID instanceId, @NonNull UUID acElementId) {
153         var automationComposition = automationCompositions.get(instanceId);
154         var element = automationComposition.getElements().get(acElementId);
155         return getCommonProperties(automationComposition.getCompositionId(), element.getDefinition());
156     }
157
158     /**
159      * Get CommonProperties.
160      *
161      * @param compositionId the composition Id
162      * @param definition the AutomationCompositionElementDefinition Id
163      * @return the common Properties as Map
164      */
165     public Map<String, Object> getCommonProperties(@NonNull UUID compositionId,
166         @NonNull ToscaConceptIdentifier definition) {
167         var acDefinition = acElementsDefinitions.get(compositionId);
168         if (acDefinition == null) {
169             return new HashMap<>();
170         }
171         var map = acDefinition.getElements().get(definition);
172         return map != null ? map.getAutomationCompositionElementToscaNodeTemplate().getProperties() : new HashMap<>();
173     }
174
175     /**
176      * Initialize an AutomationComposition from a ParticipantDeploy.
177      *
178      * @param compositionId the composition Id
179      * @param instanceId the Automation Composition Id
180      * @param participantDeploy the ParticipantDeploy
181      * @param revisionId the identification of the last update
182      */
183     public void initializeAutomationComposition(@NonNull UUID compositionId, @NonNull UUID instanceId,
184             ParticipantDeploy participantDeploy, UUID revisionId) {
185         initializeAutomationComposition(compositionId, null, instanceId, participantDeploy,
186             DeployState.DEPLOYING, SubState.NONE, revisionId);
187
188     }
189
190     /**
191      * Initialize an AutomationComposition from a ParticipantDeploy.
192      *
193      * @param compositionId the composition Id
194      * @param instanceId the Automation Composition Id
195      * @param participantDeploy the ParticipantDeploy
196      * @param deployState the DeployState
197      * @param subState the SubState
198      * @param revisionId the identification of the last update
199      */
200     public void initializeAutomationComposition(@NonNull UUID compositionId, UUID compositionTargetId,
201                                                 @NonNull UUID instanceId,
202             ParticipantDeploy participantDeploy, DeployState deployState, SubState subState, UUID revisionId) {
203
204         var automationComposition = createAcInstance(compositionId, compositionTargetId, instanceId, participantDeploy,
205                 deployState, subState, revisionId);
206
207         automationCompositions.put(instanceId, automationComposition);
208         LOGGER.info("Initialized participant cache for the {} operation of the instance {}", deployState, instanceId);
209
210     }
211
212     /**
213      * Initialize an AutomationComposition from a ParticipantRestartAc.
214      *
215      * @param compositionId the composition Id
216      * @param participantRestartAc the ParticipantRestartAc
217      */
218     public void initializeAutomationComposition(@NonNull UUID compositionId,
219             ParticipantRestartAc participantRestartAc) {
220         Map<UUID, AutomationCompositionElement> acElementMap = new LinkedHashMap<>();
221         for (var element : participantRestartAc.getAcElementList()) {
222             if (!getParticipantId().equals(element.getParticipantId())) {
223                 continue;
224             }
225             var acElement = new AutomationCompositionElement();
226             acElement.setId(element.getId());
227             acElement.setParticipantId(getParticipantId());
228             acElement.setDefinition(element.getDefinition());
229             acElement.setDeployState(element.getDeployState());
230             acElement.setLockState(element.getLockState());
231             acElement.setSubState(SubState.NONE);
232             acElement.setOperationalState(element.getOperationalState());
233             acElement.setUseState(element.getUseState());
234             acElement.setProperties(element.getProperties());
235             acElement.setOutProperties(element.getOutProperties());
236             acElement.setMigrationState(element.getMigrationState());
237             acElementMap.put(element.getId(), acElement);
238         }
239         var automationComposition = new AutomationComposition();
240         automationComposition.setCompositionId(compositionId);
241         automationComposition.setCompositionTargetId(participantRestartAc.getCompositionTargetId());
242         automationComposition.setDeployState(participantRestartAc.getDeployState());
243         automationComposition.setLockState(participantRestartAc.getLockState());
244         automationComposition.setInstanceId(participantRestartAc.getAutomationCompositionId());
245         automationComposition.setElements(acElementMap);
246         automationComposition.setStateChangeResult(participantRestartAc.getStateChangeResult());
247         automationComposition.setRevisionId(participantRestartAc.getRevisionId());
248         automationCompositions.put(automationComposition.getInstanceId(), automationComposition);
249         LOGGER.info("Updated participant cache for the instance id {}",
250                 participantRestartAc.getAutomationCompositionId());
251     }
252
253     /**
254      *  Create an AutomationComposition.
255      * @param compositionId compositionId
256      * @param compositionTargetId compositionTargetId
257      * @param instanceId instanceId
258      * @param participantDeploy participantDeploy
259      * @param deployState deployState
260      * @param subState subState
261      * @param revisionId revisionId
262      * @return AutomationComposition
263      */
264     public AutomationComposition createAcInstance(@NonNull UUID compositionId, UUID compositionTargetId,
265                                                   @NonNull UUID instanceId, ParticipantDeploy participantDeploy,
266                                                   DeployState deployState, SubState subState, UUID revisionId) {
267         var acLast = automationCompositions.get(instanceId);
268         Map<UUID, AutomationCompositionElement> acElementMap = new LinkedHashMap<>();
269         for (var element : participantDeploy.getAcElementList()) {
270             var acElement = createAutomationCompositionElement(element);
271             acElement.setParticipantId(getParticipantId());
272             acElement.setDeployState(deployState);
273             acElement.setSubState(subState);
274             var acElementLast = acLast != null ? acLast.getElements().get(element.getId()) : null;
275             if (acElementLast != null) {
276                 acElement.setOutProperties(acElementLast.getOutProperties());
277                 acElement.setOperationalState(acElementLast.getOperationalState());
278                 acElement.setUseState(acElementLast.getUseState());
279             }
280             acElementMap.put(element.getId(), acElement);
281         }
282         var automationComposition = acLast != null ? acLast : new AutomationComposition();
283         automationComposition.setCompositionId(compositionId);
284         automationComposition.setInstanceId(instanceId);
285         if (acLast != null) {
286             automationComposition.getElements().putAll(acElementMap);
287         } else {
288             automationComposition.setElements(acElementMap);
289         }
290         automationComposition.setDeployState(deployState);
291         automationComposition.setSubState(subState);
292         automationComposition.setRevisionId(revisionId);
293         if (compositionTargetId != null) {
294             automationComposition.setCompositionTargetId(compositionTargetId);
295         }
296
297         return automationComposition;
298     }
299
300     /**
301      * Create AutomationCompositionElement to save in memory.
302      *
303      * @param element AcElementDeploy
304      * @return a new AutomationCompositionElement
305      */
306     public static AutomationCompositionElement createAutomationCompositionElement(AcElementDeploy element) {
307         var acElement = new AutomationCompositionElement();
308         acElement.setId(element.getId());
309         acElement.setDefinition(element.getDefinition());
310         acElement.setProperties(element.getProperties());
311         acElement.setSubState(SubState.NONE);
312         acElement.setLockState(LockState.LOCKED);
313         acElement.setMigrationState(element.getMigrationState());
314         return acElement;
315     }
316
317     /**
318      * Create CompositionElementDto.
319      *
320      * @param compositionId the composition Id
321      * @param element AutomationComposition Element
322      * @return the CompositionElementDto
323      */
324     public CompositionElementDto createCompositionElementDto(UUID compositionId, AutomationCompositionElement element) {
325         var acDefinition = acElementsDefinitions.get(compositionId);
326         var acDefinitionElement = acDefinition != null ? acDefinition.getElements().get(element.getDefinition()) : null;
327
328         return (acDefinitionElement != null) ? new CompositionElementDto(compositionId, element.getDefinition(),
329                 acDefinitionElement.getAutomationCompositionElementToscaNodeTemplate().getProperties(),
330                 acDefinitionElement.getOutProperties()) :
331             new CompositionElementDto(compositionId, element.getDefinition(),
332                 Map.of(), Map.of(), ElementState.NOT_PRESENT);
333     }
334
335     /**
336      * Get a Map of CompositionElementDto by elementId from the elements of an AutomationComposition.
337      *
338      * @param automationComposition the AutomationComposition
339      * @param compositionId the compositionId
340      * @return the Map of CompositionElementDto
341      */
342     public Map<UUID, CompositionElementDto> getCompositionElementDtoMap(AutomationComposition automationComposition,
343             UUID compositionId) {
344         var acDefinition = acElementsDefinitions.get(compositionId);
345         Map<UUID, CompositionElementDto> map = new HashMap<>();
346         for (var element : automationComposition.getElements().values()) {
347             var acDefinitionElement = (acDefinition != null) ? acDefinition.getElements().get(element.getDefinition()) :
348                     null;
349             var compositionElement = (acDefinitionElement != null)
350                     ? new CompositionElementDto(compositionId, element.getDefinition(),
351                     acDefinitionElement.getAutomationCompositionElementToscaNodeTemplate().getProperties(),
352                     acDefinitionElement.getOutProperties()) :
353                     new CompositionElementDto(compositionId, element.getDefinition(),
354                             Map.of(), Map.of(), ElementState.NOT_PRESENT);
355             map.put(element.getId(), compositionElement);
356         }
357         return map;
358     }
359
360     public Map<UUID, CompositionElementDto> getCompositionElementDtoMap(AutomationComposition automationComposition) {
361         return getCompositionElementDtoMap(automationComposition, automationComposition.getCompositionId());
362     }
363
364     /**
365      * Get a Map of InstanceElementDto by elementId from the elements of an AutomationComposition.
366      *
367      * @param automationComposition the AutomationComposition
368      * @return the Map of InstanceElementDto
369      */
370     public Map<UUID, InstanceElementDto> getInstanceElementDtoMap(AutomationComposition automationComposition) {
371         Map<UUID, InstanceElementDto> map = new HashMap<>();
372         for (var element : automationComposition.getElements().values()) {
373             var instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), element.getId(),
374                     element.getProperties(), element.getOutProperties());
375             map.put(element.getId(), instanceElement);
376         }
377         return map;
378     }
379
380     /**
381      * Create a new InstanceElementDto record with state New.
382      *
383      * @param instanceElement the InstanceElementDto
384      * @return a new InstanceElementDto
385      */
386     public static InstanceElementDto changeStateToNew(InstanceElementDto instanceElement) {
387         return new InstanceElementDto(instanceElement.instanceId(), instanceElement.elementId(),
388                 instanceElement.inProperties(), instanceElement.outProperties(), ElementState.NEW);
389     }
390
391     /**
392      * Create a new CompositionElementDto record with state New.
393      *
394      * @param compositionElement the CompositionElementDto
395      * @return a new CompositionElementDto
396      */
397     public static CompositionElementDto changeStateToNew(CompositionElementDto compositionElement) {
398         return new CompositionElementDto(compositionElement.compositionId(), compositionElement.elementDefinitionId(),
399                 compositionElement.inProperties(), compositionElement.outProperties(), ElementState.NEW);
400     }
401
402     /**
403      * Check composition is present and compare the last update.
404      *
405      * @param compositionId the instanceId
406      * @param revisionId the last Update
407      * @return true if the composition is updated
408      */
409     public boolean isCompositionDefinitionUpdated(UUID compositionId, UUID revisionId) {
410         if (revisionId == null) {
411             // old ACM-r
412             return true;
413         }
414         var acDefinition = acElementsDefinitions.get(compositionId);
415         if (acDefinition == null) {
416             return false;
417         }
418         return revisionId.equals(acDefinition.getRevisionId());
419     }
420
421     /**
422      * Check instance is present and compare the last update.
423      *
424      * @param instanceId the instanceId
425      * @param revisionId the last Update
426      * @return true if the instance is updated
427      */
428     public boolean isInstanceUpdated(UUID instanceId, UUID revisionId) {
429         if (revisionId == null) {
430             // old ACM-r
431             return true;
432         }
433         var automationComposition = automationCompositions.get(instanceId);
434         if (automationComposition == null) {
435             return false;
436         }
437         return revisionId.equals(automationComposition.getRevisionId());
438     }
439 }