2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021-2025 OpenInfra Foundation Europe. All rights reserved.
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.runtime.instantiation;
24 import jakarta.validation.Valid;
25 import jakarta.ws.rs.core.Response.Status;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.List;
29 import java.util.UUID;
30 import java.util.stream.Collectors;
31 import lombok.NonNull;
32 import lombok.RequiredArgsConstructor;
33 import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup;
34 import org.onap.policy.clamp.acm.runtime.main.utils.EncryptionUtils;
35 import org.onap.policy.clamp.acm.runtime.supervision.SupervisionAcHandler;
36 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
37 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition;
38 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
39 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions;
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.MigrationState;
43 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
44 import org.onap.policy.clamp.models.acm.concepts.SubState;
45 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AcInstanceStateUpdate;
46 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
47 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse;
48 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder;
49 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.SubOrder;
50 import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider;
51 import org.onap.policy.clamp.models.acm.persistence.provider.AcInstanceStateResolver;
52 import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
53 import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider;
54 import org.onap.policy.clamp.models.acm.utils.AcmStageUtils;
55 import org.onap.policy.clamp.models.acm.utils.AcmStateUtils;
56 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
57 import org.onap.policy.common.parameters.BeanValidationResult;
58 import org.onap.policy.models.base.PfModelRuntimeException;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61 import org.springframework.data.domain.Pageable;
62 import org.springframework.stereotype.Service;
63 import org.springframework.transaction.annotation.Transactional;
66 * This class is dedicated to the Instantiation of Commissioned automation composition.
70 @RequiredArgsConstructor
71 public class AutomationCompositionInstantiationProvider {
72 private static final String DO_NOT_MATCH = " do not match with ";
73 private static final String ELEMENT_ID_NOT_PRESENT = "Element id not present ";
74 private static final String NOT_VALID_ORDER =
75 "Not valid order %s; DeployState: %s; LockState: %s; SubState: %s; StateChangeResult: %s";
77 private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionInstantiationProvider.class);
79 private final AutomationCompositionProvider automationCompositionProvider;
80 private final AcDefinitionProvider acDefinitionProvider;
81 private final AcInstanceStateResolver acInstanceStateResolver;
82 private final SupervisionAcHandler supervisionAcHandler;
83 private final ParticipantProvider participantProvider;
84 private final AcRuntimeParameterGroup acRuntimeParameterGroup;
85 private final EncryptionUtils encryptionUtils;
88 * Create automation composition.
90 * @param compositionId The UUID of the automation composition definition
91 * @param automationComposition the automation composition
92 * @return the result of the instantiation operation
94 public InstantiationResponse createAutomationComposition(UUID compositionId,
95 AutomationComposition automationComposition) {
96 LOGGER.info("Create instance request received for compositionId {}", compositionId);
97 AutomationCompositionProvider.validateInstanceEndpoint(compositionId, automationComposition);
98 automationCompositionProvider.validateNameVersion(automationComposition.getKey().asIdentifier());
100 var acDefinition = acDefinitionProvider.getAcDefinition(compositionId);
101 AcDefinitionProvider.checkPrimedComposition(acDefinition);
102 var validationResult = validateAutomationComposition(automationComposition, acDefinition, 0);
103 if (!validationResult.isValid()) {
104 throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult());
106 associateParticipantId(automationComposition, acDefinition, null);
108 encryptInstanceProperties(automationComposition, compositionId);
109 automationComposition = automationCompositionProvider.createAutomationComposition(automationComposition);
111 return createInstantiationResponse(automationComposition);
114 private InstantiationResponse createInstantiationResponse(AutomationComposition automationComposition) {
115 var response = new InstantiationResponse();
116 response.setInstanceId(automationComposition.getInstanceId());
117 response.setAffectedAutomationComposition(automationComposition.getKey().asIdentifier());
122 * Update automation composition.
124 * @param compositionId The UUID of the automation composition definition
125 * @param automationComposition the automation composition
126 * @return the result of the update
128 public InstantiationResponse updateAutomationComposition(UUID compositionId,
129 AutomationComposition automationComposition) {
130 var instanceId = automationComposition.getInstanceId();
131 var acFromDb = automationCompositionProvider.getAutomationComposition(instanceId);
132 AutomationCompositionProvider.validateInstanceEndpoint(compositionId, acFromDb);
133 var acDefinition = acDefinitionProvider.getAcDefinition(compositionId);
134 AcDefinitionProvider.checkPrimedComposition(acDefinition);
135 if (DeployState.UNDEPLOYED.equals(acFromDb.getDeployState())) {
136 LOGGER.info("Updating undeployed instance with id {}", instanceId);
137 acFromDb.setElements(automationComposition.getElements());
138 acFromDb.setName(automationComposition.getName());
139 acFromDb.setVersion(automationComposition.getVersion());
140 acFromDb.setDescription(automationComposition.getDescription());
141 acFromDb.setDerivedFrom(automationComposition.getDerivedFrom());
142 var validationResult = validateAutomationComposition(acFromDb, acDefinition, 0);
143 if (!validationResult.isValid()) {
144 throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult());
146 associateParticipantId(acFromDb, acDefinition, null);
148 encryptInstanceProperties(acFromDb, compositionId);
149 automationComposition = automationCompositionProvider.updateAutomationComposition(acFromDb);
150 return createInstantiationResponse(automationComposition);
154 var deployOrder = DeployOrder.UPDATE;
155 var subOrder = SubOrder.NONE;
157 if (automationComposition.getCompositionTargetId() != null) {
159 if (Boolean.TRUE.equals(automationComposition.getPrecheck())) {
160 subOrder = SubOrder.MIGRATE_PRECHECK;
161 deployOrder = DeployOrder.NONE;
163 deployOrder = DeployOrder.MIGRATE;
166 var result = acInstanceStateResolver.resolve(deployOrder, LockOrder.NONE, subOrder,
167 acFromDb.getDeployState(), acFromDb.getLockState(), acFromDb.getSubState(),
168 acFromDb.getStateChangeResult());
169 return switch (result) {
170 case "UPDATE" -> updateDeployedAutomationComposition(automationComposition, acFromDb, acDefinition);
172 case "MIGRATE" -> migrateAutomationComposition(automationComposition, acFromDb, acDefinition);
174 case "MIGRATE_PRECHECK" -> migratePrecheckAc(automationComposition, acFromDb, acDefinition);
176 default -> throw new PfModelRuntimeException(Status.BAD_REQUEST,
177 "Not allowed to " + deployOrder + " in the state " + acFromDb.getDeployState());
182 * Update deployed AC Element properties.
184 * @param automationComposition the automation composition
185 * @param acToBeUpdated the composition to be updated
186 * @return the result of the update
188 private InstantiationResponse updateDeployedAutomationComposition(
189 AutomationComposition automationComposition, AutomationComposition acToBeUpdated,
190 AutomationCompositionDefinition acDefinition) {
191 // save copy in case of a rollback
192 automationCompositionProvider.copyAcElementsBeforeUpdate(acToBeUpdated);
193 LOGGER.info("Updating deployed instance with id {}", automationComposition.getInstanceId());
195 // Iterate and update the element property values
196 for (var element : automationComposition.getElements().entrySet()) {
197 var elementId = element.getKey();
198 var dbAcElement = acToBeUpdated.getElements().get(elementId);
199 if (dbAcElement == null) {
200 throw new PfModelRuntimeException(Status.BAD_REQUEST, ELEMENT_ID_NOT_PRESENT + elementId);
202 AcmUtils.recursiveMerge(dbAcElement.getProperties(), element.getValue().getProperties());
205 var validationResult = validateAutomationComposition(acToBeUpdated, acDefinition, 0);
206 if (!validationResult.isValid()) {
207 throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult());
209 associateParticipantId(acToBeUpdated, acDefinition, null);
211 updateAcForProperties(acToBeUpdated);
213 var acToPublish = new AutomationComposition(acToBeUpdated);
214 encryptInstanceProperties(acToBeUpdated, acToBeUpdated.getCompositionId());
216 automationComposition = automationCompositionProvider.updateAutomationComposition(acToBeUpdated);
217 // Publish property update event to the participants
218 supervisionAcHandler.update(acToPublish, acDefinition.getRevisionId());
219 return createInstantiationResponse(automationComposition);
222 private InstantiationResponse migrateAutomationComposition(
223 AutomationComposition automationComposition, AutomationComposition acFromDb,
224 AutomationCompositionDefinition acDefinition) {
225 LOGGER.info("Migrating instance with id {}", automationComposition.getInstanceId());
226 if (!DeployState.DEPLOYED.equals(acFromDb.getDeployState())) {
227 throw new PfModelRuntimeException(Status.BAD_REQUEST,
228 "Not allowed to migrate in the state " + acFromDb.getDeployState());
230 // make copy for rollback
231 automationCompositionProvider.copyAcElementsBeforeUpdate(acFromDb);
233 var acDefinitionTarget = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionTargetId());
234 AcDefinitionProvider.checkPrimedComposition(acDefinitionTarget);
235 // Iterate and update the element property values
236 updateElementsProperties(automationComposition, acFromDb, acDefinitionTarget, acDefinition);
238 updateAcForMigration(acFromDb, acDefinitionTarget, DeployState.MIGRATING);
240 var acToPublish = new AutomationComposition(acFromDb);
241 encryptInstanceProperties(acFromDb, acFromDb.getCompositionTargetId());
243 var ac = automationCompositionProvider.updateAutomationComposition(acFromDb);
245 // Publish migrate event to the participants
246 supervisionAcHandler.migrate(acToPublish, acDefinition.getRevisionId(), acDefinitionTarget.getRevisionId());
247 return createInstantiationResponse(ac);
250 private void updateAcForMigration(AutomationComposition acFromDb,
251 AutomationCompositionDefinition acDefinition, DeployState deployState) {
252 AcmStateUtils.setCascadedState(acFromDb, deployState, LockState.LOCKED);
253 acFromDb.setStateChangeResult(StateChangeResult.NO_ERROR);
254 var stage = AcmStageUtils.getFirstStage(acFromDb, acDefinition.getServiceTemplate());
255 acFromDb.setPhase(stage);
258 private void updateAcForProperties(AutomationComposition acToBeUpdated) {
259 AcmStateUtils.setCascadedState(acToBeUpdated, DeployState.UPDATING, acToBeUpdated.getLockState());
260 acToBeUpdated.setStateChangeResult(StateChangeResult.NO_ERROR);
263 private List<AutomationCompositionElement> getElementRemoved(AutomationComposition acFromDb,
264 AutomationComposition acFromMigration) {
265 return acFromDb.getElements().values().stream()
266 .filter(element -> acFromMigration.getElements().get(element.getId()) == null).toList();
270 private InstantiationResponse migratePrecheckAc(
271 AutomationComposition automationComposition, AutomationComposition acToBeUpdated,
272 AutomationCompositionDefinition acDefinition) {
274 acToBeUpdated.setPrecheck(true);
275 LOGGER.info("Running migrate precheck for id: {}", automationComposition.getInstanceId());
276 var copyAc = new AutomationComposition(acToBeUpdated);
277 var acDefinitionTarget = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionTargetId());
278 AcDefinitionProvider.checkPrimedComposition(acDefinitionTarget);
279 // Iterate and update the element property values
280 updateElementsProperties(automationComposition, copyAc, acDefinitionTarget, acDefinition);
282 // Publish migrate event to the participants
283 supervisionAcHandler.migratePrecheck(copyAc, acDefinition.getRevisionId(), acDefinitionTarget.getRevisionId());
285 AcmStateUtils.setCascadedState(acToBeUpdated, DeployState.DEPLOYED, LockState.LOCKED,
286 SubState.MIGRATION_PRECHECKING);
287 acToBeUpdated.setStateChangeResult(StateChangeResult.NO_ERROR);
289 return createInstantiationResponse(automationCompositionProvider.updateAutomationComposition(acToBeUpdated));
293 * Validate AutomationComposition.
295 * @param automationComposition AutomationComposition to validate
296 * @param acDefinition the Composition Definition
297 * @return the result of validation
299 private BeanValidationResult validateAutomationComposition(AutomationComposition automationComposition,
300 AutomationCompositionDefinition acDefinition, int removeElement) {
301 var result = new BeanValidationResult("AutomationComposition", automationComposition);
302 participantProvider.checkRegisteredParticipant(acDefinition);
303 result.addResult(AcmUtils.validateAutomationComposition(automationComposition,
304 acDefinition.getServiceTemplate(),
305 acRuntimeParameterGroup.getAcmParameters().getToscaCompositionName(), removeElement));
307 result.addResult(automationCompositionProvider.validateElementIds(automationComposition));
313 private void encryptInstanceProperties(AutomationComposition automationComposition, UUID compositionId) {
314 if (encryptionUtils.encryptionEnabled()) {
315 var acDefinitionOpt = acDefinitionProvider.findAcDefinition(compositionId);
316 acDefinitionOpt.ifPresent(acDefinition
317 -> encryptionUtils.findAndEncryptSensitiveData(acDefinition, automationComposition));
322 * Get Automation Composition.
324 * @param compositionId The UUID of the automation composition definition
325 * @param instanceId The UUID of the automation composition instance
326 * @return the Automation Composition
328 @Transactional(readOnly = true)
329 public AutomationComposition getAutomationComposition(@NonNull UUID compositionId, UUID instanceId) {
330 var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId);
331 if (!compositionId.equals(automationComposition.getCompositionId())
332 && !compositionId.equals(automationComposition.getCompositionTargetId())) {
333 throw new PfModelRuntimeException(Status.BAD_REQUEST,
334 automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId);
336 return automationComposition;
340 * Delete the automation composition with the given name and version.
342 * @param compositionId The UUID of the automation composition definition
343 * @param instanceId The UUID of the automation composition instance
344 * @return the result of the deletion
346 public InstantiationResponse deleteAutomationComposition(UUID compositionId, UUID instanceId) {
347 var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId);
348 var acDefinition = getAcDefinition(compositionId, automationComposition);
349 LOGGER.info("Delete automation composition request received for name: {} and version: {}",
350 automationComposition.getName(), automationComposition.getVersion());
351 var result = acInstanceStateResolver.resolve(DeployOrder.DELETE,
353 automationComposition.getDeployState(), automationComposition.getLockState(),
354 automationComposition.getSubState(), automationComposition.getStateChangeResult());
355 if (!DeployOrder.DELETE.name().equals(result)) {
356 var msg = String.format(NOT_VALID_ORDER, DeployOrder.DELETE,
357 automationComposition.getDeployState(), automationComposition.getLockState(),
358 automationComposition.getSubState(), automationComposition.getStateChangeResult());
359 throw new PfModelRuntimeException(Status.BAD_REQUEST, msg);
361 supervisionAcHandler.delete(automationComposition, acDefinition);
362 return createInstantiationResponse(automationComposition);
366 * Get the requested automation compositions.
368 * @param name the name of the automation composition to get, null for all automation compositions
369 * @param version the version of the automation composition to get, null for all automation compositions
370 * @param pageable the Pageable
371 * @return the automation compositions
373 @Transactional(readOnly = true)
374 public AutomationCompositions getAutomationCompositions(@NonNull final UUID compositionId,
375 final String name, final String version,
376 @NonNull final Pageable pageable) {
377 var automationCompositions = new AutomationCompositions();
378 automationCompositions.setAutomationCompositionList(
379 automationCompositionProvider.getAutomationCompositions(compositionId, name, version, pageable));
381 return automationCompositions;
385 * Handle Composition Instance State.
387 * @param compositionId the compositionId
388 * @param instanceId the instanceId
389 * @param acInstanceStateUpdate the AcInstanceStateUpdate
391 public void compositionInstanceState(UUID compositionId, UUID instanceId,
392 @Valid AcInstanceStateUpdate acInstanceStateUpdate) {
393 var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId);
394 var acDefinition = getAcDefinition(compositionId, automationComposition);
395 var result = acInstanceStateResolver.resolve(acInstanceStateUpdate.getDeployOrder(),
396 acInstanceStateUpdate.getLockOrder(), acInstanceStateUpdate.getSubOrder(),
397 automationComposition.getDeployState(), automationComposition.getLockState(),
398 automationComposition.getSubState(), automationComposition.getStateChangeResult());
401 supervisionAcHandler.deploy(automationComposition, acDefinition);
405 supervisionAcHandler.undeploy(automationComposition, acDefinition);
409 supervisionAcHandler.lock(automationComposition, acDefinition);
413 supervisionAcHandler.unlock(automationComposition, acDefinition);
417 supervisionAcHandler.prepare(automationComposition, acDefinition);
421 supervisionAcHandler.review(automationComposition, acDefinition);
425 var msg = String.format(NOT_VALID_ORDER, acInstanceStateUpdate,
426 automationComposition.getDeployState(), automationComposition.getLockState(),
427 automationComposition.getSubState(), automationComposition.getStateChangeResult());
428 throw new PfModelRuntimeException(Status.BAD_REQUEST, msg);
433 * Rollback AC Instance.
435 * @param compositionId The UUID of the automation composition definition
436 * @param instanceId The UUID of the automation composition instance
438 public void rollback(UUID compositionId, UUID instanceId) {
439 LOGGER.info("Rollback automation composition request received for CompositionID: {} and InstanceID: {}",
440 compositionId, instanceId);
441 var acFromDb = automationCompositionProvider.getAutomationComposition(instanceId);
442 AutomationCompositionProvider.validateInstanceEndpoint(compositionId, acFromDb);
444 if (!DeployOrder.MIGRATION_REVERT.name().equals(acInstanceStateResolver.resolve(
445 DeployOrder.MIGRATION_REVERT, LockOrder.NONE,
446 SubOrder.NONE, acFromDb.getDeployState(), acFromDb.getLockState(),
447 acFromDb.getSubState(), acFromDb.getStateChangeResult()))) {
448 throw new PfModelRuntimeException(Status.BAD_REQUEST, "Invalid state for rollback");
451 var automationCompositionToRollback =
452 automationCompositionProvider.getAutomationCompositionRollback(instanceId);
453 var acFromDbCopy = new AutomationComposition(acFromDb);
454 acFromDbCopy.setElements(automationCompositionToRollback.getElements().values().stream()
455 .collect(Collectors.toMap(AutomationCompositionElement::getId, AutomationCompositionElement::new)));
457 var acDefinition = acDefinitionProvider.getAcDefinition(acFromDbCopy.getCompositionId());
458 var validationResult = validateAutomationComposition(acFromDbCopy, acDefinition, 0);
459 if (!validationResult.isValid()) {
460 throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult());
462 // Include new elements from migration for the participant undeploy
463 for (var element : acFromDb.getElements().values()) {
464 if (MigrationState.NEW.equals(element.getMigrationState())) {
465 acFromDbCopy.getElements().put(element.getId(), element);
467 if (MigrationState.REMOVED.equals(element.getMigrationState())) {
468 acFromDbCopy.getElements().get(element.getId()).setMigrationState(MigrationState.REMOVED);
472 updateAcForMigration(acFromDbCopy, acDefinition, DeployState.MIGRATION_REVERTING);
473 automationCompositionProvider.updateAutomationComposition(acFromDbCopy);
474 var acDefinitionTarget = acDefinitionProvider.getAcDefinition(acFromDbCopy.getCompositionTargetId());
475 supervisionAcHandler.migrate(acFromDbCopy, acDefinition.getRevisionId(), acDefinitionTarget.getRevisionId());
478 private void updateElementsProperties(AutomationComposition automationComposition,
479 AutomationComposition acFromDb, AutomationCompositionDefinition acDefinitionTarget,
480 AutomationCompositionDefinition acDefinition) {
481 for (var element : automationComposition.getElements().entrySet()) {
482 var elementId = element.getKey();
483 var dbAcElement = acFromDb.getElements().get(elementId);
484 if (dbAcElement == null) {
485 LOGGER.info("New Ac element {} added in Migration", elementId);
486 element.getValue().setMigrationState(MigrationState.NEW);
487 acFromDb.getElements().put(elementId, element.getValue());
489 AcmUtils.recursiveMerge(dbAcElement.getProperties(), element.getValue().getProperties());
490 var newDefinition = element.getValue().getDefinition().asConceptKey();
491 var dbElementDefinition = dbAcElement.getDefinition().asConceptKey();
492 AutomationCompositionProvider.checkCompatibility(
493 newDefinition, dbElementDefinition, automationComposition.getInstanceId());
494 dbAcElement.setDefinition(element.getValue().getDefinition());
497 // Update migrationState for the removed elements
498 var elementsRemoved = getElementRemoved(acFromDb, automationComposition);
499 elementsRemoved.forEach(element -> acFromDb.getElements().get(element.getId())
500 .setMigrationState(MigrationState.REMOVED));
502 var validationResult = validateAutomationComposition(acFromDb, acDefinitionTarget, elementsRemoved.size());
503 if (!validationResult.isValid()) {
504 throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult());
506 associateParticipantId(acFromDb, acDefinitionTarget, acDefinition);
508 acFromDb.setCompositionTargetId(automationComposition.getCompositionTargetId());
511 private void associateParticipantId(AutomationComposition acFromDb,
512 AutomationCompositionDefinition acDefinitionTarget,
513 AutomationCompositionDefinition oldAcDefinition) {
514 for (var element : acFromDb.getElements().values()) {
515 var name = element.getDefinition().getName();
516 var migrationState = element.getMigrationState();
517 if (MigrationState.DEFAULT.equals(migrationState) || MigrationState.NEW.equals(migrationState)) {
518 var participantId = acDefinitionTarget.getElementStateMap().get(name).getParticipantId();
519 element.setParticipantId(participantId);
520 } else if (MigrationState.REMOVED.equals(migrationState) && oldAcDefinition != null) {
521 var participantId = oldAcDefinition.getElementStateMap().get(name).getParticipantId();
522 element.setParticipantId(participantId);
527 private AutomationCompositionDefinition getAcDefinition(UUID compositionId,
528 AutomationComposition automationComposition) {
529 AutomationCompositionProvider.validateInstanceEndpoint(compositionId, automationComposition);
530 var acDefinition = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionId());
531 participantProvider.checkRegisteredParticipant(acDefinition);
536 * Retrieves a list of AutomationComposition instances filtered by the specified state change results
537 * and deployment states. The result can be paginated and sorted based on the provided parameters.
539 * @param instanceIds a list of instance UUIDs
540 * @param stateChangeResults a list of StateChangeResult values to filter the AutomationComposition instances
541 * @param deployStates a list of DeployState values to filter the AutomationComposition instances
542 * @param pageable the pagination information including page size and page number
543 * @return a list of AutomationComposition instances that match the specified filters
545 public AutomationCompositions getAcInstancesByFilter(
546 final String instanceIds, final String stateChangeResults, final String deployStates,
547 final Pageable pageable) {
549 LOGGER.info("Get automation compositions request received with filters");
550 List<String> acIds = new ArrayList<>();
551 if (instanceIds != null) {
552 Arrays.stream(instanceIds.split(",")).forEach(acId -> acIds.add(acId.trim()));
555 List<StateChangeResult> stateChangeResultList = new ArrayList<>();
556 if (stateChangeResults != null) {
557 Arrays.stream(stateChangeResults.split(","))
558 .forEach(stateChangeResult -> stateChangeResultList.add(StateChangeResult.valueOf(stateChangeResult)));
561 List<DeployState> deployStateList = new ArrayList<>();
562 if (deployStates != null) {
563 Arrays.stream(deployStates.split(","))
564 .forEach(deployState -> deployStateList.add(DeployState.valueOf(deployState)));
567 var instances = automationCompositionProvider.getAcInstancesByFilter(acIds, stateChangeResultList,
568 deployStateList, pageable);
569 return new AutomationCompositions(instances);