Update fetch rollback elements 89/141389/3
authorFrancescoFioraEst <francesco.fiora@est.tech>
Wed, 25 Jun 2025 14:35:05 +0000 (15:35 +0100)
committerFrancesco Fiora <francesco.fiora@est.tech>
Thu, 26 Jun 2025 11:39:48 +0000 (11:39 +0000)
Delete rollback when the instance is deleted.
Fix fetch rollback elements from DB.

Issue-ID: POLICY-5364
Change-Id: I0b39fc7eda05843799417fb1eb141f462c8e435d
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
14 files changed:
models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionRollback.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/AbstractConverter.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionRollback.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/StringToDocMessage.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/StringToMapConverter.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/StringToServiceTemplateConverter.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProvider.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionRollbackRepository.java
models/src/test/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionRollbackTest.java
models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/AbstractConverterTest.java [new file with mode: 0644]
models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionRollbackTest.java
models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProviderTest.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java

index 3d62f91..c11d5b8 100644 (file)
@@ -40,7 +40,7 @@ public class AutomationCompositionRollback {
     private UUID compositionId;\r
 \r
     @NonNull\r
-    private Map<String, Object> elements = new LinkedHashMap<>();\r
+    private Map<UUID, AutomationCompositionElement> elements = new LinkedHashMap<>();\r
 \r
     /**\r
      * Copy constructor, does a deep copy.\r
@@ -61,10 +61,6 @@ public class AutomationCompositionRollback {
     public AutomationCompositionRollback(final AutomationComposition automationComposition) {\r
         this.instanceId = automationComposition.getInstanceId();\r
         this.compositionId = automationComposition.getCompositionId();\r
-        var originalElements = automationComposition.getElements();\r
-\r
-        this.elements = new LinkedHashMap<>();\r
-        originalElements.forEach((uuid, element) ->\r
-            this.elements.put(uuid.toString(), element));\r
+        this.elements = PfUtils.mapMap(automationComposition.getElements(), UnaryOperator.identity());\r
     }\r
 }\r
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/AbstractConverter.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/AbstractConverter.java
new file mode 100644 (file)
index 0000000..c75b32d
--- /dev/null
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.models.acm.persistence.concepts;
+
+import jakarta.ws.rs.core.Response;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.models.base.PfModelRuntimeException;
+
+public abstract class AbstractConverter {
+
+    private static final Coder coder = new StandardCoder();
+
+    protected  <T> String encode(final T object) {
+        try {
+            return object == null ? null : coder.encode(object);
+        } catch (CoderException e) {
+            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, e.getMessage(), e);
+        }
+    }
+
+    protected <T> T decode(String message, Class<T> clazz) {
+        try {
+            return coder.decode(message, clazz);
+        } catch (CoderException e) {
+            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Converts an Object to a typed Object.
+     *
+     * @param obj the Object
+     * @param clazz the Class
+     * @return the object converted
+     */
+    public static <T> T convertObject(Object obj, Class<T> clazz) {
+        try {
+            var json = coder.encode(obj);
+            return coder.decode(json, clazz);
+        } catch (CoderException e) {
+            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, e.getMessage(), e);
+        }
+    }
+}
index 38437e1..64b3ccd 100644 (file)
@@ -33,10 +33,12 @@ import java.util.LinkedHashMap;
 import java.util.Map;\r
 import java.util.UUID;\r
 import java.util.function.UnaryOperator;\r
+import java.util.stream.Collectors;\r
 import lombok.Data;\r
 import lombok.EqualsAndHashCode;\r
 import lombok.NonNull;\r
 import org.apache.commons.lang3.ObjectUtils;\r
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;\r
 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionRollback;\r
 import org.onap.policy.models.base.PfAuthorative;\r
 import org.onap.policy.models.base.PfUtils;\r
@@ -110,7 +112,9 @@ public class JpaAutomationCompositionRollback extends Validated
         var acmRollback = new AutomationCompositionRollback();\r
         acmRollback.setInstanceId(UUID.fromString(this.instanceId));\r
         acmRollback.setCompositionId(UUID.fromString(this.compositionId));\r
-        acmRollback.setElements(PfUtils.mapMap(this.elements, UnaryOperator.identity()));\r
+        acmRollback.setElements(this.elements.values().stream()\r
+                .map(el -> AbstractConverter.convertObject(el, AutomationCompositionElement.class))\r
+                .collect(Collectors.toMap(AutomationCompositionElement::getId, UnaryOperator.identity())));\r
         return acmRollback;\r
     }\r
 \r
@@ -118,7 +122,8 @@ public class JpaAutomationCompositionRollback extends Validated
     public void fromAuthorative(@NonNull final AutomationCompositionRollback acmRollback) {\r
         this.instanceId = acmRollback.getInstanceId().toString();\r
         this.compositionId = acmRollback.getCompositionId().toString();\r
-        this.elements = PfUtils.mapMap(acmRollback.getElements(), UnaryOperator.identity());\r
+        this.elements = acmRollback.getElements().values().stream()\r
+                .collect(Collectors.toMap(element -> element.getId().toString(), UnaryOperator.identity()));\r
     }\r
 \r
     @Override\r
index 78eaed2..66aff1e 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- * Copyright (C) 2025 Nordix Foundation.
+ * Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,25 +22,14 @@ package org.onap.policy.clamp.models.acm.persistence.concepts;
 
 import jakarta.persistence.AttributeConverter;
 import jakarta.persistence.Converter;
-import jakarta.ws.rs.core.Response;
 import org.onap.policy.clamp.models.acm.document.concepts.DocMessage;
-import org.onap.policy.common.utils.coder.Coder;
-import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.common.utils.coder.StandardCoder;
-import org.onap.policy.models.base.PfModelRuntimeException;
 
 @Converter(autoApply = true)
-public class StringToDocMessage implements AttributeConverter<DocMessage, String> {
-
-    private static final Coder coder = new StandardCoder();
+public class StringToDocMessage extends AbstractConverter implements AttributeConverter<DocMessage, String> {
 
     @Override
     public String convertToDatabaseColumn(DocMessage docMessage) {
-        try {
-            return docMessage == null ? null : coder.encode(docMessage);
-        } catch (CoderException e) {
-            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, e.getMessage(), e);
-        }
+        return encode(docMessage);
     }
 
     @Override
@@ -48,10 +37,6 @@ public class StringToDocMessage implements AttributeConverter<DocMessage, String
         if (message == null) {
             return new DocMessage();
         }
-        try {
-            return coder.decode(message, DocMessage.class);
-        } catch (CoderException e) {
-            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, e.getMessage(), e);
-        }
+        return decode(message, DocMessage.class);
     }
 }
index e755c34..ada09a2 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2022 Nordix Foundation.
+ *  Copyright (C) 2022, 2025 OpenInfra Foundation Europe. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,26 +22,15 @@ package org.onap.policy.clamp.models.acm.persistence.concepts;
 
 import jakarta.persistence.AttributeConverter;
 import jakarta.persistence.Converter;
-import jakarta.ws.rs.core.Response;
 import java.util.HashMap;
 import java.util.Map;
-import org.onap.policy.common.utils.coder.Coder;
-import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.common.utils.coder.StandardCoder;
-import org.onap.policy.models.base.PfModelRuntimeException;
 
 @Converter(autoApply = true)
-public class StringToMapConverter implements AttributeConverter<Map<String, Object>, String> {
-
-    private static final Coder coder = new StandardCoder();
+public class StringToMapConverter extends AbstractConverter implements AttributeConverter<Map<String, Object>, String> {
 
     @Override
     public String convertToDatabaseColumn(Map<String, Object> map) {
-        try {
-            return map == null ? null : coder.encode(map);
-        } catch (CoderException e) {
-            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, e.getMessage(), e);
-        }
+        return encode(map);
     }
 
     @SuppressWarnings("unchecked")
@@ -50,10 +39,6 @@ public class StringToMapConverter implements AttributeConverter<Map<String, Obje
         if (dbData == null) {
             return new HashMap<>();
         }
-        try {
-            return coder.decode(dbData, Map.class);
-        } catch (CoderException e) {
-            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, e.getMessage(), e);
-        }
+        return decode(dbData, Map.class);
     }
 }
index 01806f5..86a3254 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation.
+ *  Copyright (C) 2021, 2025 OpenInfra Foundation Europe. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,25 +22,15 @@ package org.onap.policy.clamp.models.acm.persistence.concepts;
 
 import jakarta.persistence.AttributeConverter;
 import jakarta.persistence.Converter;
-import jakarta.ws.rs.core.Response;
 import org.onap.policy.clamp.models.acm.document.concepts.DocToscaServiceTemplate;
-import org.onap.policy.common.utils.coder.Coder;
-import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.common.utils.coder.StandardCoder;
-import org.onap.policy.models.base.PfModelRuntimeException;
 
 @Converter(autoApply = true)
-public class StringToServiceTemplateConverter implements AttributeConverter<DocToscaServiceTemplate, String> {
-
-    private static final Coder coder = new StandardCoder();
+public class StringToServiceTemplateConverter extends AbstractConverter
+        implements AttributeConverter<DocToscaServiceTemplate, String> {
 
     @Override
     public String convertToDatabaseColumn(DocToscaServiceTemplate serviceTemplate) {
-        try {
-            return serviceTemplate == null ? null : coder.encode(serviceTemplate);
-        } catch (CoderException e) {
-            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, e.getMessage(), e);
-        }
+        return encode(serviceTemplate);
     }
 
     @Override
@@ -48,10 +38,6 @@ public class StringToServiceTemplateConverter implements AttributeConverter<DocT
         if (dbData == null) {
             return new DocToscaServiceTemplate();
         }
-        try {
-            return coder.decode(dbData, DocToscaServiceTemplate.class);
-        } catch (CoderException e) {
-            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, e.getMessage(), e);
-        }
+        return decode(dbData, DocToscaServiceTemplate.class);
     }
 }
index b5f5efd..225c95a 100644 (file)
@@ -210,6 +210,9 @@ public class AutomationCompositionProvider {
             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, errorMessage);
         }
 
+        if (acRollbackRepository.existsById(instanceId.toString())) {
+            acRollbackRepository.deleteById(instanceId.toString());
+        }
         automationCompositionRepository.deleteById(instanceId.toString());
 
         return jpaDeleteAutomationComposition.get().toAuthorative();
@@ -273,11 +276,11 @@ public class AutomationCompositionProvider {
      * @param instanceId the id of the ac instance
      * @return the acRollback object
      */
-    public JpaAutomationCompositionRollback getAutomationCompositionRollback(String instanceId) {
-        var result = acRollbackRepository.findById(instanceId);
+    public AutomationCompositionRollback getAutomationCompositionRollback(UUID instanceId) {
+        var result = acRollbackRepository.findById(instanceId.toString());
         if (result.isEmpty()) {
             throw new PfModelRuntimeException(Status.NOT_FOUND, "Instance not found for rollback");
         }
-        return result.get();
+        return result.get().toAuthorative();
     }
 }
index 7004bb9..3549d1f 100644 (file)
 \r
 package org.onap.policy.clamp.models.acm.persistence.repository;\r
 \r
-import java.util.List;\r
 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionRollback;\r
 import org.springframework.data.jpa.repository.JpaRepository;\r
 \r
 public interface AutomationCompositionRollbackRepository\r
         extends JpaRepository<JpaAutomationCompositionRollback, String> {\r
-\r
-    List<JpaAutomationCompositionRollback> findByCompositionId(String compositionId);\r
 }\r
index a67639d..ea9eadd 100644 (file)
@@ -22,13 +22,9 @@ package org.onap.policy.clamp.models.acm.concepts;
 \r
 import static org.junit.jupiter.api.Assertions.assertEquals;\r
 \r
-import java.util.HashMap;\r
-import java.util.LinkedHashMap;\r
 import java.util.Map;\r
 import java.util.UUID;\r
-import java.util.function.UnaryOperator;\r
 import org.junit.jupiter.api.Test;\r
-import org.onap.policy.models.base.PfUtils;\r
 \r
 class AutomationCompositionRollbackTest {\r
     @Test\r
@@ -36,9 +32,7 @@ class AutomationCompositionRollbackTest {
         var acr0 = new AutomationCompositionRollback();\r
         acr0.setInstanceId(UUID.randomUUID());\r
         acr0.setCompositionId(UUID.randomUUID());\r
-        Map<String, Object> map = new LinkedHashMap<>();\r
-        map.put("test", "test");\r
-        acr0.setElements(PfUtils.mapMap(map, UnaryOperator.identity()));\r
+        acr0.setElements(Map.of(UUID.randomUUID(), new AutomationCompositionElement()));\r
 \r
         var acr1 = new AutomationCompositionRollback(acr0);\r
         assertEquals(acr0, acr1);\r
diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/AbstractConverterTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/AbstractConverterTest.java
new file mode 100644 (file)
index 0000000..5fdcb51
--- /dev/null
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.models.acm.persistence.concepts;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+import org.onap.policy.models.base.PfModelRuntimeException;
+
+class AbstractConverterTest {
+
+    static class TestConverter extends AbstractConverter {
+
+    }
+
+    @Test
+    void testNull() {
+        assertThatThrownBy(() -> AbstractConverter.convertObject("-", Map.class))
+                .isInstanceOf(PfModelRuntimeException.class);
+
+        var converter = new TestConverter();
+        var dbData = converter.encode(null);
+        assertThat(dbData).isNull();
+
+        assertThatThrownBy(() -> converter.decode("-", Map.class))
+                .isInstanceOf(PfModelRuntimeException.class);
+    }
+
+}
index 94d899e..bf91168 100644 (file)
@@ -24,15 +24,12 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\r
 import static org.junit.jupiter.api.Assertions.assertEquals;\r
 \r
-import java.util.HashMap;\r
 import java.util.LinkedHashMap;\r
 import java.util.Map;\r
 import java.util.UUID;\r
-import java.util.function.UnaryOperator;\r
 import org.junit.jupiter.api.Test;\r
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;\r
 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionRollback;\r
-import org.onap.policy.models.base.PfUtils;\r
-\r
 \r
 class JpaAutomationCompositionRollbackTest {\r
 \r
@@ -96,9 +93,8 @@ class JpaAutomationCompositionRollbackTest {
         var testAcmRollback = new AutomationCompositionRollback();\r
         testAcmRollback.setInstanceId(UUID.fromString(INSTANCE_ID));\r
         testAcmRollback.setCompositionId(UUID.fromString(COMPOSITION_ID));\r
-        Map<String, Object> map = new HashMap<>();\r
-        map.put("test", "test");\r
-        testAcmRollback.setElements(PfUtils.mapMap(map, UnaryOperator.identity()));\r
+        var acElement = new AutomationCompositionElement();\r
+        testAcmRollback.setElements(Map.of(acElement.getId(), acElement));\r
 \r
         return testAcmRollback;\r
     }\r
index dd24833..40c2639 100644 (file)
@@ -69,33 +69,24 @@ class AutomationCompositionProviderTest {
     private List<JpaAutomationComposition> inputAutomationCompositionsJpa;
     private final String originalJson = ResourceUtils.getResourceAsString(AUTOMATION_COMPOSITION_JSON);
 
-    private AutomationCompositionProvider automationCompositionProvider;
-    private AutomationCompositionRepository automationCompositionRepository;
-    private AutomationCompositionElementRepository acElementRepository;
-    private AutomationCompositionRollbackRepository acRollbackRepository;
-
     @BeforeEach
     void beforeSetupDao() throws Exception {
         inputAutomationCompositions = CODER.decode(originalJson, AutomationCompositions.class);
         inputAutomationCompositionsJpa =
             ProviderUtils.getJpaAndValidateList(inputAutomationCompositions.getAutomationCompositionList(),
                 JpaAutomationComposition::new, "automation compositions");
-
-        // set mocks
-        automationCompositionRepository = mock(AutomationCompositionRepository.class);
-        acElementRepository = mock(AutomationCompositionElementRepository.class);
-        acRollbackRepository = mock(AutomationCompositionRollbackRepository.class);
-        automationCompositionProvider =
-            new AutomationCompositionProvider(automationCompositionRepository, acElementRepository,
-                acRollbackRepository);
     }
 
     @Test
     void testAutomationCompositionCreate() {
+        var automationCompositionRepository = mock(AutomationCompositionRepository.class);
         when(automationCompositionRepository.save(any(JpaAutomationComposition.class)))
             .thenReturn(inputAutomationCompositionsJpa.get(0));
         var inputAc = inputAutomationCompositions.getAutomationCompositionList().get(0);
 
+        var automationCompositionProvider = new AutomationCompositionProvider(
+                automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
+                mock(AutomationCompositionRollbackRepository.class));
         var createdAutomationComposition = automationCompositionProvider.createAutomationComposition(inputAc);
         inputAc.setInstanceId(createdAutomationComposition.getInstanceId());
         inputAc.setLastMsg(createdAutomationComposition.getLastMsg());
@@ -104,6 +95,10 @@ class AutomationCompositionProviderTest {
 
     @Test
     void testAutomationCompositionUpdate() {
+        var automationCompositionRepository = mock(AutomationCompositionRepository.class);
+        var automationCompositionProvider = new AutomationCompositionProvider(
+                automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
+                mock(AutomationCompositionRollbackRepository.class));
         assertThatThrownBy(() -> automationCompositionProvider.updateAutomationComposition(null))
             .hasMessageMatching(AC_IS_NULL);
 
@@ -118,6 +113,9 @@ class AutomationCompositionProviderTest {
 
     @Test
     void testGetAutomationCompositionsWithNull() {
+        var automationCompositionProvider = new AutomationCompositionProvider(
+                mock(AutomationCompositionRepository.class), mock(AutomationCompositionElementRepository.class),
+                mock(AutomationCompositionRollbackRepository.class));
         assertThatThrownBy(() -> automationCompositionProvider
             .getAutomationCompositions(UUID.randomUUID(), null, null, null))
             .hasMessage("pageable is marked non-null but is null");
@@ -129,6 +127,10 @@ class AutomationCompositionProviderTest {
 
     @Test
     void testGetAutomationCompositions() {
+        var automationCompositionRepository = mock(AutomationCompositionRepository.class);
+        var automationCompositionProvider = new AutomationCompositionProvider(
+                automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
+                mock(AutomationCompositionRollbackRepository.class));
         var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
         when(automationCompositionRepository
             .findAll(Mockito.any(), any(Pageable.class)))
@@ -152,6 +154,10 @@ class AutomationCompositionProviderTest {
     @Test
     void testGetAutomationComposition() {
         var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
+        var automationCompositionRepository = mock(AutomationCompositionRepository.class);
+        var automationCompositionProvider = new AutomationCompositionProvider(
+                automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
+                mock(AutomationCompositionRollbackRepository.class));
         assertThatThrownBy(
             () -> automationCompositionProvider.getAutomationComposition(automationComposition.getInstanceId()))
             .hasMessageMatching("AutomationComposition not found");
@@ -165,6 +171,10 @@ class AutomationCompositionProviderTest {
     @Test
     void testFindAutomationComposition() {
         var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
+        var automationCompositionRepository = mock(AutomationCompositionRepository.class);
+        var automationCompositionProvider = new AutomationCompositionProvider(
+                automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
+                mock(AutomationCompositionRollbackRepository.class));
         var acOpt = automationCompositionProvider.findAutomationComposition(automationComposition.getInstanceId());
         assertThat(acOpt).isEmpty();
 
@@ -185,8 +195,12 @@ class AutomationCompositionProviderTest {
     @Test
     void testGetAcInstancesByCompositionId() {
         var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
+        var automationCompositionRepository = mock(AutomationCompositionRepository.class);
         when(automationCompositionRepository.findByCompositionId(automationComposition.getCompositionId().toString()))
             .thenReturn(inputAutomationCompositionsJpa);
+        var automationCompositionProvider = new AutomationCompositionProvider(
+                automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
+                mock(AutomationCompositionRollbackRepository.class));
         var acList =
             automationCompositionProvider.getAcInstancesByCompositionId(automationComposition.getCompositionId());
         assertEquals(inputAutomationCompositions.getAutomationCompositionList(), acList);
@@ -202,11 +216,15 @@ class AutomationCompositionProviderTest {
         List<JpaAutomationComposition> res1 = new ArrayList<>();
         res1.add(inputAutomationCompositionsJpa.get(0));
 
+        var automationCompositionRepository = mock(AutomationCompositionRepository.class);
         when(automationCompositionRepository.findByDeployStateIn(List.of(DeployState.DEPLOYING,
             DeployState.UNDEPLOYING, DeployState.DELETING, DeployState.UPDATING, DeployState.MIGRATING)))
             .thenReturn(res1);
         when(automationCompositionRepository.findByLockStateIn(List.of(LockState.LOCKING, LockState.UNLOCKING)))
             .thenReturn(List.of(inputAutomationCompositionsJpa.get(1)));
+        var automationCompositionProvider = new AutomationCompositionProvider(
+                automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
+                mock(AutomationCompositionRollbackRepository.class));
         var acList = automationCompositionProvider.getAcInstancesInTransition();
         assertThat(acList).hasSize(2)
             .contains(inputAutomationCompositions.getAutomationCompositionList().get(0).getInstanceId())
@@ -215,9 +233,17 @@ class AutomationCompositionProviderTest {
 
     @Test
     void testDeleteAutomationComposition() {
+        var automationCompositionRepository = mock(AutomationCompositionRepository.class);
+        var acRollbackRepository = mock(AutomationCompositionRollbackRepository.class);
+        var automationCompositionProvider = new AutomationCompositionProvider(
+                automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
+                acRollbackRepository);
         assertThatThrownBy(() -> automationCompositionProvider.deleteAutomationComposition(UUID.randomUUID()))
             .hasMessageMatching(".*.failed, automation composition does not exist");
 
+        assertThatThrownBy(() -> automationCompositionProvider.deleteAutomationComposition(null))
+                .hasMessageMatching("instanceId is marked non-null but is null");
+
         var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
         when(automationCompositionRepository.findById(automationComposition.getInstanceId().toString()))
             .thenReturn(Optional.of(inputAutomationCompositionsJpa.get(0)));
@@ -225,10 +251,22 @@ class AutomationCompositionProviderTest {
         var deletedAc =
             automationCompositionProvider.deleteAutomationComposition(automationComposition.getInstanceId());
         assertEquals(automationComposition, deletedAc);
+
+        when(acRollbackRepository.existsById(automationComposition.getInstanceId().toString())).thenReturn(true);
+
+        deletedAc =
+                automationCompositionProvider.deleteAutomationComposition(automationComposition.getInstanceId());
+        assertEquals(automationComposition, deletedAc);
+        verify(acRollbackRepository).deleteById(automationComposition.getInstanceId().toString());
     }
 
     @Test
     void testDeleteElementById() {
+        var automationCompositionRepository = mock(AutomationCompositionRepository.class);
+        var acElementRepository = mock(AutomationCompositionElementRepository.class);
+        var automationCompositionProvider = new AutomationCompositionProvider(
+                automationCompositionRepository, acElementRepository,
+                mock(AutomationCompositionRollbackRepository.class));
         assertThatThrownBy(() -> automationCompositionProvider.deleteAutomationCompositionElement(null))
             .hasMessageMatching(ACELEMENT_ID_IS_NULL);
         var elementId = UUID.randomUUID();
@@ -240,6 +278,10 @@ class AutomationCompositionProviderTest {
     void testValidateElementIds() {
         var ac = inputAutomationCompositions.getAutomationCompositionList().get(0);
 
+        var acElementRepository = mock(AutomationCompositionElementRepository.class);
+        var automationCompositionProvider = new AutomationCompositionProvider(
+                mock(AutomationCompositionRepository.class), acElementRepository,
+                mock(AutomationCompositionRollbackRepository.class));
         var result = automationCompositionProvider.validateElementIds(ac);
         assertThat(result.isValid()).isTrue();
 
@@ -265,11 +307,17 @@ class AutomationCompositionProviderTest {
     @Test
     void testCopyAcElements() {
         var ac = inputAutomationCompositions.getAutomationCompositionList().get(0);
+        var automationCompositionRepository = mock(AutomationCompositionRepository.class);
+        var acRollbackRepository = mock(AutomationCompositionRollbackRepository.class);
+        var automationCompositionProvider = new AutomationCompositionProvider(
+                automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
+                acRollbackRepository);
         automationCompositionProvider.copyAcElementsBeforeUpdate(ac);
 
         verify(acRollbackRepository).save(any(JpaAutomationCompositionRollback.class));
-        assertThrows(PfModelRuntimeException.class, () -> automationCompositionProvider // NOSONAR
-            .getAutomationCompositionRollback(ac.getInstanceId().toString()));
+        var instanceId = ac.getInstanceId();
+        assertThrows(PfModelRuntimeException.class, () -> automationCompositionProvider
+            .getAutomationCompositionRollback(instanceId));
     }
 
     @Test
@@ -279,17 +327,25 @@ class AutomationCompositionProviderTest {
         rollback.setInstanceId(ac.getInstanceId().toString());
         rollback.setCompositionId(ac.getCompositionId().toString());
 
+        var acRollbackRepository = mock(AutomationCompositionRollbackRepository.class);
         when(acRollbackRepository.findById(anyString())).thenReturn(Optional.of(rollback));
 
-        var rbFromDb = automationCompositionProvider.getAutomationCompositionRollback(ac.getInstanceId()
-            .toString());
+        var automationCompositionProvider = new AutomationCompositionProvider(
+                mock(AutomationCompositionRepository.class), mock(AutomationCompositionElementRepository.class),
+                acRollbackRepository);
+        var rbFromDb = automationCompositionProvider.getAutomationCompositionRollback(ac.getInstanceId());
         assertNotNull(rbFromDb);
     }
 
     @Test
     void testGetRollbackEmpty() {
+        var acRollbackRepository = mock(AutomationCompositionRollbackRepository.class);
+        var automationCompositionProvider = new AutomationCompositionProvider(
+                mock(AutomationCompositionRepository.class), mock(AutomationCompositionElementRepository.class),
+                acRollbackRepository);
         when(acRollbackRepository.findById(anyString())).thenReturn(Optional.empty());
+        var compositionId = UUID.randomUUID();
         assertThrows(PfModelRuntimeException.class, () -> automationCompositionProvider
-            .getAutomationCompositionRollback("empty"));
+            .getAutomationCompositionRollback(compositionId));
     }
 }
index 14660a8..fdafcf0 100644 (file)
@@ -23,10 +23,9 @@ package org.onap.policy.clamp.acm.runtime.instantiation;
 
 import jakarta.validation.Valid;
 import jakarta.ws.rs.core.Response.Status;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.UUID;
+import java.util.function.UnaryOperator;
 import java.util.stream.Collectors;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
@@ -463,25 +462,21 @@ public class AutomationCompositionInstantiationProvider {
      * Rollback AC Instance.
      *
      * @param instanceId the instanceId
-     * @return the instantiation response
      */
-    public InstantiationResponse rollback(UUID instanceId) {
+    public void rollback(UUID instanceId) {
         var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId);
         var automationCompositionToRollback =
-            automationCompositionProvider.getAutomationCompositionRollback(instanceId.toString());
+            automationCompositionProvider.getAutomationCompositionRollback(instanceId);
 
         if (DeployState.DEPLOYED.equals(automationComposition.getDeployState())
               && SubState.NONE.equals(automationComposition.getSubState())
               && StateChangeResult.NO_ERROR.equals(automationComposition.getStateChangeResult())) {
-            automationComposition.setCompositionId(UUID.fromString(automationCompositionToRollback.getCompositionId()));
-            Map<UUID, AutomationCompositionElement> elements = new HashMap<>();
-            automationCompositionToRollback.getElements().forEach((String uuid, Object acElement) ->
-                elements.put(UUID.fromString(uuid), (AutomationCompositionElement) acElement));
-            automationComposition.setElements(elements);
+            automationComposition.setCompositionId(automationCompositionToRollback.getCompositionId());
+            automationComposition.setElements(automationCompositionToRollback.getElements().values().stream()
+                    .collect(Collectors.toMap(AutomationCompositionElement::getId, UnaryOperator.identity())));
             automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR);
             AcmUtils.setCascadedState(automationComposition, DeployState.MIGRATION_REVERTING, LockState.LOCKED);
             automationCompositionProvider.updateAutomationComposition(automationComposition);
-            return createInstantiationResponse(automationComposition);
         } else {
             throw new PfModelRuntimeException(Status.BAD_REQUEST, "Invalid state for rollback");
         }
index 70d6554..a604fd5 100644 (file)
@@ -27,7 +27,6 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -37,7 +36,6 @@ import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVIC
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
 import java.util.UUID;
 import org.junit.jupiter.api.BeforeAll;
@@ -49,7 +47,6 @@ import org.onap.policy.clamp.acm.runtime.util.CommonTestData;
 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition;
-import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
 import org.onap.policy.clamp.models.acm.concepts.DeployState;
 import org.onap.policy.clamp.models.acm.concepts.LockState;
 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
@@ -67,7 +64,6 @@ import org.onap.policy.clamp.models.acm.persistence.provider.ProviderUtils;
 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
 import org.onap.policy.models.base.PfConceptKey;
 import org.onap.policy.models.base.PfModelRuntimeException;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
 import org.springframework.data.domain.Pageable;
@@ -568,8 +564,8 @@ class AutomationCompositionInstantiationProviderTest {
         var acProvider = mock(AutomationCompositionProvider.class);
         when(acProvider.getAutomationComposition(automationComposition.getInstanceId()))
             .thenReturn(automationComposition);
-        var rollbackRecord = mock(JpaAutomationCompositionRollback.class);
-        when(acProvider.getAutomationCompositionRollback(anyString())).thenReturn(rollbackRecord);
+        var rollbackRecord = new JpaAutomationCompositionRollback();
+        when(acProvider.getAutomationCompositionRollback(any(UUID.class))).thenReturn(rollbackRecord.toAuthorative());
 
         final var acDefinitionProvider = mock(AcDefinitionProvider.class);
         final var supervisionAcHandler = mock(SupervisionAcHandler.class);
@@ -579,29 +575,26 @@ class AutomationCompositionInstantiationProviderTest {
             new AcInstanceStateResolver(), supervisionAcHandler, participantProvider, new AcRuntimeParameterGroup(),
             encryptionUtils);
 
-        assertThrows(PfModelRuntimeException.class, () -> instantiationProvider
-            .rollback(automationComposition.getInstanceId()));
+        var instanceId = automationComposition.getInstanceId();
+        assertThrows(PfModelRuntimeException.class, () -> instantiationProvider.rollback(instanceId));
 
         // DeployState != MIGRATION_REVERTING
         when(acProvider.getAutomationComposition(automationComposition.getInstanceId()))
             .thenReturn(automationComposition);
-        when(acProvider.getAutomationCompositionRollback(anyString())).thenReturn(rollbackRecord);
+        when(acProvider.getAutomationCompositionRollback(any(UUID.class))).thenReturn(rollbackRecord.toAuthorative());
 
         automationComposition.setDeployState(DeployState.DELETING);
-        assertThrows(PfModelRuntimeException.class, () -> instantiationProvider
-            .rollback(automationComposition.getInstanceId()));
+        assertThrows(PfModelRuntimeException.class, () -> instantiationProvider.rollback(instanceId));
 
         // SubState != NONE
         automationComposition.setDeployState(DeployState.DEPLOYED);
         automationComposition.setSubState(SubState.PREPARING);
-        assertThrows(PfModelRuntimeException.class, () -> instantiationProvider
-            .rollback(automationComposition.getInstanceId()));
+        assertThrows(PfModelRuntimeException.class, () -> instantiationProvider.rollback(instanceId));
 
         // StateChangeResult != NO_ERROR
         automationComposition.setSubState(SubState.NONE);
         automationComposition.setStateChangeResult(StateChangeResult.FAILED);
-        assertThrows(PfModelRuntimeException.class, () -> instantiationProvider
-            .rollback(automationComposition.getInstanceId()));
+        assertThrows(PfModelRuntimeException.class, () -> instantiationProvider.rollback(instanceId));
 
         verify(acProvider, never()).updateAutomationComposition(any());
     }
@@ -636,7 +629,7 @@ class AutomationCompositionInstantiationProviderTest {
 
         when(acProvider.getAutomationComposition(automationComposition.getInstanceId()))
             .thenReturn(automationComposition);
-        when(acProvider.getAutomationCompositionRollback(anyString())).thenReturn(rollbackRecord);
+        when(acProvider.getAutomationCompositionRollback(any(UUID.class))).thenReturn(rollbackRecord.toAuthorative());
 
         instantiationProvider.rollback(automationComposition.getInstanceId());