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
 
   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.cache;
 
  23 import java.util.HashMap;
 
  24 import java.util.LinkedHashMap;
 
  25 import java.util.List;
 
  27 import java.util.UUID;
 
  28 import java.util.concurrent.ConcurrentHashMap;
 
  30 import lombok.NonNull;
 
  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;
 
  54 public class CacheProvider {
 
  56     private static final Logger LOGGER = LoggerFactory.getLogger(CacheProvider.class);
 
  59     private final UUID participantId;
 
  63     private boolean registered = false;
 
  66     private final UUID replicaId;
 
  68     private final List<ParticipantSupportedElementType> supportedAcElementTypes;
 
  71     private final Map<UUID, AutomationComposition> automationCompositions = new ConcurrentHashMap<>();
 
  74     private final Map<UUID, AcDefinition> acElementsDefinitions = new ConcurrentHashMap<>();
 
  77     private final Map<UUID, UUID> msgIdentification = new ConcurrentHashMap<>();
 
  80     private final Map<UUID, AutomationCompositionMsg<?>> messagesOnHold = new HashMap<>();
 
  85      * @param parameters the parameters of the participant
 
  87     public CacheProvider(ParticipantParameters parameters) {
 
  88         this.participantId = parameters.getIntermediaryParameters().getParticipantId();
 
  89         this.supportedAcElementTypes = parameters.getIntermediaryParameters().getParticipantSupportedElementTypes();
 
  90         this.replicaId = UUID.randomUUID();
 
  93     public List<ParticipantSupportedElementType> getSupportedAcElementTypes() {
 
  94         return PfUtils.mapList(supportedAcElementTypes, ParticipantSupportedElementType::new);
 
  98      * Get AutomationComposition by id.
 
 100      * @param automationCompositionId the AutomationComposition Id
 
 101      * @return the AutomationComposition
 
 103     public AutomationComposition getAutomationComposition(@NonNull UUID automationCompositionId) {
 
 104         return automationCompositions.get(automationCompositionId);
 
 108      * Remove AutomationComposition.
 
 110      * @param automationCompositionId the AutomationComposition Id
 
 112     public void removeAutomationComposition(@NonNull UUID automationCompositionId) {
 
 113         automationCompositions.remove(automationCompositionId);
 
 117      * Add ElementDefinition.
 
 119      * @param compositionId the composition Id
 
 120      * @param list the list of AutomationCompositionElementDefinition to add
 
 121      * @param revisionId the last Update
 
 123     public void addElementDefinition(@NonNull UUID compositionId, List<AutomationCompositionElementDefinition> list,
 
 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());
 
 132             if (acElementDefinition.getAutomationCompositionElementToscaNodeTemplate().getProperties() == null) {
 
 133                 acElementDefinition.getAutomationCompositionElementToscaNodeTemplate().setProperties(new HashMap<>());
 
 135             acDefinition.getElements().put(acElementDefinition.getAcElementDefinitionId(), acElementDefinition);
 
 137         acElementsDefinitions.put(compositionId, acDefinition);
 
 138         LOGGER.info("Updated cache for the composition id {}", compositionId);
 
 141     public void removeElementDefinition(@NonNull UUID compositionId) {
 
 142         acElementsDefinitions.remove(compositionId);
 
 146      * Get CommonProperties.
 
 148      * @param instanceId the Automation Composition Id
 
 149      * @param acElementId the Automation Composition Element Id
 
 150      * @return the common Properties as Map
 
 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());
 
 159      * Get CommonProperties.
 
 161      * @param compositionId the composition Id
 
 162      * @param definition the AutomationCompositionElementDefinition Id
 
 163      * @return the common Properties as Map
 
 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<>();
 
 171         var map = acDefinition.getElements().get(definition);
 
 172         return map != null ? map.getAutomationCompositionElementToscaNodeTemplate().getProperties() : new HashMap<>();
 
 176      * Initialize an AutomationComposition from a ParticipantDeploy.
 
 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
 
 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);
 
 191      * Initialize an AutomationComposition from a ParticipantDeploy.
 
 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
 
 200     public void initializeAutomationComposition(@NonNull UUID compositionId, UUID compositionTargetId,
 
 201                                                 @NonNull UUID instanceId,
 
 202             ParticipantDeploy participantDeploy, DeployState deployState, SubState subState, UUID revisionId) {
 
 204         var automationComposition = createAcInstance(compositionId, compositionTargetId, instanceId, participantDeploy,
 
 205                 deployState, subState, revisionId);
 
 207         automationCompositions.put(instanceId, automationComposition);
 
 208         LOGGER.info("Initialized participant cache for the {} operation of the instance {}", deployState, instanceId);
 
 213      * Initialize an AutomationComposition from a ParticipantRestartAc.
 
 215      * @param compositionId the composition Id
 
 216      * @param participantRestartAc the ParticipantRestartAc
 
 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())) {
 
 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);
 
 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());
 
 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
 
 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());
 
 280             acElementMap.put(element.getId(), acElement);
 
 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);
 
 288             automationComposition.setElements(acElementMap);
 
 290         automationComposition.setDeployState(deployState);
 
 291         automationComposition.setSubState(subState);
 
 292         automationComposition.setRevisionId(revisionId);
 
 293         if (compositionTargetId != null) {
 
 294             automationComposition.setCompositionTargetId(compositionTargetId);
 
 297         return automationComposition;
 
 301      * Create AutomationCompositionElement to save in memory.
 
 303      * @param element AcElementDeploy
 
 304      * @return a new AutomationCompositionElement
 
 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());
 
 318      * Create CompositionElementDto.
 
 320      * @param compositionId the composition Id
 
 321      * @param element AutomationComposition Element
 
 322      * @return the CompositionElementDto
 
 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;
 
 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);
 
 336      * Get a Map of CompositionElementDto by elementId from the elements of an AutomationComposition.
 
 338      * @param automationComposition the AutomationComposition
 
 339      * @param compositionId the compositionId
 
 340      * @return the Map of CompositionElementDto
 
 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()) :
 
 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);
 
 360     public Map<UUID, CompositionElementDto> getCompositionElementDtoMap(AutomationComposition automationComposition) {
 
 361         return getCompositionElementDtoMap(automationComposition, automationComposition.getCompositionId());
 
 365      * Get a Map of InstanceElementDto by elementId from the elements of an AutomationComposition.
 
 367      * @param automationComposition the AutomationComposition
 
 368      * @return the Map of InstanceElementDto
 
 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);
 
 381      * Create a new InstanceElementDto record with state New.
 
 383      * @param instanceElement the InstanceElementDto
 
 384      * @return a new InstanceElementDto
 
 386     public static InstanceElementDto changeStateToNew(InstanceElementDto instanceElement) {
 
 387         return new InstanceElementDto(instanceElement.instanceId(), instanceElement.elementId(),
 
 388                 instanceElement.inProperties(), instanceElement.outProperties(), ElementState.NEW);
 
 392      * Create a new CompositionElementDto record with state New.
 
 394      * @param compositionElement the CompositionElementDto
 
 395      * @return a new CompositionElementDto
 
 397     public static CompositionElementDto changeStateToNew(CompositionElementDto compositionElement) {
 
 398         return new CompositionElementDto(compositionElement.compositionId(), compositionElement.elementDefinitionId(),
 
 399                 compositionElement.inProperties(), compositionElement.outProperties(), ElementState.NEW);
 
 403      * Check composition is present and compare the last update.
 
 405      * @param compositionId the instanceId
 
 406      * @param revisionId the last Update
 
 407      * @return true if the composition is updated
 
 409     public boolean isCompositionDefinitionUpdated(UUID compositionId, UUID revisionId) {
 
 410         if (revisionId == null) {
 
 414         var acDefinition = acElementsDefinitions.get(compositionId);
 
 415         if (acDefinition == null) {
 
 418         return revisionId.equals(acDefinition.getRevisionId());
 
 422      * Check instance is present and compare the last update.
 
 424      * @param instanceId the instanceId
 
 425      * @param revisionId the last Update
 
 426      * @return true if the instance is updated
 
 428     public boolean isInstanceUpdated(UUID instanceId, UUID revisionId) {
 
 429         if (revisionId == null) {
 
 433         var automationComposition = automationCompositions.get(instanceId);
 
 434         if (automationComposition == null) {
 
 437         return revisionId.equals(automationComposition.getRevisionId());