2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021-2023 Nordix Foundation.
4 * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.clamp.acm.participant.intermediary.handler;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.UUID;
27 import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener;
28 import org.onap.policy.clamp.acm.participant.intermediary.comm.ParticipantMessagePublisher;
29 import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
30 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
31 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition;
32 import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy;
33 import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils;
34 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionDeploy;
35 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionDeployAck;
36 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionStateChange;
37 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantMessageType;
38 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.PropertiesUpdate;
39 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
40 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder;
41 import org.onap.policy.clamp.models.acm.persistence.provider.AcInstanceStateResolver;
42 import org.onap.policy.models.base.PfModelException;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45 import org.springframework.stereotype.Component;
48 * This class is responsible for managing the state of all automation compositions in the participant.
51 public class AutomationCompositionHandler {
52 private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionHandler.class);
54 private final CacheProvider cacheProvider;
55 private final ParticipantMessagePublisher publisher;
56 private final AutomationCompositionElementListener listener;
57 private final AcInstanceStateResolver acInstanceStateResolver;
60 * Constructor, set the participant ID and messageSender.
62 * @param cacheProvider the Cache Provider
63 * @param publisher the ParticipantMessage Publisher
64 * @param listener the ThreadHandler Listener
66 public AutomationCompositionHandler(CacheProvider cacheProvider, ParticipantMessagePublisher publisher,
67 AutomationCompositionElementListener listener) {
68 this.cacheProvider = cacheProvider;
69 this.publisher = publisher;
70 this.listener = listener;
71 this.acInstanceStateResolver = new AcInstanceStateResolver();
75 * Handle a automation composition state change message.
77 * @param stateChangeMsg the state change message
79 public void handleAutomationCompositionStateChange(AutomationCompositionStateChange stateChangeMsg) {
80 if (stateChangeMsg.getAutomationCompositionId() == null) {
84 var automationComposition = cacheProvider.getAutomationComposition(stateChangeMsg.getAutomationCompositionId());
86 if (automationComposition == null) {
87 var automationCompositionAck =
88 new AutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK);
89 automationCompositionAck.setParticipantId(cacheProvider.getParticipantId());
90 automationCompositionAck.setMessage("Automation composition " + stateChangeMsg.getAutomationCompositionId()
91 + " does not use this participant " + cacheProvider.getParticipantId());
92 automationCompositionAck.setResult(false);
93 automationCompositionAck.setResponseTo(stateChangeMsg.getMessageId());
94 automationCompositionAck.setAutomationCompositionId(stateChangeMsg.getAutomationCompositionId());
95 publisher.sendAutomationCompositionAck(automationCompositionAck);
96 LOGGER.debug("Automation composition {} does not use this participant",
97 stateChangeMsg.getAutomationCompositionId());
101 if (!checkConsistantOrderState(automationComposition, stateChangeMsg.getDeployOrderedState(),
102 stateChangeMsg.getLockOrderedState())) {
103 LOGGER.warn("Not Consistant OrderState Automation composition {}",
104 stateChangeMsg.getAutomationCompositionId());
108 if (DeployOrder.NONE.equals(stateChangeMsg.getDeployOrderedState())) {
109 handleLockOrderState(automationComposition, stateChangeMsg.getLockOrderedState(),
110 stateChangeMsg.getStartPhase());
112 handleDeployOrderState(automationComposition, stateChangeMsg.getDeployOrderedState(),
113 stateChangeMsg.getStartPhase());
117 private boolean checkConsistantOrderState(AutomationComposition automationComposition, DeployOrder deployOrder,
118 LockOrder lockOrder) {
119 if (DeployOrder.UPDATE.equals(deployOrder)) {
122 return acInstanceStateResolver.resolve(deployOrder, lockOrder, automationComposition.getDeployState(),
123 automationComposition.getLockState(), automationComposition.getStateChangeResult()) != null;
127 * Method to handle state changes.
129 * @param automationComposition participant response
130 * @param orderedState automation composition ordered state
131 * @param startPhaseMsg startPhase from message
133 private void handleDeployOrderState(final AutomationComposition automationComposition, DeployOrder orderedState,
134 Integer startPhaseMsg) {
136 switch (orderedState) {
138 handleUndeployState(automationComposition, startPhaseMsg);
141 handleDeleteState(automationComposition, startPhaseMsg);
145 LOGGER.error("StateChange message has no state, state is null {}", automationComposition.getKey());
151 * Method to handle state changes.
153 * @param automationComposition participant response
154 * @param orderedState automation composition ordered state
155 * @param startPhaseMsg startPhase from message
157 private void handleLockOrderState(final AutomationComposition automationComposition, LockOrder orderedState,
158 Integer startPhaseMsg) {
160 switch (orderedState) {
162 handleLockState(automationComposition, startPhaseMsg);
165 handleUnlockState(automationComposition, startPhaseMsg);
168 LOGGER.error("StateChange message has no state, state is null {}", automationComposition.getKey());
174 * Handle a automation composition properties update message.
176 * @param updateMsg the properties update message
178 public void handleAcPropertyUpdate(PropertiesUpdate updateMsg) {
180 if (updateMsg.getParticipantUpdatesList().isEmpty()) {
181 LOGGER.warn("No AutomationCompositionElement updates in message {}",
182 updateMsg.getAutomationCompositionId());
186 for (var participantDeploy : updateMsg.getParticipantUpdatesList()) {
187 if (cacheProvider.getParticipantId().equals(participantDeploy.getParticipantId())) {
189 updateExistingElementsOnThisParticipant(updateMsg.getAutomationCompositionId(), participantDeploy);
191 callParticipantUpdateProperty(participantDeploy.getAcElementList(),
192 updateMsg.getAutomationCompositionId());
198 * Handle a automation composition Deploy message.
200 * @param deployMsg the Deploy message
202 public void handleAutomationCompositionDeploy(AutomationCompositionDeploy deployMsg) {
204 if (deployMsg.getParticipantUpdatesList().isEmpty()) {
205 LOGGER.warn("No AutomationCompositionElement deploy in message {}", deployMsg.getAutomationCompositionId());
209 for (var participantDeploy : deployMsg.getParticipantUpdatesList()) {
210 if (cacheProvider.getParticipantId().equals(participantDeploy.getParticipantId())) {
211 if (deployMsg.isFirstStartPhase()) {
212 cacheProvider.initializeAutomationComposition(deployMsg.getCompositionId(),
213 deployMsg.getAutomationCompositionId(), participantDeploy);
215 callParticipanDeploy(participantDeploy.getAcElementList(), deployMsg.getStartPhase(),
216 deployMsg.getAutomationCompositionId());
221 private void callParticipanDeploy(List<AcElementDeploy> acElements, Integer startPhaseMsg, UUID instanceId) {
223 for (var element : acElements) {
224 var commonProperties = cacheProvider.getCommonProperties(instanceId, element.getId());
225 int startPhase = ParticipantUtils.findStartPhase(commonProperties);
226 if (startPhaseMsg.equals(startPhase)) {
227 var map = new HashMap<>(commonProperties);
228 map.putAll(element.getProperties());
229 listener.deploy(instanceId, element, map);
232 } catch (PfModelException e) {
233 LOGGER.debug("Automation composition element Deploy failed {}", instanceId);
237 private void callParticipantUpdateProperty(List<AcElementDeploy> acElements, UUID instanceId) {
239 for (var element : acElements) {
240 listener.update(instanceId, element, element.getProperties());
242 } catch (PfModelException e) {
243 LOGGER.debug("Automation composition element update failed {}", instanceId);
247 private void updateExistingElementsOnThisParticipant(UUID instanceId, ParticipantDeploy participantDeploy) {
248 var acElementList = cacheProvider.getAutomationComposition(instanceId).getElements();
249 for (var element : participantDeploy.getAcElementList()) {
250 var acElement = acElementList.get(element.getId());
251 acElement.getProperties().putAll(element.getProperties());
256 * Method to handle when the new state from participant is UNINITIALISED state.
258 * @param automationComposition participant response
259 * @param startPhaseMsg startPhase from message
261 private void handleUndeployState(final AutomationComposition automationComposition, Integer startPhaseMsg) {
263 for (var acElement : automationComposition.getElements().values()) {
264 int startPhase = ParticipantUtils.findStartPhase(
265 cacheProvider.getCommonProperties(automationComposition.getInstanceId(), acElement.getId()));
266 if (startPhaseMsg.equals(startPhase)) {
267 listener.undeploy(automationComposition.getInstanceId(), acElement.getId());
270 } catch (PfModelException e) {
271 LOGGER.debug("Automation composition element Undeploy failed {}", automationComposition.getInstanceId());
275 private void handleDeleteState(final AutomationComposition automationComposition, Integer startPhaseMsg) {
277 for (var acElement : automationComposition.getElements().values()) {
278 int startPhase = ParticipantUtils.findStartPhase(
279 cacheProvider.getCommonProperties(automationComposition.getInstanceId(), acElement.getId()));
280 if (startPhaseMsg.equals(startPhase)) {
281 listener.delete(automationComposition.getInstanceId(), acElement.getId());
284 } catch (PfModelException e) {
285 LOGGER.debug("Automation composition element Delete failed {}", automationComposition.getInstanceId());
290 * Method to handle when the new state from participant is PASSIVE state.
292 * @param automationComposition participant response
293 * @param startPhaseMsg startPhase from message
295 private void handleLockState(final AutomationComposition automationComposition, Integer startPhaseMsg) {
297 for (var acElement : automationComposition.getElements().values()) {
298 int startPhase = ParticipantUtils.findStartPhase(
299 cacheProvider.getCommonProperties(automationComposition.getInstanceId(), acElement.getId()));
300 if (startPhaseMsg.equals(startPhase)) {
301 listener.lock(automationComposition.getInstanceId(), acElement.getId());
304 } catch (PfModelException e) {
305 LOGGER.debug("Automation composition element Lock failed {}", automationComposition.getInstanceId());
310 * Method to handle when the new state from participant is RUNNING state.
312 * @param automationComposition participant response
313 * @param startPhaseMsg startPhase from message
315 private void handleUnlockState(final AutomationComposition automationComposition, Integer startPhaseMsg) {
317 for (var acElement : automationComposition.getElements().values()) {
318 int startPhase = ParticipantUtils.findStartPhase(
319 cacheProvider.getCommonProperties(automationComposition.getInstanceId(), acElement.getId()));
320 if (startPhaseMsg.equals(startPhase)) {
321 listener.unlock(automationComposition.getInstanceId(), acElement.getId());
324 } catch (PfModelException e) {
325 LOGGER.debug("Automation composition element Unlock failed {}", automationComposition.getInstanceId());
330 * Handles prime a Composition Definition.
332 * @param compositionId the compositionId
333 * @param list the list of AutomationCompositionElementDefinition
335 public void prime(UUID compositionId, List<AutomationCompositionElementDefinition> list) {
337 listener.prime(compositionId, list);
338 } catch (PfModelException e) {
339 LOGGER.debug("Composition prime failed {}", compositionId);
344 * Handles deprime a Composition Definition.
346 * @param compositionId the compositionId
348 public void deprime(UUID compositionId) {
350 listener.deprime(compositionId);
351 } catch (PfModelException e) {
352 LOGGER.debug("Composition deprime failed {}", compositionId);