2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2024-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
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.policy.clamp.acm.participant.intermediary.handler;
23 import java.util.List;
25 import java.util.UUID;
26 import lombok.RequiredArgsConstructor;
27 import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto;
28 import org.onap.policy.clamp.acm.participant.intermediary.api.ElementState;
29 import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto;
30 import org.onap.policy.clamp.acm.participant.intermediary.handler.cache.CacheProvider;
31 import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
32 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
33 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
34 import org.onap.policy.clamp.models.acm.concepts.DeployState;
35 import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils;
36 import org.onap.policy.clamp.models.acm.concepts.SubState;
37 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration;
38 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionPrepare;
39 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42 import org.springframework.stereotype.Component;
45 @RequiredArgsConstructor
46 public class AcSubStateHandler {
48 private static final Logger LOGGER = LoggerFactory.getLogger(AcSubStateHandler.class);
50 private final CacheProvider cacheProvider;
51 private final ThreadHandler listener;
54 * Handles AutomationComposition Migration Precheck.
56 * @param migrationMsg the AutomationCompositionMigration
58 public void handleAcMigrationPrecheck(AutomationCompositionMigration migrationMsg) {
59 if (migrationMsg.getAutomationCompositionId() == null || migrationMsg.getCompositionTargetId() == null) {
63 var automationComposition = cacheProvider.getAutomationComposition(migrationMsg.getAutomationCompositionId());
64 if (automationComposition == null) {
65 LOGGER.debug("Automation composition {} does not use this participant",
66 migrationMsg.getAutomationCompositionId());
69 automationComposition.setSubState(SubState.MIGRATION_PRECHECKING);
70 for (var participantDeploy : migrationMsg.getParticipantUpdatesList()) {
71 if (cacheProvider.getParticipantId().equals(participantDeploy.getParticipantId())) {
73 callParticipantMigratePrecheck(migrationMsg.getMessageId(), participantDeploy.getAcElementList(),
74 automationComposition, migrationMsg.getCompositionTargetId());
79 private void callParticipantMigratePrecheck(UUID messageId, List<AcElementDeploy> acElements,
80 AutomationComposition automationComposition, UUID compositionTargetId) {
81 var compositionElementMap = cacheProvider.getCompositionElementDtoMap(automationComposition);
82 var instanceElementMap = cacheProvider.getInstanceElementDtoMap(automationComposition);
83 var acElementList = automationComposition.getElements();
84 for (var acElement : acElements) {
85 var element = acElementList.get(acElement.getId());
86 if (element != null) {
87 element.setSubState(SubState.MIGRATION_PRECHECKING);
90 var acCopyMigrateTo = new AutomationComposition(automationComposition);
91 var acElementCopyList = acCopyMigrateTo.getElements();
92 for (var acElement : acElements) {
93 var element = acElementCopyList.get(acElement.getId());
94 if (element != null) {
95 AcmUtils.recursiveMerge(element.getProperties(), acElement.getProperties());
96 element.setDefinition(acElement.getDefinition());
98 element = CacheProvider.createAutomationCompositionElement(acElement);
99 element.setSubState(SubState.MIGRATION_PRECHECKING);
100 acElementCopyList.put(element.getId(), element);
103 var toDelete = acElementCopyList.values().stream()
104 .filter(el -> !SubState.MIGRATION_PRECHECKING.equals(el.getSubState()))
105 .map(AutomationCompositionElement::getId)
107 toDelete.forEach(acElementCopyList::remove);
109 var compositionElementTargetMap = cacheProvider.getCompositionElementDtoMap(acCopyMigrateTo,
110 compositionTargetId);
111 var instanceElementMigrateMap = cacheProvider.getInstanceElementDtoMap(acCopyMigrateTo);
113 for (var acElement : acElements) {
114 var compositionElement = compositionElementMap.get(acElement.getId());
115 var compositionElementTarget = compositionElementTargetMap.get(acElement.getId());
116 var instanceElement = instanceElementMap.get(acElement.getId());
117 var instanceElementMigrate = instanceElementMigrateMap.get(acElement.getId());
119 if (instanceElement == null) {
120 // new element scenario
121 compositionElement = new CompositionElementDto(automationComposition.getCompositionId(),
122 acElement.getDefinition(), Map.of(), Map.of(), ElementState.NOT_PRESENT);
123 instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), acElement.getId(),
124 Map.of(), Map.of(), ElementState.NOT_PRESENT);
125 compositionElementTarget = CacheProvider.changeStateToNew(compositionElementTarget);
126 instanceElementMigrate = CacheProvider.changeStateToNew(instanceElementMigrate);
129 listener.migratePrecheck(messageId, compositionElement, compositionElementTarget,
130 instanceElement, instanceElementMigrate);
133 for (var elementId : toDelete) {
134 var compositionDtoTarget =
135 new CompositionElementDto(compositionTargetId,
136 automationComposition.getElements().get(elementId).getDefinition(),
137 Map.of(), Map.of(), ElementState.REMOVED);
138 var instanceDtoTarget =
139 new InstanceElementDto(automationComposition.getInstanceId(), elementId,
140 Map.of(), Map.of(), ElementState.REMOVED);
142 listener.migratePrecheck(messageId, compositionElementMap.get(elementId), compositionDtoTarget,
143 instanceElementMap.get(elementId), instanceDtoTarget);
148 * Handle AutomationComposition Prepare message.
150 * @param acPrepareMsg the AutomationCompositionPrepare message
152 public void handleAcPrepare(AutomationCompositionPrepare acPrepareMsg) {
153 if (acPrepareMsg.isPreDeploy()) {
154 for (var participantPrepare : acPrepareMsg.getParticipantList()) {
155 if (cacheProvider.getParticipantId().equals(participantPrepare.getParticipantId())) {
156 cacheProvider.initializeAutomationComposition(acPrepareMsg.getCompositionId(),
157 acPrepareMsg.getAutomationCompositionId(), participantPrepare, DeployState.UNDEPLOYED,
158 SubState.PREPARING, acPrepareMsg.getRevisionIdInstance());
159 callParticipanPrepare(acPrepareMsg.getMessageId(), participantPrepare.getAcElementList(),
160 acPrepareMsg.getStage(), acPrepareMsg.getAutomationCompositionId());
164 var automationComposition =
165 cacheProvider.getAutomationComposition(acPrepareMsg.getAutomationCompositionId());
166 automationComposition.setSubState(SubState.REVIEWING);
167 callParticipanReview(acPrepareMsg.getMessageId(), automationComposition);
171 private void callParticipanPrepare(UUID messageId, List<AcElementDeploy> acElementList, Integer stageMsg,
173 var automationComposition = cacheProvider.getAutomationComposition(instanceId);
174 for (var elementDeploy : acElementList) {
175 var element = automationComposition.getElements().get(elementDeploy.getId());
176 var compositionInProperties = cacheProvider
177 .getCommonProperties(automationComposition.getCompositionId(), element.getDefinition());
178 var compositionElement = cacheProvider.createCompositionElementDto(automationComposition.getCompositionId(),
180 var stageSet = ParticipantUtils.findStageSetPrepare(compositionInProperties);
181 if (stageSet.contains(stageMsg)) {
182 var instanceElement =
183 new InstanceElementDto(instanceId, elementDeploy.getId(), elementDeploy.getProperties(),
184 element.getOutProperties());
185 listener.prepare(messageId, compositionElement, instanceElement, stageMsg);
190 private void callParticipanReview(UUID messageId, AutomationComposition automationComposition) {
191 for (var element : automationComposition.getElements().values()) {
192 element.setSubState(SubState.REVIEWING);
193 var compositionElement = cacheProvider.createCompositionElementDto(automationComposition.getCompositionId(),
195 var instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), element.getId(),
196 element.getProperties(), element.getOutProperties());
197 listener.review(messageId, compositionElement, instanceElement);