d33498518240b5c199dce5b6af29870ef008f302
[policy/clamp.git] /
1 /*-
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.clamp.acm.participant.intermediary.handler;
23
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.LinkedHashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.UUID;
30 import lombok.Getter;
31 import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener;
32 import org.onap.policy.clamp.acm.participant.intermediary.comm.ParticipantMessagePublisher;
33 import org.onap.policy.clamp.acm.participant.intermediary.parameters.ParticipantParameters;
34 import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
35 import org.onap.policy.clamp.models.acm.concepts.AcElementDeployAck;
36 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
37 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
38 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition;
39 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementInfo;
40 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionInfo;
41 import org.onap.policy.clamp.models.acm.concepts.DeployState;
42 import org.onap.policy.clamp.models.acm.concepts.LockState;
43 import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy;
44 import org.onap.policy.clamp.models.acm.concepts.ParticipantState;
45 import org.onap.policy.clamp.models.acm.concepts.ParticipantSupportedElementType;
46 import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils;
47 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionDeploy;
48 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionDeployAck;
49 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionStateChange;
50 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantMessageType;
51 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantStatus;
52 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
53 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder;
54 import org.onap.policy.clamp.models.acm.persistence.provider.AcInstanceStateResolver;
55 import org.onap.policy.models.base.PfModelException;
56 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
57 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60 import org.springframework.stereotype.Component;
61
62 /*
63  * This class is responsible for managing the state of all automation compositions in the participant.
64  */
65 @Component
66 public class AutomationCompositionHandler {
67     private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionHandler.class);
68
69     private final UUID participantId;
70     private final ParticipantMessagePublisher publisher;
71     private final AcInstanceStateResolver acInstanceStateResolver;
72     private final List<ParticipantSupportedElementType> supportedAcElementTypes;
73     private final List<AutomationCompositionElementListener> listeners = new ArrayList<>();
74
75     @Getter
76     private final Map<UUID, AutomationComposition> automationCompositionMap = new LinkedHashMap<>();
77
78     /**
79      * Constructor, set the participant ID and messageSender.
80      *
81      * @param parameters the parameters of the participant
82      * @param publisher the ParticipantMessage Publisher
83      */
84     public AutomationCompositionHandler(ParticipantParameters parameters, ParticipantMessagePublisher publisher) {
85         this.participantId = parameters.getIntermediaryParameters().getParticipantId();
86         this.publisher = publisher;
87         this.acInstanceStateResolver = new AcInstanceStateResolver();
88         this.supportedAcElementTypes = parameters.getIntermediaryParameters().getParticipantSupportedElementTypes();
89     }
90
91     public void registerAutomationCompositionElementListener(AutomationCompositionElementListener listener) {
92         listeners.add(listener);
93     }
94
95     /**
96      * Handle a automation composition element state change message.
97      *
98      * @param automationCompositionId the automationComposition Id
99      * @param id the automationComposition UUID
100      * @param deployState the DeployState state
101      * @param lockState the LockState state
102      */
103     public void updateAutomationCompositionElementState(UUID automationCompositionId, UUID id, DeployState deployState,
104             LockState lockState, String message) {
105
106         if (automationCompositionId == null || id == null) {
107             LOGGER.error("Cannot update Automation composition element state, id is null");
108             return;
109         }
110
111         if ((deployState != null && lockState != null) || (deployState == null && lockState == null)) {
112             LOGGER.error("state error {} and {} cannot be handled", deployState, lockState);
113             return;
114         }
115
116         var automationComposition = automationCompositionMap.get(automationCompositionId);
117         if (automationComposition == null) {
118             LOGGER.error("Cannot update Automation composition element state, Automation composition id {} not present",
119                     automationComposition);
120             return;
121         }
122
123         var element = automationComposition.getElements().get(id);
124         if (element == null) {
125             var msg = "Cannot update Automation composition element state, AC Element id {} not present";
126             LOGGER.error(msg, automationComposition);
127             return;
128         }
129
130         if (deployState != null) {
131             element.setDeployState(deployState);
132             element.setLockState(
133                     DeployState.DEPLOYED.equals(element.getDeployState()) ? LockState.LOCKED : LockState.NONE);
134             var checkOpt = automationComposition.getElements().values().stream()
135                     .filter(acElement -> !deployState.equals(acElement.getDeployState())).findAny();
136             if (checkOpt.isEmpty()) {
137                 automationComposition.setDeployState(deployState);
138                 automationComposition.setLockState(element.getLockState());
139             }
140         }
141         if (lockState != null) {
142             element.setLockState(lockState);
143             var checkOpt = automationComposition.getElements().values().stream()
144                     .filter(acElement -> !lockState.equals(acElement.getLockState())).findAny();
145             if (checkOpt.isEmpty()) {
146                 automationComposition.setLockState(lockState);
147             }
148         }
149
150         var automationCompositionStateChangeAck =
151                 new AutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK);
152         automationCompositionStateChangeAck.setParticipantId(participantId);
153         automationCompositionStateChangeAck.setMessage(message);
154         automationCompositionStateChangeAck.setAutomationCompositionId(automationCompositionId);
155         automationCompositionStateChangeAck.getAutomationCompositionResultMap().put(element.getId(),
156                 new AcElementDeployAck(element.getDeployState(), element.getLockState(), element.getOperationalState(),
157                         element.getUseState(), element.getOutProperties(), true,
158                         "Automation composition element {} state changed to {}\", id, newState)"));
159         LOGGER.debug("Automation composition element {} state changed to {}", id, deployState);
160         automationCompositionStateChangeAck.setResult(true);
161         publisher.sendAutomationCompositionAck(automationCompositionStateChangeAck);
162     }
163
164     /**
165      * Handle a automation composition state change message.
166      *
167      * @param stateChangeMsg the state change message
168      * @param acElementDefinitions the list of AutomationCompositionElementDefinition
169      */
170     public void handleAutomationCompositionStateChange(AutomationCompositionStateChange stateChangeMsg,
171             List<AutomationCompositionElementDefinition> acElementDefinitions) {
172         if (stateChangeMsg.getAutomationCompositionId() == null) {
173             return;
174         }
175
176         var automationComposition = automationCompositionMap.get(stateChangeMsg.getAutomationCompositionId());
177
178         if (automationComposition == null) {
179             var automationCompositionAck =
180                     new AutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK);
181             automationCompositionAck.setParticipantId(participantId);
182             automationCompositionAck.setMessage("Automation composition " + stateChangeMsg.getAutomationCompositionId()
183                     + " does not use this participant " + participantId);
184             automationCompositionAck.setResult(false);
185             automationCompositionAck.setResponseTo(stateChangeMsg.getMessageId());
186             automationCompositionAck.setAutomationCompositionId(stateChangeMsg.getAutomationCompositionId());
187             publisher.sendAutomationCompositionAck(automationCompositionAck);
188             LOGGER.debug("Automation composition {} does not use this participant",
189                     stateChangeMsg.getAutomationCompositionId());
190             return;
191         }
192
193         if (!checkConsistantOrderState(automationComposition, stateChangeMsg.getDeployOrderedState(),
194                 stateChangeMsg.getLockOrderedState())) {
195             LOGGER.warn("Not Consistant OrderState Automation composition {}",
196                     stateChangeMsg.getAutomationCompositionId());
197             return;
198         }
199
200         if (DeployOrder.NONE.equals(stateChangeMsg.getDeployOrderedState())) {
201             handleLockOrderState(automationComposition, stateChangeMsg.getLockOrderedState(),
202                     stateChangeMsg.getStartPhase(), acElementDefinitions);
203         } else {
204             handleDeployOrderState(automationComposition, stateChangeMsg.getDeployOrderedState(),
205                     stateChangeMsg.getStartPhase(), acElementDefinitions);
206         }
207     }
208
209     private boolean checkConsistantOrderState(AutomationComposition automationComposition, DeployOrder deployOrder,
210             LockOrder lockOrder) {
211         return acInstanceStateResolver.resolve(deployOrder, lockOrder, automationComposition.getDeployState(),
212                 automationComposition.getLockState()) != null;
213     }
214
215     /**
216      * Method to handle state changes.
217      *
218      * @param automationComposition participant response
219      * @param orderedState automation composition ordered state
220      * @param startPhaseMsg startPhase from message
221      * @param acElementDefinitions the list of AutomationCompositionElementDefinition
222      */
223     private void handleDeployOrderState(final AutomationComposition automationComposition, DeployOrder orderedState,
224             Integer startPhaseMsg, List<AutomationCompositionElementDefinition> acElementDefinitions) {
225
226         switch (orderedState) {
227             case UNDEPLOY:
228                 handleUndeployState(automationComposition, startPhaseMsg, acElementDefinitions);
229                 break;
230             case DELETE:
231                 handleDeleteState(automationComposition, startPhaseMsg, acElementDefinitions);
232                 break;
233
234             default:
235                 LOGGER.debug("StateChange message has no state, state is null {}", automationComposition.getKey());
236                 break;
237         }
238     }
239
240     /**
241      * Method to handle state changes.
242      *
243      * @param automationComposition participant response
244      * @param orderedState automation composition ordered state
245      * @param startPhaseMsg startPhase from message
246      * @param acElementDefinitions the list of AutomationCompositionElementDefinition
247      */
248     private void handleLockOrderState(final AutomationComposition automationComposition, LockOrder orderedState,
249             Integer startPhaseMsg, List<AutomationCompositionElementDefinition> acElementDefinitions) {
250
251         switch (orderedState) {
252             case LOCK:
253                 handleLockState(automationComposition, startPhaseMsg, acElementDefinitions);
254                 break;
255             case UNLOCK:
256                 handleUnlockState(automationComposition, startPhaseMsg, acElementDefinitions);
257                 break;
258             default:
259                 LOGGER.debug("StateChange message has no state, state is null {}", automationComposition.getKey());
260                 break;
261         }
262     }
263
264     /**
265      * Handle a automation composition Deploy message.
266      *
267      * @param updateMsg the Deploy message
268      * @param acElementDefinitions the list of AutomationCompositionElementDefinition
269      */
270     public void handleAutomationCompositionDeploy(AutomationCompositionDeploy updateMsg,
271             List<AutomationCompositionElementDefinition> acElementDefinitions) {
272
273         if (updateMsg.getParticipantUpdatesList().isEmpty()) {
274             LOGGER.warn("No AutomationCompositionElement updates in message {}",
275                     updateMsg.getAutomationCompositionId());
276             return;
277         }
278
279         for (var participantDeploy : updateMsg.getParticipantUpdatesList()) {
280             if (participantId.equals(participantDeploy.getParticipantId())) {
281                 if (updateMsg.isFirstStartPhase()) {
282                     initializeDeploy(updateMsg.getMessageId(), updateMsg.getAutomationCompositionId(),
283                             participantDeploy);
284                 }
285                 callParticipanDeploy(participantDeploy.getAcElementList(), acElementDefinitions,
286                         updateMsg.getStartPhase(), updateMsg.getAutomationCompositionId());
287             }
288         }
289     }
290
291     private void initializeDeploy(UUID messageId, UUID instanceId, ParticipantDeploy participantDeploy) {
292         var automationComposition = new AutomationComposition();
293         automationComposition.setInstanceId(instanceId);
294         var acElements = storeElementsOnThisParticipant(participantDeploy);
295         automationComposition.setElements(prepareAcElementMap(acElements));
296         automationCompositionMap.put(instanceId, automationComposition);
297     }
298
299     private void callParticipanDeploy(List<AcElementDeploy> acElements,
300             List<AutomationCompositionElementDefinition> acElementDefinitions, Integer startPhaseMsg,
301             UUID automationCompositionId) {
302         try {
303             for (var element : acElements) {
304                 var acElementNodeTemplate = getAcElementNodeTemplate(acElementDefinitions, element.getDefinition());
305                 if (acElementNodeTemplate != null) {
306                     int startPhase = ParticipantUtils.findStartPhase(acElementNodeTemplate.getProperties());
307                     if (startPhaseMsg.equals(startPhase)) {
308                         for (var acElementListener : listeners) {
309                             var map = new HashMap<>(acElementNodeTemplate.getProperties());
310                             map.putAll(element.getProperties());
311                             acElementListener.deploy(automationCompositionId, element, map);
312                         }
313                     }
314                 }
315             }
316         } catch (PfModelException e) {
317             LOGGER.debug("Automation composition element update failed {}", automationCompositionId);
318         }
319
320     }
321
322     private ToscaNodeTemplate getAcElementNodeTemplate(
323             List<AutomationCompositionElementDefinition> acElementDefinitions, ToscaConceptIdentifier acElementDefId) {
324
325         for (var acElementDefinition : acElementDefinitions) {
326             if (acElementDefId.getName().contains(acElementDefinition.getAcElementDefinitionId().getName())) {
327                 return acElementDefinition.getAutomationCompositionElementToscaNodeTemplate();
328             }
329         }
330         return null;
331     }
332
333     private List<AutomationCompositionElement> storeElementsOnThisParticipant(ParticipantDeploy participantDeploy) {
334         List<AutomationCompositionElement> acElementList = new ArrayList<>();
335         for (var element : participantDeploy.getAcElementList()) {
336             var acElement = new AutomationCompositionElement();
337             acElement.setId(element.getId());
338             acElement.setParticipantId(participantDeploy.getParticipantId());
339             acElement.setDefinition(element.getDefinition());
340             acElement.setDeployState(DeployState.DEPLOYING);
341             acElement.setLockState(LockState.NONE);
342             acElementList.add(acElement);
343         }
344         return acElementList;
345     }
346
347     private Map<UUID, AutomationCompositionElement> prepareAcElementMap(List<AutomationCompositionElement> acElements) {
348         Map<UUID, AutomationCompositionElement> acElementMap = new LinkedHashMap<>();
349         for (var element : acElements) {
350             acElementMap.put(element.getId(), element);
351         }
352         return acElementMap;
353     }
354
355     /**
356      * Method to handle when the new state from participant is UNINITIALISED state.
357      *
358      * @param automationComposition participant response
359      * @param startPhaseMsg startPhase from message
360      * @param acElementDefinitions the list of AutomationCompositionElementDefinition
361      */
362     private void handleUndeployState(final AutomationComposition automationComposition, Integer startPhaseMsg,
363             List<AutomationCompositionElementDefinition> acElementDefinitions) {
364
365         automationComposition.getElements().values().stream()
366                 .forEach(acElement -> automationCompositionElementUndeploy(automationComposition.getInstanceId(),
367                         acElement, startPhaseMsg, acElementDefinitions));
368     }
369
370     private void handleDeleteState(final AutomationComposition automationComposition, Integer startPhaseMsg,
371             List<AutomationCompositionElementDefinition> acElementDefinitions) {
372
373         automationComposition.getElements().values().stream()
374                 .forEach(acElement -> automationCompositionElementDelete(automationComposition.getInstanceId(),
375                         acElement, startPhaseMsg, acElementDefinitions));
376
377         boolean isAllUninitialised = automationComposition.getElements().values().stream()
378                 .filter(element -> !DeployState.DELETED.equals(element.getDeployState())).findAny().isEmpty();
379         if (isAllUninitialised) {
380             automationCompositionMap.remove(automationComposition.getInstanceId());
381         }
382     }
383
384     /**
385      * Method to handle when the new state from participant is PASSIVE state.
386      *
387      * @param automationComposition participant response
388      * @param startPhaseMsg startPhase from message
389      * @param acElementDefinitions the list of AutomationCompositionElementDefinition
390      */
391     private void handleLockState(final AutomationComposition automationComposition, Integer startPhaseMsg,
392             List<AutomationCompositionElementDefinition> acElementDefinitions) {
393         automationComposition.getElements().values().stream()
394                 .forEach(acElement -> automationCompositionElementLock(automationComposition.getInstanceId(), acElement,
395                         startPhaseMsg, acElementDefinitions));
396     }
397
398     /**
399      * Method to handle when the new state from participant is RUNNING state.
400      *
401      * @param automationComposition participant response
402      * @param startPhaseMsg startPhase from message
403      * @param acElementDefinitions the list of AutomationCompositionElementDefinition
404      */
405     private void handleUnlockState(final AutomationComposition automationComposition, Integer startPhaseMsg,
406             List<AutomationCompositionElementDefinition> acElementDefinitions) {
407         automationComposition.getElements().values().stream()
408                 .forEach(acElement -> automationCompositionElementUnlock(automationComposition.getInstanceId(),
409                         acElement, startPhaseMsg, acElementDefinitions));
410     }
411
412     private void automationCompositionElementLock(UUID instanceId, AutomationCompositionElement acElement,
413             Integer startPhaseMsg, List<AutomationCompositionElementDefinition> acElementDefinitions) {
414         var acElementNodeTemplate = getAcElementNodeTemplate(acElementDefinitions, acElement.getDefinition());
415         if (acElementNodeTemplate != null) {
416             int startPhase = ParticipantUtils.findStartPhase(acElementNodeTemplate.getProperties());
417             if (startPhaseMsg.equals(startPhase)) {
418                 for (var acElementListener : listeners) {
419                     try {
420                         acElementListener.lock(instanceId, acElement.getId());
421                         updateAutomationCompositionElementState(instanceId, acElement.getId(), null, LockState.LOCKED,
422                                 "Locked");
423                     } catch (PfModelException e) {
424                         LOGGER.error("Automation composition element lock failed {}", instanceId);
425                     }
426                 }
427             }
428         }
429     }
430
431     private void automationCompositionElementUnlock(UUID instanceId, AutomationCompositionElement acElement,
432             Integer startPhaseMsg, List<AutomationCompositionElementDefinition> acElementDefinitions) {
433         var acElementNodeTemplate = getAcElementNodeTemplate(acElementDefinitions, acElement.getDefinition());
434         if (acElementNodeTemplate != null) {
435             int startPhase = ParticipantUtils.findStartPhase(acElementNodeTemplate.getProperties());
436             if (startPhaseMsg.equals(startPhase)) {
437                 for (var acElementListener : listeners) {
438                     try {
439                         acElementListener.unlock(instanceId, acElement.getId());
440                         updateAutomationCompositionElementState(instanceId, acElement.getId(), null, LockState.UNLOCKED,
441                                 "Unlocked");
442                     } catch (PfModelException e) {
443                         LOGGER.error("Automation composition element unlock failed {}", instanceId);
444                     }
445                 }
446             }
447         }
448     }
449
450     private void automationCompositionElementUndeploy(UUID instanceId, AutomationCompositionElement acElement,
451             Integer startPhaseMsg, List<AutomationCompositionElementDefinition> acElementDefinitions) {
452         var acElementNodeTemplate = getAcElementNodeTemplate(acElementDefinitions, acElement.getDefinition());
453         if (acElementNodeTemplate != null) {
454             int startPhase = ParticipantUtils.findStartPhase(acElementNodeTemplate.getProperties());
455             if (startPhaseMsg.equals(startPhase)) {
456                 undeployInstanceElements(instanceId, acElement.getId());
457             }
458         }
459     }
460
461     private void automationCompositionElementDelete(UUID instanceId, AutomationCompositionElement acElement,
462             Integer startPhaseMsg, List<AutomationCompositionElementDefinition> acElementDefinitions) {
463         var acElementNodeTemplate = getAcElementNodeTemplate(acElementDefinitions, acElement.getDefinition());
464         if (acElementNodeTemplate != null) {
465             int startPhase = ParticipantUtils.findStartPhase(acElementNodeTemplate.getProperties());
466             if (startPhaseMsg.equals(startPhase)) {
467                 for (var acElementListener : listeners) {
468                     try {
469                         acElementListener.delete(instanceId, acElement.getId());
470                         updateAutomationCompositionElementState(instanceId, acElement.getId(), DeployState.DELETED,
471                                 null, "Deleted");
472                     } catch (PfModelException e) {
473                         LOGGER.error("Automation composition element unlock failed {}", instanceId);
474                     }
475                 }
476             }
477         }
478     }
479
480     /**
481      * Undeploy Instance Elements On Participant.
482      */
483     public void undeployInstances() {
484         automationCompositionMap.values().forEach(this::undeployInstance);
485     }
486
487     private void undeployInstance(AutomationComposition automationComposition) {
488         automationComposition.getElements().values().forEach(element -> {
489             if (element.getParticipantId().equals(participantId)) {
490                 undeployInstanceElements(automationComposition.getInstanceId(), element.getId());
491             }
492         });
493     }
494
495     private void undeployInstanceElements(UUID instanceId, UUID elementId) {
496         for (var acElementListener : listeners) {
497             try {
498                 acElementListener.undeploy(instanceId, elementId);
499             } catch (PfModelException e) {
500                 LOGGER.error("Automation composition element update failed {}", instanceId);
501             }
502         }
503     }
504
505     /**
506      * Send Ac Element Info.
507      *
508      * @param automationCompositionId the automationComposition Id
509      * @param elementId the automationComposition Element id
510      * @param useState the use State
511      * @param operationalState the operational State
512      * @param outProperties the output Properties Map
513      */
514     public void sendAcElementInfo(UUID automationCompositionId, UUID elementId, String useState,
515             String operationalState, Map<String, Object> outProperties) {
516
517         if (automationCompositionId == null || elementId == null) {
518             LOGGER.error("Cannot update Automation composition element state, id is null");
519             return;
520         }
521
522         var automationComposition = automationCompositionMap.get(automationCompositionId);
523         if (automationComposition == null) {
524             LOGGER.error("Cannot update Automation composition element state, Automation composition id {} not present",
525                     automationComposition);
526             return;
527         }
528
529         var element = automationComposition.getElements().get(elementId);
530         if (element == null) {
531             var msg = "Cannot update Automation composition element state, AC Element id {} not present";
532             LOGGER.error(msg, automationComposition);
533             return;
534         }
535         element.setOperationalState(operationalState);
536         element.setUseState(useState);
537         element.setOutProperties(outProperties);
538
539         var statusMsg = new ParticipantStatus();
540         statusMsg.setParticipantId(participantId);
541         statusMsg.setState(ParticipantState.ON_LINE);
542         statusMsg.setParticipantSupportedElementType(new ArrayList<>(supportedAcElementTypes));
543         var acInfo = new AutomationCompositionInfo();
544         acInfo.setAutomationCompositionId(automationCompositionId);
545         acInfo.setDeployState(automationComposition.getDeployState());
546         acInfo.setLockState(automationComposition.getLockState());
547         acInfo.setElements(List.of(getAutomationCompositionElementInfo(element)));
548         statusMsg.setAutomationCompositionInfoList(List.of(acInfo));
549         publisher.sendParticipantStatus(statusMsg);
550     }
551
552     /**
553      * get AutomationComposition Info List.
554      *
555      * @return list of AutomationCompositionInfo
556      */
557     public List<AutomationCompositionInfo> getAutomationCompositionInfoList() {
558         List<AutomationCompositionInfo> automationCompositionInfoList = new ArrayList<>();
559         for (var entry : automationCompositionMap.entrySet()) {
560             var acInfo = new AutomationCompositionInfo();
561             acInfo.setAutomationCompositionId(entry.getKey());
562             acInfo.setDeployState(entry.getValue().getDeployState());
563             acInfo.setLockState(entry.getValue().getLockState());
564             for (var element : entry.getValue().getElements().values()) {
565                 acInfo.getElements().add(getAutomationCompositionElementInfo(element));
566             }
567             automationCompositionInfoList.add(acInfo);
568         }
569         return automationCompositionInfoList;
570     }
571
572     private AutomationCompositionElementInfo getAutomationCompositionElementInfo(AutomationCompositionElement element) {
573         var elementInfo = new AutomationCompositionElementInfo();
574         elementInfo.setAutomationCompositionElementId(element.getId());
575         elementInfo.setDeployState(element.getDeployState());
576         elementInfo.setLockState(element.getLockState());
577         elementInfo.setOperationalState(element.getOperationalState());
578         elementInfo.setUseState(element.getUseState());
579         elementInfo.setOutProperties(element.getOutProperties());
580         return elementInfo;
581     }
582 }