2  * ============LICENSE_START=======================================================
 
   3  *  Copyright (C) 2023-2024 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
 
   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.comm.ParticipantMessagePublisher;
 
  28 import org.onap.policy.clamp.models.acm.concepts.AcElementDeployAck;
 
  29 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
 
  30 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
 
  31 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
 
  32 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition;
 
  33 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementInfo;
 
  34 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionInfo;
 
  35 import org.onap.policy.clamp.models.acm.concepts.DeployState;
 
  36 import org.onap.policy.clamp.models.acm.concepts.LockState;
 
  37 import org.onap.policy.clamp.models.acm.concepts.ParticipantDefinition;
 
  38 import org.onap.policy.clamp.models.acm.concepts.ParticipantState;
 
  39 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
 
  40 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeployAck;
 
  41 import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantMessageType;
 
  42 import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantPrimeAck;
 
  43 import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantStatus;
 
  44 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 
  45 import org.slf4j.Logger;
 
  46 import org.slf4j.LoggerFactory;
 
  47 import org.springframework.stereotype.Component;
 
  50 @RequiredArgsConstructor
 
  51 public class AutomationCompositionOutHandler {
 
  52     private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionOutHandler.class);
 
  54     private final ParticipantMessagePublisher publisher;
 
  55     private final CacheProvider cacheProvider;
 
  58      * Handle a automation composition element state change message.
 
  60      * @param automationCompositionId the automationComposition Id
 
  61      * @param elementId the automationComposition Element Id
 
  62      * @param deployState the DeployState state
 
  63      * @param lockState the LockState state
 
  64      * @param message the message
 
  65      * @param stateChangeResult the indicator if error occurs
 
  67     public void updateAutomationCompositionElementState(UUID automationCompositionId, UUID elementId,
 
  68             DeployState deployState, LockState lockState, StateChangeResult stateChangeResult, String message) {
 
  70         if (automationCompositionId == null || elementId == null) {
 
  71             LOGGER.error("Cannot update Automation composition element state, id is null");
 
  75         var automationComposition = cacheProvider.getAutomationComposition(automationCompositionId);
 
  76         if (automationComposition == null) {
 
  77             LOGGER.error("Cannot update Automation composition element state, Automation composition id {} not present",
 
  78                     automationCompositionId);
 
  82         var element = automationComposition.getElements().get(elementId);
 
  83         if (element == null) {
 
  84             var msg = "Cannot update Automation composition element state, AC Element id {} not present";
 
  85             LOGGER.error(msg, elementId);
 
  89         if ((element.getRestarting() == null)
 
  90                 && ((deployState != null && lockState != null) || (deployState == null && lockState == null))) {
 
  91             LOGGER.error("state error {} and {} cannot be handled", deployState, lockState);
 
  94         element.setRestarting(null);
 
  96         if (deployState != null) {
 
  97             handleDeployState(automationComposition, element, deployState);
 
  99         if (lockState != null) {
 
 100             handleLockState(automationComposition, element, lockState);
 
 103         var automationCompositionStateChangeAck =
 
 104                 new AutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK);
 
 105         automationCompositionStateChangeAck.setParticipantId(cacheProvider.getParticipantId());
 
 106         automationCompositionStateChangeAck.setReplicaId(cacheProvider.getReplicaId());
 
 107         automationCompositionStateChangeAck.setMessage(message);
 
 108         automationCompositionStateChangeAck.setResponseTo(cacheProvider.getMsgIdentification().get(element.getId()));
 
 109         automationCompositionStateChangeAck.setStateChangeResult(stateChangeResult);
 
 110         automationCompositionStateChangeAck.setAutomationCompositionId(automationCompositionId);
 
 111         automationCompositionStateChangeAck.getAutomationCompositionResultMap().put(element.getId(),
 
 112                 new AcElementDeployAck(element.getDeployState(), element.getLockState(), element.getOperationalState(),
 
 113                         element.getUseState(), element.getOutProperties(), true, message));
 
 114         LOGGER.debug("Automation composition element {} state changed to {}", elementId, deployState);
 
 115         automationCompositionStateChangeAck.setResult(true);
 
 116         publisher.sendAutomationCompositionAck(automationCompositionStateChangeAck);
 
 117         cacheProvider.getMsgIdentification().remove(element.getId());
 
 120     private void handleDeployState(AutomationComposition automationComposition, AutomationCompositionElement element,
 
 121             DeployState deployState) {
 
 122         element.setDeployState(deployState);
 
 123         element.setLockState(DeployState.DEPLOYED.equals(element.getDeployState()) ? LockState.LOCKED : LockState.NONE);
 
 124         var checkOpt = automationComposition.getElements().values().stream()
 
 125                 .filter(acElement -> !deployState.equals(acElement.getDeployState())).findAny();
 
 126         if (checkOpt.isEmpty()) {
 
 127             if (DeployState.DEPLOYED.equals(automationComposition.getDeployState())
 
 128                     && automationComposition.getCompositionTargetId() != null) {
 
 129                 // migration scenario
 
 130                 automationComposition.setCompositionId(automationComposition.getCompositionTargetId());
 
 131                 automationComposition.setCompositionTargetId(null);
 
 133             automationComposition.setDeployState(deployState);
 
 134             automationComposition.setLockState(element.getLockState());
 
 136             if (DeployState.DELETED.equals(deployState)) {
 
 137                 cacheProvider.removeAutomationComposition(automationComposition.getInstanceId());
 
 142     private void handleLockState(AutomationComposition automationComposition, AutomationCompositionElement element,
 
 143             LockState lockState) {
 
 144         element.setLockState(lockState);
 
 145         var checkOpt = automationComposition.getElements().values().stream()
 
 146                 .filter(acElement -> !lockState.equals(acElement.getLockState())).findAny();
 
 147         if (checkOpt.isEmpty()) {
 
 148             automationComposition.setLockState(lockState);
 
 153      * Send Ac Element Info.
 
 155      * @param automationCompositionId the automationComposition Id
 
 156      * @param elementId the automationComposition Element id
 
 157      * @param useState the use State
 
 158      * @param operationalState the operational State
 
 159      * @param outProperties the output Properties Map
 
 161     public void sendAcElementInfo(UUID automationCompositionId, UUID elementId, String useState,
 
 162             String operationalState, Map<String, Object> outProperties) {
 
 164         if (automationCompositionId == null || elementId == null) {
 
 165             LOGGER.error("Cannot update Automation composition element state, id is null");
 
 169         var automationComposition = cacheProvider.getAutomationComposition(automationCompositionId);
 
 170         if (automationComposition == null) {
 
 171             LOGGER.error("Cannot update Automation composition element state, Automation composition id {} not present",
 
 172                     automationCompositionId);
 
 176         var element = automationComposition.getElements().get(elementId);
 
 177         if (element == null) {
 
 178             var msg = "Cannot update Automation composition element state, AC Element id {} not present";
 
 179             LOGGER.error(msg, elementId);
 
 182         element.setOperationalState(operationalState);
 
 183         element.setUseState(useState);
 
 184         element.setOutProperties(outProperties);
 
 186         var acInfo = new AutomationCompositionInfo();
 
 187         acInfo.setAutomationCompositionId(automationCompositionId);
 
 188         acInfo.setDeployState(automationComposition.getDeployState());
 
 189         acInfo.setLockState(automationComposition.getLockState());
 
 190         acInfo.setElements(List.of(getAutomationCompositionElementInfo(element)));
 
 191         var statusMsg = createParticipantStatus();
 
 192         statusMsg.setCompositionId(automationComposition.getCompositionId());
 
 193         statusMsg.setAutomationCompositionInfoList(List.of(acInfo));
 
 194         publisher.sendParticipantStatus(statusMsg);
 
 198      * Get AutomationCompositionElementInfo from AutomationCompositionElement.
 
 200      * @param element the AutomationCompositionElement
 
 201      * @return the AutomationCompositionElementInfo
 
 203     public AutomationCompositionElementInfo getAutomationCompositionElementInfo(AutomationCompositionElement element) {
 
 204         var elementInfo = new AutomationCompositionElementInfo();
 
 205         elementInfo.setAutomationCompositionElementId(element.getId());
 
 206         elementInfo.setDeployState(element.getDeployState());
 
 207         elementInfo.setLockState(element.getLockState());
 
 208         elementInfo.setOperationalState(element.getOperationalState());
 
 209         elementInfo.setUseState(element.getUseState());
 
 210         elementInfo.setOutProperties(element.getOutProperties());
 
 215      * Update Composition State for prime and deprime.
 
 217      * @param compositionId the composition id
 
 218      * @param state the Composition State
 
 219      * @param stateChangeResult the indicator if error occurs
 
 220      * @param message the message
 
 222     public void updateCompositionState(UUID compositionId, AcTypeState state, StateChangeResult stateChangeResult,
 
 224         var participantPrimeAck = new ParticipantPrimeAck();
 
 225         participantPrimeAck.setCompositionId(compositionId);
 
 226         participantPrimeAck.setMessage(message);
 
 227         participantPrimeAck.setResult(true);
 
 228         participantPrimeAck.setResponseTo(cacheProvider.getMsgIdentification().get(compositionId));
 
 229         participantPrimeAck.setCompositionState(state);
 
 230         participantPrimeAck.setStateChangeResult(stateChangeResult);
 
 231         participantPrimeAck.setParticipantId(cacheProvider.getParticipantId());
 
 232         participantPrimeAck.setReplicaId(cacheProvider.getReplicaId());
 
 233         participantPrimeAck.setState(ParticipantState.ON_LINE);
 
 234         publisher.sendParticipantPrimeAck(participantPrimeAck);
 
 235         cacheProvider.getMsgIdentification().remove(compositionId);
 
 236         if (AcTypeState.COMMISSIONED.equals(state) && StateChangeResult.NO_ERROR.equals(stateChangeResult)) {
 
 237             cacheProvider.removeElementDefinition(compositionId);
 
 242      * Send Composition Definition Info.
 
 244      * @param compositionId the composition id
 
 245      * @param elementId the Composition Definition Element id
 
 246      * @param outProperties the output Properties Map
 
 248     public void sendAcDefinitionInfo(UUID compositionId, ToscaConceptIdentifier elementId,
 
 249             Map<String, Object> outProperties) {
 
 250         if (compositionId == null) {
 
 251             LOGGER.error("Cannot send Composition outProperties, id is null");
 
 254         var statusMsg = createParticipantStatus();
 
 255         statusMsg.setCompositionId(compositionId);
 
 256         var acElementDefsMap = cacheProvider.getAcElementsDefinitions();
 
 257         var acElementsDefinitions = acElementDefsMap.get(compositionId);
 
 258         if (acElementsDefinitions == null) {
 
 259             LOGGER.error("Cannot send Composition outProperties, id {} is null", compositionId);
 
 262         var acElementDefinition = getAutomationCompositionElementDefinition(acElementsDefinitions, elementId);
 
 263         if (acElementDefinition == null) {
 
 264             LOGGER.error("Cannot send Composition outProperties, elementId {} not present", elementId);
 
 267         acElementDefinition.setOutProperties(outProperties);
 
 268         var participantDefinition = new ParticipantDefinition();
 
 269         participantDefinition.setParticipantId(cacheProvider.getParticipantId());
 
 270         participantDefinition.setAutomationCompositionElementDefinitionList(List.of(acElementDefinition));
 
 271         statusMsg.setParticipantDefinitionUpdates(List.of(participantDefinition));
 
 272         publisher.sendParticipantStatus(statusMsg);
 
 275     private AutomationCompositionElementDefinition getAutomationCompositionElementDefinition(
 
 276             Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition> acElementsDefinition,
 
 277             ToscaConceptIdentifier elementId) {
 
 279         if (elementId == null) {
 
 280             if (acElementsDefinition.size() == 1) {
 
 281                 return acElementsDefinition.values().iterator().next();
 
 285         return acElementsDefinition.get(elementId);
 
 288     private ParticipantStatus createParticipantStatus() {
 
 289         var statusMsg = new ParticipantStatus();
 
 290         statusMsg.setParticipantId(cacheProvider.getParticipantId());
 
 291         statusMsg.setReplicaId(cacheProvider.getReplicaId());
 
 292         statusMsg.setState(ParticipantState.ON_LINE);
 
 293         statusMsg.setParticipantSupportedElementType(cacheProvider.getSupportedAcElementTypes());