2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021-2025 OpenInfra Foundation Europe. All rights reserved.
4 * ================================================================================
5 * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * SPDX-License-Identifier: Apache-2.0
20 * ============LICENSE_END=========================================================
23 package org.onap.policy.clamp.models.acm.persistence.provider;
25 import jakarta.ws.rs.core.Response;
26 import jakarta.ws.rs.core.Response.Status;
27 import java.util.List;
28 import java.util.Optional;
30 import java.util.UUID;
31 import java.util.stream.Collectors;
32 import lombok.AllArgsConstructor;
33 import lombok.NonNull;
34 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
35 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
36 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionRollback;
37 import org.onap.policy.clamp.models.acm.concepts.DeployState;
38 import org.onap.policy.clamp.models.acm.concepts.LockState;
39 import org.onap.policy.clamp.models.acm.concepts.SubState;
40 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationComposition;
41 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionRollback;
42 import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionElementRepository;
43 import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionRepository;
44 import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionRollbackRepository;
45 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
46 import org.onap.policy.common.parameters.BeanValidationResult;
47 import org.onap.policy.common.parameters.ValidationStatus;
48 import org.onap.policy.models.base.PfModelRuntimeException;
49 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
50 import org.springframework.data.domain.Example;
51 import org.springframework.data.domain.Pageable;
52 import org.springframework.stereotype.Service;
53 import org.springframework.transaction.annotation.Isolation;
54 import org.springframework.transaction.annotation.Transactional;
57 * This class provides information on automation composition concepts in the database to callers.
62 public class AutomationCompositionProvider {
64 private final AutomationCompositionRepository automationCompositionRepository;
65 private final AutomationCompositionElementRepository acElementRepository;
66 private final AutomationCompositionRollbackRepository acRollbackRepository;
69 * Get automation composition.
71 * @param instanceId the ID of the automation composition to get
72 * @return the automation composition found
74 @Transactional(readOnly = true)
75 public AutomationComposition getAutomationComposition(final UUID instanceId) {
76 var result = automationCompositionRepository.findById(instanceId.toString());
77 if (result.isEmpty()) {
78 throw new PfModelRuntimeException(Status.NOT_FOUND, "AutomationComposition not found");
80 return result.get().toAuthorative();
84 * Find automation composition.
86 * @param instanceId the ID of the automation composition to get
87 * @return the automation composition found
89 @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
90 public Optional<AutomationComposition> findAutomationComposition(final UUID instanceId) {
91 var result = automationCompositionRepository.findById(instanceId.toString());
92 return result.stream().map(JpaAutomationComposition::toAuthorative).findFirst();
96 * Find automation composition by automationCompositionId.
98 * @param automationCompositionId the ID of the automation composition to get
99 * @return the automation composition found
101 @Transactional(readOnly = true)
102 public Optional<AutomationComposition> findAutomationComposition(
103 final ToscaConceptIdentifier automationCompositionId) {
104 return automationCompositionRepository
105 .findOne(createExample(null, automationCompositionId.getName(), automationCompositionId.getVersion()))
106 .map(JpaAutomationComposition::toAuthorative);
110 * Create automation composition.
112 * @param automationComposition the automation composition to create
113 * @return the created automation composition
115 public AutomationComposition createAutomationComposition(final AutomationComposition automationComposition) {
116 automationComposition.setInstanceId(UUID.randomUUID());
117 AcmUtils.setCascadedState(automationComposition, DeployState.UNDEPLOYED, LockState.NONE);
118 var result = automationCompositionRepository.save(ProviderUtils.getJpaAndValidate(automationComposition,
119 JpaAutomationComposition::new, "automation composition"));
121 // Return the saved automation composition
122 return result.toAuthorative();
126 * Update automation composition.
128 * @param automationComposition the automation composition to update
129 * @return the updated automation composition
131 public AutomationComposition updateAutomationComposition(
132 @NonNull final AutomationComposition automationComposition) {
133 var result = automationCompositionRepository.save(ProviderUtils.getJpaAndValidate(automationComposition,
134 JpaAutomationComposition::new, "automation composition"));
135 automationCompositionRepository.flush();
136 // Return the saved automation composition
137 return result.toAuthorative();
141 * Get all automation compositions by compositionId.
143 * @param compositionId the compositionId of the automation composition definition
144 * @return all automation compositions found
146 @Transactional(readOnly = true)
147 public List<AutomationComposition> getAcInstancesByCompositionId(UUID compositionId) {
149 .asEntityList(automationCompositionRepository.findByCompositionId(compositionId.toString()));
153 * Get all automation compositions in transition.
155 * @return all automation compositions found
157 @Transactional(readOnly = true)
158 public Set<UUID> getAcInstancesInTransition() {
159 var jpaList = automationCompositionRepository.findByDeployStateIn(List.of(DeployState.DEPLOYING,
160 DeployState.UNDEPLOYING, DeployState.DELETING, DeployState.UPDATING, DeployState.MIGRATING));
161 jpaList.addAll(automationCompositionRepository.findByLockStateIn(
162 List.of(LockState.LOCKING, LockState.UNLOCKING)));
163 jpaList.addAll(automationCompositionRepository.findBySubStateIn(
164 List.of(SubState.PREPARING, SubState.MIGRATION_PRECHECKING, SubState.REVIEWING)));
165 return jpaList.stream().map(JpaAutomationComposition::getInstanceId)
166 .map(UUID::fromString).collect(Collectors.toSet());
170 * Get automation compositions.
172 * @param name the name of the automation composition to get, null to get all automation compositions
173 * @param version the version of the automation composition to get, null to get all automation compositions
174 * @param pageable the Pageable
175 * @return the automation compositions found
177 @Transactional(readOnly = true)
178 public List<AutomationComposition> getAutomationCompositions(@NonNull final UUID compositionId, final String name,
179 final String version,
180 @NonNull final Pageable pageable) {
181 return ProviderUtils.asEntityList(automationCompositionRepository
182 .findAll(createExample(compositionId, name, version), pageable).toList());
185 private Example<JpaAutomationComposition> createExample(final UUID compositionId, final String name,
186 final String version) {
187 var example = new JpaAutomationComposition();
188 example.setCompositionId(compositionId != null ? compositionId.toString() : null);
189 example.setName(name);
190 example.setVersion(version);
191 example.setInstanceId(null);
192 example.setElements(null);
193 example.setDeployState(null);
194 example.setLockState(null);
196 return Example.of(example);
200 * Delete a automation composition.
202 * @param instanceId the ID of the automation composition to get
203 * @return the automation composition deleted
205 public AutomationComposition deleteAutomationComposition(@NonNull final UUID instanceId) {
206 var jpaDeleteAutomationComposition = automationCompositionRepository.findById(instanceId.toString());
207 if (jpaDeleteAutomationComposition.isEmpty()) {
208 var errorMessage = "delete of automation composition \"" + instanceId
209 + "\" failed, automation composition does not exist";
210 throw new PfModelRuntimeException(Response.Status.NOT_FOUND, errorMessage);
213 automationCompositionRepository.deleteById(instanceId.toString());
215 return jpaDeleteAutomationComposition.get().toAuthorative();
219 * Delete AutomationCompositionElement.
221 * @param elementId the AutomationCompositionElement Id
223 public void deleteAutomationCompositionElement(@NonNull final UUID elementId) {
224 acElementRepository.deleteById(elementId.toString());
228 * Validate ElementIds.
230 * @param automationComposition the AutomationComposition
231 * @return the BeanValidationResult
233 public BeanValidationResult validateElementIds(final AutomationComposition automationComposition) {
234 var result = new BeanValidationResult(
235 "UUID elements " + automationComposition.getName(), automationComposition);
237 var ids = automationComposition
238 .getElements().values().stream().map(AutomationCompositionElement::getId).toList();
239 var elements = acElementRepository.findAllById(ids.stream().map(UUID::toString).toList());
240 if (automationComposition.getInstanceId() == null) {
241 for (var element : elements) {
243 element.getDescription(), element.getElementId(), ValidationStatus.INVALID, "UUID already used");
246 var instanceId = automationComposition.getInstanceId().toString();
247 for (var element : elements) {
248 if (!instanceId.equals(element.getInstanceId())) {
250 element.getDescription(), element.getElementId(), ValidationStatus.INVALID,
251 "UUID already used");
259 * Save a copy of an automation composition to the copy table in case of a rollback.
261 * @param automationComposition the composition to be copied
263 public void copyAcElementsBeforeUpdate(AutomationComposition automationComposition) {
264 var copy = new AutomationCompositionRollback(automationComposition);
265 var jpaCopy = new JpaAutomationCompositionRollback(copy);
266 acRollbackRepository.save(jpaCopy);
267 acRollbackRepository.flush();
271 * Get the copied automation composition from the RollbackRepository.
273 * @param instanceId the id of the ac instance
274 * @return the acRollback object
276 public JpaAutomationCompositionRollback getAutomationCompositionRollback(String instanceId) {
277 var result = acRollbackRepository.findById(instanceId);
278 if (result.isEmpty()) {
279 throw new PfModelRuntimeException(Status.NOT_FOUND, "Instance not found for rollback");