2  * ============LICENSE_START=======================================================
 
   3  * Copyright (C) 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.runtime.supervision.scanner;
 
  23 import java.util.UUID;
 
  24 import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup;
 
  25 import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher;
 
  26 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
 
  27 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition;
 
  28 import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils;
 
  29 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
 
  30 import org.onap.policy.clamp.models.acm.document.concepts.DocMessage;
 
  31 import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider;
 
  32 import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
 
  33 import org.slf4j.Logger;
 
  34 import org.slf4j.LoggerFactory;
 
  35 import org.springframework.stereotype.Component;
 
  38 public class AcDefinitionScanner {
 
  39     private static final Logger LOGGER = LoggerFactory.getLogger(AcDefinitionScanner.class);
 
  41     private final long maxOperationWaitMs;
 
  43     private final AcDefinitionProvider acDefinitionProvider;
 
  44     private final ParticipantSyncPublisher participantSyncPublisher;
 
  47      * Constructor for instantiating AcDefinitionScanner.
 
  49      * @param acDefinitionProvider the Policy Models Provider
 
  50      * @param participantSyncPublisher the Participant Sync Publisher
 
  51      * @param acRuntimeParameterGroup the parameters for the automation composition runtime
 
  53     public AcDefinitionScanner(final AcDefinitionProvider acDefinitionProvider,
 
  54             final ParticipantSyncPublisher participantSyncPublisher,
 
  55             final AcRuntimeParameterGroup acRuntimeParameterGroup) {
 
  56         this.acDefinitionProvider = acDefinitionProvider;
 
  57         this.participantSyncPublisher = participantSyncPublisher;
 
  58         this.maxOperationWaitMs = acRuntimeParameterGroup.getParticipantParameters().getMaxOperationWaitMs();
 
  61     private UpdateSync handlePrimeAckElement(DocMessage message, AutomationCompositionDefinition acDefinition) {
 
  62         var result = new UpdateSync();
 
  63         if (StateChangeResult.FAILED.equals(message.getStateChangeResult())) {
 
  64             acDefinition.setStateChangeResult(StateChangeResult.FAILED);
 
  65             result.setUpdated(true);
 
  66             result.setToBeSync(true);
 
  68         for (var element : acDefinition.getElementStateMap().values()) {
 
  69             if (message.getParticipantId().equals(element.getParticipantId())) {
 
  70                 element.setMessage(message.getMessage());
 
  71                 element.setState(message.getCompositionState());
 
  72                 result.setUpdated(true);
 
  78     private UpdateSync handleOutProperties(DocMessage message, AutomationCompositionDefinition acDefinition) {
 
  79         var elementOpt = acDefinition.getElementStateMap().values().stream()
 
  80                 .filter(element -> element.getNodeTemplateId().equals(message.getAcElementDefinitionId())).findFirst();
 
  82         var result = new UpdateSync();
 
  83         if (elementOpt.isPresent()) {
 
  84             elementOpt.get().setOutProperties(message.getOutProperties());
 
  85             result.setUpdated(true);
 
  86             result.setToBeSync(true);
 
  94      * @param acDefinition the AutomationComposition Definition
 
  95      * @param message the message
 
  97     public UpdateSync scanMessage(AutomationCompositionDefinition acDefinition, DocMessage message) {
 
  98         return switch (message.getMessageType()) {
 
  99             case PARTICIPANT_STATUS -> handleOutProperties(message, acDefinition);
 
 100             case PARTICIPANT_PRIME_ACK -> handlePrimeAckElement(message, acDefinition);
 
 102                 LOGGER.debug("Not valid MessageType {}", message.getMessageType());
 
 103                 yield new UpdateSync();
 
 109      * Scan an AutomationComposition Definition.
 
 111      * @param acDefinition the AutomationComposition Definition
 
 112      * @param updateSync defines if true if the composition has to be saved or sync
 
 114     public void scanAutomationCompositionDefinition(AutomationCompositionDefinition acDefinition,
 
 115             UpdateSync updateSync) {
 
 116         if (StateChangeResult.FAILED.equals(acDefinition.getStateChangeResult())) {
 
 117             LOGGER.debug("automation definition {} scanned, OK", acDefinition.getCompositionId());
 
 118             updateAcDefinitionState(acDefinition, updateSync);
 
 122         boolean completed = true;
 
 123         var finalState = AcTypeState.PRIMING.equals(acDefinition.getState())
 
 124                 || AcTypeState.PRIMED.equals(acDefinition.getState()) ? AcTypeState.PRIMED : AcTypeState.COMMISSIONED;
 
 125         for (var element : acDefinition.getElementStateMap().values()) {
 
 126             if (!finalState.equals(element.getState())) {
 
 132             acDefinition.setState(finalState);
 
 133             acDefinition.setStateChangeResult(StateChangeResult.NO_ERROR);
 
 134             updateSync.setUpdated(true);
 
 135             updateSync.setToBeSync(true);
 
 137             updateSync.or(handleTimeout(acDefinition));
 
 139         updateAcDefinitionState(acDefinition, updateSync);
 
 142     private UpdateSync handleTimeout(AutomationCompositionDefinition acDefinition) {
 
 143         var result = new UpdateSync();
 
 144         if (StateChangeResult.TIMEOUT.equals(acDefinition.getStateChangeResult())) {
 
 145             LOGGER.debug("The ac definition is in timeout {}", acDefinition.getCompositionId());
 
 148         var name = ParticipantUtils.getOpName(acDefinition.getState());
 
 149         var maxWaitMs = ParticipantUtils
 
 150                 .getTimeout(acDefinition.getServiceTemplate().getMetadata(), name, maxOperationWaitMs);
 
 151         var lastMsg = TimestampHelper.toEpochMilli(acDefinition.getLastMsg());
 
 152         var now = TimestampHelper.nowEpochMilli();
 
 153         if ((now - lastMsg) > maxWaitMs) {
 
 154             LOGGER.debug("Report timeout for the ac definition {}", acDefinition.getCompositionId());
 
 155             acDefinition.setStateChangeResult(StateChangeResult.TIMEOUT);
 
 156             result.setUpdated(true);
 
 157             result.setToBeSync(true);
 
 162     private void updateAcDefinitionState(AutomationCompositionDefinition acDefinition,
 
 163             UpdateSync updateSync) {
 
 164         if (updateSync.isUpdated()) {
 
 165             acDefinition.setRevisionId(UUID.randomUUID());
 
 166             acDefinitionProvider.updateAcDefinitionState(acDefinition);
 
 168         if (updateSync.isToBeSync()) {
 
 169             participantSyncPublisher.sendSync(acDefinition, null);