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.ParticipantUtils;
44 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
45 import org.onap.policy.clamp.models.acm.concepts.SubState;
46 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AcInstanceStateUpdate;
47 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
48 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse;
49 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder;
50 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.SubOrder;
51 import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider;
52 import org.onap.policy.clamp.models.acm.persistence.provider.AcInstanceStateResolver;
53 import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
54 import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider;
55 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
56 import org.onap.policy.common.parameters.BeanValidationResult;
57 import org.onap.policy.models.base.PfModelRuntimeException;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60 import org.springframework.data.domain.Pageable;
61 import org.springframework.stereotype.Service;
62 import org.springframework.transaction.annotation.Transactional;
65 * This class is dedicated to the Instantiation of Commissioned automation composition.
69 @RequiredArgsConstructor
70 public class AutomationCompositionInstantiationProvider {
71 private static final String DO_NOT_MATCH = " do not match with ";
72 private static final String ELEMENT_ID_NOT_PRESENT = "Element id not present ";
73 private static final String NOT_VALID_ORDER =
74 "Not valid order %s; DeployState: %s; LockState: %s; SubState: %s; StateChangeResult: %s";
76 private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionInstantiationProvider.class);
78 private final AutomationCompositionProvider automationCompositionProvider;
79 private final AcDefinitionProvider acDefinitionProvider;
80 private final AcInstanceStateResolver acInstanceStateResolver;
81 private final SupervisionAcHandler supervisionAcHandler;
82 private final ParticipantProvider participantProvider;
83 private final AcRuntimeParameterGroup acRuntimeParameterGroup;
84 private final EncryptionUtils encryptionUtils;
87 * Create automation composition.
89 * @param compositionId The UUID of the automation composition definition
90 * @param automationComposition the automation composition
91 * @return the result of the instantiation operation
93 public InstantiationResponse createAutomationComposition(UUID compositionId,
94 AutomationComposition automationComposition) {
95 LOGGER.info("Create instance request received for compositionId {}", compositionId);
96 AutomationCompositionProvider.validateInstanceEndpoint(compositionId, automationComposition);
97 automationCompositionProvider.validateNameVersion(automationComposition.getKey().asIdentifier());
99 var acDefinition = acDefinitionProvider.getAcDefinition(compositionId);
100 AcDefinitionProvider.checkPrimedComposition(acDefinition);
101 var validationResult = validateAutomationComposition(automationComposition, acDefinition, false);
102 if (!validationResult.isValid()) {
103 throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult());
105 associateParticipantId(automationComposition, acDefinition, null);
107 encryptInstanceProperties(automationComposition, compositionId);
108 automationComposition = automationCompositionProvider.createAutomationComposition(automationComposition);
110 return createInstantiationResponse(automationComposition);
113 private InstantiationResponse createInstantiationResponse(AutomationComposition automationComposition) {
114 var response = new InstantiationResponse();
115 response.setInstanceId(automationComposition.getInstanceId());
116 response.setAffectedAutomationComposition(automationComposition.getKey().asIdentifier());
121 * Update automation composition.
123 * @param compositionId The UUID of the automation composition definition
124 * @param automationComposition the automation composition
125 * @return the result of the update
127 public InstantiationResponse updateAutomationComposition(UUID compositionId,
128 AutomationComposition automationComposition) {
129 var instanceId = automationComposition.getInstanceId();
130 var acFromDb = automationCompositionProvider.getAutomationComposition(instanceId);
131 AutomationCompositionProvider.validateInstanceEndpoint(compositionId, acFromDb);
132 var acDefinition = acDefinitionProvider.getAcDefinition(compositionId);
133 AcDefinitionProvider.checkPrimedComposition(acDefinition);
134 if (DeployState.UNDEPLOYED.equals(acFromDb.getDeployState())) {
135 LOGGER.info("Updating undeployed instance with id {}", instanceId);
136 acFromDb.setElements(automationComposition.getElements());
137 acFromDb.setName(automationComposition.getName());
138 acFromDb.setVersion(automationComposition.getVersion());
139 acFromDb.setDescription(automationComposition.getDescription());
140 acFromDb.setDerivedFrom(automationComposition.getDerivedFrom());
141 var validationResult = validateAutomationComposition(acFromDb, acDefinition, false);
142 if (!validationResult.isValid()) {
143 throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult());
145 associateParticipantId(acFromDb, acDefinition, null);
147 encryptInstanceProperties(acFromDb, compositionId);
148 automationComposition = automationCompositionProvider.updateAutomationComposition(acFromDb);
149 return createInstantiationResponse(automationComposition);
153 var deployOrder = DeployOrder.UPDATE;
154 var subOrder = SubOrder.NONE;
156 if (automationComposition.getCompositionTargetId() != null) {
158 if (Boolean.TRUE.equals(automationComposition.getPrecheck())) {
159 subOrder = SubOrder.MIGRATE_PRECHECK;
160 deployOrder = DeployOrder.NONE;
162 deployOrder = DeployOrder.MIGRATE;
165 var result = acInstanceStateResolver.resolve(deployOrder, LockOrder.NONE, subOrder,
166 acFromDb.getDeployState(), acFromDb.getLockState(), acFromDb.getSubState(),
167 acFromDb.getStateChangeResult());
168 return switch (result) {
169 case "UPDATE" -> updateDeployedAutomationComposition(automationComposition, acFromDb, acDefinition);
171 case "MIGRATE" -> migrateAutomationComposition(automationComposition, acFromDb, acDefinition);
173 case "MIGRATE_PRECHECK" -> migratePrecheckAc(automationComposition, acFromDb, acDefinition);
175 default -> throw new PfModelRuntimeException(Status.BAD_REQUEST,
176 "Not allowed to " + deployOrder + " in the state " + acFromDb.getDeployState());
181 * Update deployed AC Element properties.
183 * @param automationComposition the automation composition
184 * @param acToBeUpdated the composition to be updated
185 * @return the result of the update
187 private InstantiationResponse updateDeployedAutomationComposition(
188 AutomationComposition automationComposition, AutomationComposition acToBeUpdated,
189 AutomationCompositionDefinition acDefinition) {
190 // save copy in case of a rollback
191 automationCompositionProvider.copyAcElementsBeforeUpdate(acToBeUpdated);
192 LOGGER.info("Updating deployed instance with id {}", automationComposition.getInstanceId());
194 // Iterate and update the element property values
195 for (var element : automationComposition.getElements().entrySet()) {
196 var elementId = element.getKey();
197 var dbAcElement = acToBeUpdated.getElements().get(elementId);
198 if (dbAcElement == null) {
199 throw new PfModelRuntimeException(Status.BAD_REQUEST, ELEMENT_ID_NOT_PRESENT + elementId);
201 AcmUtils.recursiveMerge(dbAcElement.getProperties(), element.getValue().getProperties());
204 var validationResult = validateAutomationComposition(acToBeUpdated, acDefinition, false);
205 if (!validationResult.isValid()) {
206 throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult());
208 associateParticipantId(acToBeUpdated, acDefinition, null);
210 updateAcForProperties(acToBeUpdated);
212 var acToPublish = new AutomationComposition(acToBeUpdated);
213 encryptInstanceProperties(acToBeUpdated, acToBeUpdated.getCompositionId());
215 automationComposition = automationCompositionProvider.updateAutomationComposition(acToBeUpdated);
216 // Publish property update event to the participants
217 supervisionAcHandler.update(acToPublish, acDefinition.getRevisionId());
218 return createInstantiationResponse(automationComposition);
221 private InstantiationResponse migrateAutomationComposition(
222 AutomationComposition automationComposition, AutomationComposition acFromDb,
223 AutomationCompositionDefinition acDefinition) {
224 LOGGER.info("Migrating instance with id {}", automationComposition.getInstanceId());
225 if (!DeployState.DEPLOYED.equals(acFromDb.getDeployState())) {
226 throw new PfModelRuntimeException(Status.BAD_REQUEST,
227 "Not allowed to migrate in the state " + acFromDb.getDeployState());
229 // make copy for rollback
230 automationCompositionProvider.copyAcElementsBeforeUpdate(acFromDb);
232 var acDefinitionTarget = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionTargetId());
233 AcDefinitionProvider.checkPrimedComposition(acDefinitionTarget);
234 // Iterate and update the element property values
235 updateElementsProperties(automationComposition, acFromDb, acDefinitionTarget, acDefinition);
237 updateAcForMigration(acFromDb, acDefinitionTarget, DeployState.MIGRATING);
239 var acToPublish = new AutomationComposition(acFromDb);
240 encryptInstanceProperties(acFromDb, acFromDb.getCompositionTargetId());
242 var ac = automationCompositionProvider.updateAutomationComposition(acFromDb);
244 // Publish migrate event to the participants
245 supervisionAcHandler.migrate(acToPublish, acDefinition.getRevisionId(), acDefinitionTarget.getRevisionId());
246 return createInstantiationResponse(ac);
249 private void updateAcForMigration(AutomationComposition acFromDb,
250 AutomationCompositionDefinition acDefinition, DeployState deployState) {
251 AcmUtils.setCascadedState(acFromDb, deployState, LockState.LOCKED);
252 acFromDb.setStateChangeResult(StateChangeResult.NO_ERROR);
253 var stage = ParticipantUtils.getFirstStage(acFromDb, acDefinition.getServiceTemplate());
254 acFromDb.setPhase(stage);
257 private void updateAcForProperties(AutomationComposition acToBeUpdated) {
258 AcmUtils.setCascadedState(acToBeUpdated, DeployState.UPDATING, acToBeUpdated.getLockState());
259 acToBeUpdated.setStateChangeResult(StateChangeResult.NO_ERROR);
262 private List<AutomationCompositionElement> getElementRemoved(AutomationComposition acFromDb,
263 AutomationComposition acFromMigration) {
264 return acFromDb.getElements().values().stream()
265 .filter(element -> acFromMigration.getElements().get(element.getId()) == null).toList();
269 private InstantiationResponse migratePrecheckAc(
270 AutomationComposition automationComposition, AutomationComposition acToBeUpdated,
271 AutomationCompositionDefinition acDefinition) {
273 acToBeUpdated.setPrecheck(true);
274 LOGGER.info("Running migrate precheck for id: {}", automationComposition.getInstanceId());
275 var copyAc = new AutomationComposition(acToBeUpdated);
276 var acDefinitionTarget = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionTargetId());
277 AcDefinitionProvider.checkPrimedComposition(acDefinitionTarget);
278 // Iterate and update the element property values
279 updateElementsProperties(automationComposition, copyAc, acDefinitionTarget, acDefinition);
281 // Publish migrate event to the participants
282 supervisionAcHandler.migratePrecheck(copyAc, acDefinition.getRevisionId(), acDefinitionTarget.getRevisionId());
284 AcmUtils.setCascadedState(acToBeUpdated, DeployState.DEPLOYED, LockState.LOCKED,
285 SubState.MIGRATION_PRECHECKING);
286 acToBeUpdated.setStateChangeResult(StateChangeResult.NO_ERROR);
288 return createInstantiationResponse(automationCompositionProvider.updateAutomationComposition(acToBeUpdated));
292 * Validate AutomationComposition.
294 * @param automationComposition AutomationComposition to validate
295 * @param acDefinition the Composition Definition
296 * @return the result of validation
298 private BeanValidationResult validateAutomationComposition(AutomationComposition automationComposition,
299 AutomationCompositionDefinition acDefinition, boolean migrateOperation) {
300 var result = new BeanValidationResult("AutomationComposition", automationComposition);
301 participantProvider.checkRegisteredParticipant(acDefinition);
302 result.addResult(AcmUtils.validateAutomationComposition(automationComposition,
303 acDefinition.getServiceTemplate(),
304 acRuntimeParameterGroup.getAcmParameters().getToscaCompositionName(), migrateOperation));
306 result.addResult(automationCompositionProvider.validateElementIds(automationComposition));
312 private void encryptInstanceProperties(AutomationComposition automationComposition, UUID compositionId) {
313 if (encryptionUtils.encryptionEnabled()) {
314 var acDefinitionOpt = acDefinitionProvider.findAcDefinition(compositionId);
315 acDefinitionOpt.ifPresent(acDefinition
316 -> encryptionUtils.findAndEncryptSensitiveData(acDefinition, automationComposition));
321 * Get Automation Composition.
323 * @param compositionId The UUID of the automation composition definition
324 * @param instanceId The UUID of the automation composition instance
325 * @return the Automation Composition
327 @Transactional(readOnly = true)
328 public AutomationComposition getAutomationComposition(@NonNull UUID compositionId, UUID instanceId) {
329 var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId);
330 if (!compositionId.equals(automationComposition.getCompositionId())
331 && !compositionId.equals(automationComposition.getCompositionTargetId())) {
332 throw new PfModelRuntimeException(Status.BAD_REQUEST,
333 automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId);
335 return automationComposition;
339 * Delete the automation composition with the given name and version.
341 * @param compositionId The UUID of the automation composition definition
342 * @param instanceId The UUID of the automation composition instance
343 * @return the result of the deletion
345 public InstantiationResponse deleteAutomationComposition(UUID compositionId, UUID instanceId) {
346 var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId);
347 var acDefinition = getAcDefinition(compositionId, automationComposition);
348 LOGGER.info("Delete automation composition request received for name: {} and version: {}",
349 automationComposition.getName(), automationComposition.getVersion());
350 var result = acInstanceStateResolver.resolve(DeployOrder.DELETE,
352 automationComposition.getDeployState(), automationComposition.getLockState(),
353 automationComposition.getSubState(), automationComposition.getStateChangeResult());
354 if (!DeployOrder.DELETE.name().equals(result)) {
355 var msg = String.format(NOT_VALID_ORDER, DeployOrder.DELETE,
356 automationComposition.getDeployState(), automationComposition.getLockState(),
357 automationComposition.getSubState(), automationComposition.getStateChangeResult());
358 throw new PfModelRuntimeException(Status.BAD_REQUEST, msg);
360 supervisionAcHandler.delete(automationComposition, acDefinition);
361 return createInstantiationResponse(automationComposition);
365 * Get the requested automation compositions.
367 * @param name the name of the automation composition to get, null for all automation compositions
368 * @param version the version of the automation composition to get, null for all automation compositions
369 * @param pageable the Pageable
370 * @return the automation compositions
372 @Transactional(readOnly = true)
373 public AutomationCompositions getAutomationCompositions(@NonNull final UUID compositionId,
374 final String name, final String version,
375 @NonNull final Pageable pageable) {
376 var automationCompositions = new AutomationCompositions();
377 automationCompositions.setAutomationCompositionList(
378 automationCompositionProvider.getAutomationCompositions(compositionId, name, version, pageable));
380 return automationCompositions;
384 * Handle Composition Instance State.
386 * @param compositionId the compositionId
387 * @param instanceId the instanceId
388 * @param acInstanceStateUpdate the AcInstanceStateUpdate
390 public void compositionInstanceState(UUID compositionId, UUID instanceId,
391 @Valid AcInstanceStateUpdate acInstanceStateUpdate) {
392 var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId);
393 var acDefinition = getAcDefinition(compositionId, automationComposition);
394 var result = acInstanceStateResolver.resolve(acInstanceStateUpdate.getDeployOrder(),
395 acInstanceStateUpdate.getLockOrder(), acInstanceStateUpdate.getSubOrder(),
396 automationComposition.getDeployState(), automationComposition.getLockState(),
397 automationComposition.getSubState(), automationComposition.getStateChangeResult());
400 supervisionAcHandler.deploy(automationComposition, acDefinition);
404 supervisionAcHandler.undeploy(automationComposition, acDefinition);
408 supervisionAcHandler.lock(automationComposition, acDefinition);
412 supervisionAcHandler.unlock(automationComposition, acDefinition);
416 supervisionAcHandler.prepare(automationComposition, acDefinition);
420 supervisionAcHandler.review(automationComposition, acDefinition);
424 var msg = String.format(NOT_VALID_ORDER, acInstanceStateUpdate,
425 automationComposition.getDeployState(), automationComposition.getLockState(),
426 automationComposition.getSubState(), automationComposition.getStateChangeResult());
427 throw new PfModelRuntimeException(Status.BAD_REQUEST, msg);
432 * Rollback AC Instance.
434 * @param compositionId The UUID of the automation composition definition
435 * @param instanceId The UUID of the automation composition instance
437 public void rollback(UUID compositionId, UUID instanceId) {
438 LOGGER.info("Rollback automation composition request received for CompositionID: {} and InstanceID: {}",
439 compositionId, instanceId);
440 var acFromDb = automationCompositionProvider.getAutomationComposition(instanceId);
441 AutomationCompositionProvider.validateInstanceEndpoint(compositionId, acFromDb);
443 if (!DeployOrder.MIGRATION_REVERT.name().equals(acInstanceStateResolver.resolve(
444 DeployOrder.MIGRATION_REVERT, LockOrder.NONE,
445 SubOrder.NONE, acFromDb.getDeployState(), acFromDb.getLockState(),
446 acFromDb.getSubState(), acFromDb.getStateChangeResult()))) {
447 throw new PfModelRuntimeException(Status.BAD_REQUEST, "Invalid state for rollback");
450 var automationCompositionToRollback =
451 automationCompositionProvider.getAutomationCompositionRollback(instanceId);
452 var acFromDbCopy = new AutomationComposition(acFromDb);
453 acFromDbCopy.setCompositionTargetId(automationCompositionToRollback.getCompositionId());
454 acFromDbCopy.setElements(automationCompositionToRollback.getElements().values().stream()
455 .collect(Collectors.toMap(AutomationCompositionElement::getId, AutomationCompositionElement::new)));
457 var acDefinitionTarget = acDefinitionProvider.getAcDefinition(acFromDbCopy.getCompositionTargetId());
458 var validationResult = validateAutomationComposition(acFromDbCopy, acDefinitionTarget, true);
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, acDefinitionTarget, DeployState.MIGRATION_REVERTING);
473 automationCompositionProvider.updateAutomationComposition(acFromDbCopy);
474 var acDefinition = acDefinitionProvider.getAcDefinition(acFromDbCopy.getCompositionId());
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, true);
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.REMOVED.equals(migrationState) && oldAcDefinition != null) {
518 var participantId = oldAcDefinition.getElementStateMap().get(name).getParticipantId();
519 element.setParticipantId(participantId);
521 var participantId = acDefinitionTarget.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);