Merge "Update openapi.yaml swagger with new status codes"
diff --git a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/acm/participant/http/main/webclient/AcHttpClient.java b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/acm/participant/http/main/webclient/AcHttpClient.java
index a88f93a..1956b0d 100644
--- a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/acm/participant/http/main/webclient/AcHttpClient.java
+++ b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/acm/participant/http/main/webclient/AcHttpClient.java
@@ -92,7 +92,7 @@
                 LOGGER.error("Error occurred on the HTTP response ", ex);
                 responseMap.put(request.getRestRequestId(),
                         new ImmutablePair<>(ex.getStatusCode().value(), ex.getResponseBodyAsString()));
-            } catch (WebClientRequestException ex) {
+            } catch (WebClientRequestException | IllegalStateException ex) {
                 LOGGER.error("Error occurred on the HTTP request ", ex);
                 responseMap.put(request.getRestRequestId(), new ImmutablePair<>(404, ex.getMessage()));
             }
diff --git a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/utils/TestListenerUtils.java b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/utils/TestListenerUtils.java
index 17d9618..5c4f06d 100644
--- a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/utils/TestListenerUtils.java
+++ b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/utils/TestListenerUtils.java
@@ -52,6 +52,7 @@
         var participantId = CommonTestData.getParticipantId();
 
         participantPrimeMsg.setParticipantId(participantId);
+        participantPrimeMsg.setCompositionId(UUID.randomUUID());
         participantPrimeMsg.setTimestamp(Instant.now());
         participantPrimeMsg.setTimestamp(Instant.ofEpochMilli(3000));
         participantPrimeMsg.setMessageId(UUID.randomUUID());
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/comm/AcPropertyUpdateListener.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/comm/AcPropertyUpdateListener.java
index d6f1970..68eb175 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/comm/AcPropertyUpdateListener.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/comm/AcPropertyUpdateListener.java
@@ -21,7 +21,6 @@
 package org.onap.policy.clamp.acm.participant.intermediary.comm;
 
 import org.onap.policy.clamp.acm.participant.intermediary.handler.ParticipantHandler;
-import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionDeploy;
 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantMessageType;
 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.PropertiesUpdate;
 import org.springframework.stereotype.Component;
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java
new file mode 100644
index 0000000..665baee
--- /dev/null
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java
@@ -0,0 +1,199 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * 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.acm.participant.intermediary.handler;
+
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import lombok.RequiredArgsConstructor;
+import org.onap.policy.clamp.acm.participant.intermediary.comm.ParticipantMessagePublisher;
+import org.onap.policy.clamp.models.acm.concepts.AcElementDeployAck;
+import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementInfo;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionInfo;
+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.ParticipantState;
+import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
+import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionDeployAck;
+import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantMessageType;
+import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class AutomationCompositionOutHandler {
+    private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionOutHandler.class);
+
+    private final ParticipantMessagePublisher publisher;
+    private final CacheProvider cacheProvider;
+
+    /**
+     * Handle a automation composition element state change message.
+     *
+     * @param automationCompositionId the automationComposition Id
+     * @param elementId the automationComposition Element Id
+     * @param deployState the DeployState state
+     * @param lockState the LockState state
+     * @param message the message
+     * @param stateChangeResult the indicator if error occurs
+     */
+    public void updateAutomationCompositionElementState(UUID automationCompositionId, UUID elementId,
+            DeployState deployState, LockState lockState, StateChangeResult stateChangeResult, String message) {
+
+        if (automationCompositionId == null || elementId == null) {
+            LOGGER.error("Cannot update Automation composition element state, id is null");
+            return;
+        }
+
+        if ((deployState != null && lockState != null) || (deployState == null && lockState == null)) {
+            LOGGER.error("state error {} and {} cannot be handled", deployState, lockState);
+            return;
+        }
+
+        var automationComposition = cacheProvider.getAutomationComposition(automationCompositionId);
+        if (automationComposition == null) {
+            LOGGER.error("Cannot update Automation composition element state, Automation composition id {} not present",
+                    automationCompositionId);
+            return;
+        }
+
+        var element = automationComposition.getElements().get(elementId);
+        if (element == null) {
+            var msg = "Cannot update Automation composition element state, AC Element id {} not present";
+            LOGGER.error(msg, elementId);
+            return;
+        }
+
+        if (deployState != null) {
+            handleDeployState(automationComposition, element, deployState);
+        }
+        if (lockState != null) {
+            handleLockState(automationComposition, element, lockState);
+        }
+
+        var automationCompositionStateChangeAck =
+                new AutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK);
+        automationCompositionStateChangeAck.setParticipantId(cacheProvider.getParticipantId());
+        automationCompositionStateChangeAck.setMessage(message);
+        automationCompositionStateChangeAck.setStateChangeResult(stateChangeResult);
+        automationCompositionStateChangeAck.setAutomationCompositionId(automationCompositionId);
+        automationCompositionStateChangeAck.getAutomationCompositionResultMap().put(element.getId(),
+                new AcElementDeployAck(element.getDeployState(), element.getLockState(), element.getOperationalState(),
+                        element.getUseState(), element.getOutProperties(), true, message));
+        LOGGER.debug("Automation composition element {} state changed to {}", elementId, deployState);
+        automationCompositionStateChangeAck.setResult(true);
+        publisher.sendAutomationCompositionAck(automationCompositionStateChangeAck);
+    }
+
+    private void handleDeployState(AutomationComposition automationComposition, AutomationCompositionElement element,
+            DeployState deployState) {
+        element.setDeployState(deployState);
+        element.setLockState(DeployState.DEPLOYED.equals(element.getDeployState()) ? LockState.LOCKED : LockState.NONE);
+        var checkOpt = automationComposition.getElements().values().stream()
+                .filter(acElement -> !deployState.equals(acElement.getDeployState())).findAny();
+        if (checkOpt.isEmpty()) {
+            automationComposition.setDeployState(deployState);
+            automationComposition.setLockState(element.getLockState());
+
+            if (DeployState.DELETED.equals(deployState)) {
+                cacheProvider.removeAutomationComposition(automationComposition.getInstanceId());
+            }
+        }
+    }
+
+    private void handleLockState(AutomationComposition automationComposition, AutomationCompositionElement element,
+            LockState lockState) {
+        element.setLockState(lockState);
+        var checkOpt = automationComposition.getElements().values().stream()
+                .filter(acElement -> !lockState.equals(acElement.getLockState())).findAny();
+        if (checkOpt.isEmpty()) {
+            automationComposition.setLockState(lockState);
+        }
+    }
+
+    /**
+     * Send Ac Element Info.
+     *
+     * @param automationCompositionId the automationComposition Id
+     * @param elementId the automationComposition Element id
+     * @param useState the use State
+     * @param operationalState the operational State
+     * @param outProperties the output Properties Map
+     */
+    public void sendAcElementInfo(UUID automationCompositionId, UUID elementId, String useState,
+            String operationalState, Map<String, Object> outProperties) {
+
+        if (automationCompositionId == null || elementId == null) {
+            LOGGER.error("Cannot update Automation composition element state, id is null");
+            return;
+        }
+
+        var automationComposition = cacheProvider.getAutomationComposition(automationCompositionId);
+        if (automationComposition == null) {
+            LOGGER.error("Cannot update Automation composition element state, Automation composition id {} not present",
+                    automationComposition);
+            return;
+        }
+
+        var element = automationComposition.getElements().get(elementId);
+        if (element == null) {
+            var msg = "Cannot update Automation composition element state, AC Element id {} not present";
+            LOGGER.error(msg, automationComposition);
+            return;
+        }
+        element.setOperationalState(operationalState);
+        element.setUseState(useState);
+        element.setOutProperties(outProperties);
+
+        var statusMsg = new ParticipantStatus();
+        statusMsg.setParticipantId(cacheProvider.getParticipantId());
+        statusMsg.setState(ParticipantState.ON_LINE);
+        statusMsg.setParticipantSupportedElementType(cacheProvider.getSupportedAcElementTypes());
+        var acInfo = new AutomationCompositionInfo();
+        acInfo.setAutomationCompositionId(automationCompositionId);
+        acInfo.setDeployState(automationComposition.getDeployState());
+        acInfo.setLockState(automationComposition.getLockState());
+        acInfo.setElements(List.of(getAutomationCompositionElementInfo(element)));
+        statusMsg.setAutomationCompositionInfoList(List.of(acInfo));
+        publisher.sendParticipantStatus(statusMsg);
+    }
+
+    /**
+     * Get AutomationCompositionElementInfo from AutomationCompositionElement.
+     *
+     * @param element the AutomationCompositionElement
+     * @return the AutomationCompositionElementInfo
+     */
+    public AutomationCompositionElementInfo getAutomationCompositionElementInfo(AutomationCompositionElement element) {
+        var elementInfo = new AutomationCompositionElementInfo();
+        elementInfo.setAutomationCompositionElementId(element.getId());
+        elementInfo.setDeployState(element.getDeployState());
+        elementInfo.setLockState(element.getLockState());
+        elementInfo.setOperationalState(element.getOperationalState());
+        elementInfo.setUseState(element.getUseState());
+        elementInfo.setOutProperties(element.getOutProperties());
+        return elementInfo;
+    }
+}
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProvider.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProvider.java
new file mode 100644
index 0000000..09e75e8
--- /dev/null
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProvider.java
@@ -0,0 +1,150 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * 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.acm.participant.intermediary.handler;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import lombok.Getter;
+import lombok.NonNull;
+import org.onap.policy.clamp.acm.participant.intermediary.parameters.ParticipantParameters;
+import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition;
+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.ParticipantDeploy;
+import org.onap.policy.clamp.models.acm.concepts.ParticipantSupportedElementType;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CacheProvider {
+
+    @Getter
+    private final UUID participantId;
+
+    private final List<ParticipantSupportedElementType> supportedAcElementTypes;
+
+    @Getter
+    private final Map<UUID, AutomationComposition> automationCompositions = new ConcurrentHashMap<>();
+
+    @Getter
+    private final Map<UUID, Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition>> acElementsDefinitions =
+            new ConcurrentHashMap<>();
+
+    /**
+     * Constructor.
+     *
+     * @param parameters the parameters of the participant
+     */
+    public CacheProvider(ParticipantParameters parameters) {
+        this.participantId = parameters.getIntermediaryParameters().getParticipantId();
+        this.supportedAcElementTypes = parameters.getIntermediaryParameters().getParticipantSupportedElementTypes();
+    }
+
+    public List<ParticipantSupportedElementType> getSupportedAcElementTypes() {
+        return PfUtils.mapList(supportedAcElementTypes, ParticipantSupportedElementType::new);
+    }
+
+    /**
+     * Get AutomationComposition by id.
+     *
+     * @param automationCompositionId the AutomationComposition Id
+     * @return the AutomationComposition
+     */
+    public AutomationComposition getAutomationComposition(@NonNull UUID automationCompositionId) {
+        return automationCompositions.get(automationCompositionId);
+    }
+
+    /**
+     * Remove AutomationComposition.
+     *
+     * @param automationCompositionId the AutomationComposition Id
+     */
+    public void removeAutomationComposition(@NonNull UUID automationCompositionId) {
+        automationCompositions.remove(automationCompositionId);
+    }
+
+    /**
+     * Add ElementDefinition.
+     *
+     * @param compositionId the composition Id
+     * @param list the list of AutomationCompositionElementDefinition to add
+     */
+    public void addElementDefinition(@NonNull UUID compositionId, List<AutomationCompositionElementDefinition> list) {
+        Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition> map = new HashMap<>();
+        for (var acElementDefinition : list) {
+            map.put(acElementDefinition.getAcElementDefinitionId(), acElementDefinition);
+        }
+        acElementsDefinitions.put(compositionId, map);
+    }
+
+    public void removeElementDefinition(@NonNull UUID compositionId) {
+        acElementsDefinitions.remove(compositionId);
+    }
+
+    /**
+     * Get CommonProperties.
+     *
+     * @param instanceId the Automation Composition Id
+     * @param acElementId the Automation Composition Element Id
+     * @return the common Properties as Map
+     */
+    public Map<String, Object> getCommonProperties(@NonNull UUID instanceId, @NonNull UUID acElementId) {
+        var automationComposition = automationCompositions.get(instanceId);
+        var map = acElementsDefinitions.get(automationComposition.getCompositionId());
+        var element = automationComposition.getElements().get(acElementId);
+        return map.get(element.getDefinition()).getAutomationCompositionElementToscaNodeTemplate().getProperties();
+    }
+
+    /**
+     * Initialize an AutomationComposition from a ParticipantDeploy.
+     *
+     * @param compositionId the composition Id
+     * @param instanceId the Automation Composition Id
+     * @param participantDeploy the ParticipantDeploy
+     */
+    public void initializeAutomationComposition(@NonNull UUID compositionId, @NonNull UUID instanceId,
+            ParticipantDeploy participantDeploy) {
+        Map<UUID, AutomationCompositionElement> acElementMap = new LinkedHashMap<>();
+        for (var element : participantDeploy.getAcElementList()) {
+            var acElement = new AutomationCompositionElement();
+            acElement.setId(element.getId());
+            acElement.setParticipantId(getParticipantId());
+            acElement.setDefinition(element.getDefinition());
+            acElement.setDeployState(DeployState.DEPLOYING);
+            acElement.setLockState(LockState.NONE);
+            acElement.setProperties(element.getProperties());
+            acElementMap.put(element.getId(), acElement);
+        }
+
+        var automationComposition = new AutomationComposition();
+        automationComposition.setCompositionId(compositionId);
+        automationComposition.setInstanceId(instanceId);
+        automationComposition.setElements(acElementMap);
+        automationCompositions.put(automationComposition.getInstanceId(), automationComposition);
+    }
+}
diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/comm/ParticipantCommTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/comm/ParticipantCommTest.java
index 1540d6e..1dbf0b1 100644
--- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/comm/ParticipantCommTest.java
+++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/comm/ParticipantCommTest.java
@@ -20,19 +20,23 @@
 
 package org.onap.policy.clamp.acm.participant.intermediary.comm;
 
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
 
 import java.util.Collections;
 import java.util.List;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
+import org.onap.policy.clamp.acm.participant.intermediary.handler.ParticipantHandler;
 import org.onap.policy.clamp.acm.participant.intermediary.main.parameters.CommonTestData;
 import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException;
 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionDeployAck;
 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantDeregister;
 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantMessageType;
+import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantPrimeAck;
 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantRegister;
 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantStatus;
 import org.onap.policy.common.endpoints.event.comm.TopicSink;
@@ -40,11 +44,9 @@
 
 class ParticipantCommTest {
 
-    private final CommonTestData commonTestData = new CommonTestData();
-
     @Test
     void participantReqTest() throws CoderException {
-        var participantHandler = commonTestData.getParticipantHandlerAutomationCompositions();
+        var participantHandler = mock(ParticipantHandler.class);
 
         var participantRegisterAckListener = new ParticipantRegisterAckListener(participantHandler);
         assertEquals(ParticipantMessageType.PARTICIPANT_REGISTER_ACK.name(), participantRegisterAckListener.getType());
@@ -54,51 +56,75 @@
 
         var participantDeregisterAckListener = new ParticipantDeregisterAckListener(participantHandler);
         assertEquals(ParticipantMessageType.PARTICIPANT_DEREGISTER_ACK.name(),
-            participantDeregisterAckListener.getType());
+                participantDeregisterAckListener.getType());
 
         var participantPrimeListener = new ParticipantPrimeListener(participantHandler);
         assertEquals(ParticipantMessageType.PARTICIPANT_PRIME.name(), participantPrimeListener.getType());
 
+        var acPropertyUpdateListener = new AcPropertyUpdateListener(participantHandler);
+        assertEquals(ParticipantMessageType.PROPERTIES_UPDATE.name(), acPropertyUpdateListener.getType());
+
         var automationCompositionUpdateListener = new AutomationCompositionDeployListener(participantHandler);
         assertEquals(ParticipantMessageType.AUTOMATION_COMPOSITION_DEPLOY.name(),
-            automationCompositionUpdateListener.getType());
+                automationCompositionUpdateListener.getType());
 
         var automationCompositionStateChangeListener = new AutomationCompositionStateChangeListener(participantHandler);
         assertEquals(ParticipantMessageType.AUTOMATION_COMPOSITION_STATE_CHANGE.name(),
-            automationCompositionStateChangeListener.getType());
+                automationCompositionStateChangeListener.getType());
+    }
+
+    @Test
+    void participantMessagePublisherTest() {
+        var publisher = new ParticipantMessagePublisher();
+        publisher.active(Collections.singletonList(Mockito.mock(TopicSink.class)));
+        var participantStatus = new ParticipantStatus();
+        assertDoesNotThrow(() -> publisher.sendParticipantStatus(participantStatus));
+
+        assertDoesNotThrow(() -> publisher.sendHeartbeat(participantStatus));
+
+        var participantRegister = new ParticipantRegister();
+        assertDoesNotThrow(() -> publisher.sendParticipantRegister(participantRegister));
+
+        var participantDeregister = new ParticipantDeregister();
+        assertDoesNotThrow(() -> publisher.sendParticipantDeregister(participantDeregister));
+
+        var participantPrimeAck = new ParticipantPrimeAck();
+        assertDoesNotThrow(() -> publisher.sendParticipantPrimeAck(participantPrimeAck));
+
+        var automationCompositionAck = mock(AutomationCompositionDeployAck.class);
+        assertDoesNotThrow(() -> publisher.sendAutomationCompositionAck(automationCompositionAck));
     }
 
     @Test
     void participantMessagePublisherExceptionsTest() {
-        var participantMessagePublisher = new ParticipantMessagePublisher();
+        var publisher = new ParticipantMessagePublisher();
 
-        var participantStatus = Mockito.mock(ParticipantStatus.class);
+        var participantStatus = new ParticipantStatus();
         assertThrows(AutomationCompositionRuntimeException.class,
-            () -> participantMessagePublisher.sendParticipantStatus(participantStatus));
-        assertThrows(AutomationCompositionRuntimeException.class,
-            () -> participantMessagePublisher.sendHeartbeat(participantStatus));
+                () -> publisher.sendParticipantStatus(participantStatus));
+        assertThrows(AutomationCompositionRuntimeException.class, () -> publisher.sendHeartbeat(participantStatus));
 
-        var participantRegister = Mockito.mock(ParticipantRegister.class);
+        var participantRegister = new ParticipantRegister();
         assertThrows(AutomationCompositionRuntimeException.class,
-            () -> participantMessagePublisher.sendParticipantRegister(participantRegister));
+                () -> publisher.sendParticipantRegister(participantRegister));
 
-        var participantDeregister = Mockito.mock(ParticipantDeregister.class);
+        var participantDeregister = new ParticipantDeregister();
         assertThrows(AutomationCompositionRuntimeException.class,
-            () -> participantMessagePublisher.sendParticipantDeregister(participantDeregister));
+                () -> publisher.sendParticipantDeregister(participantDeregister));
 
-        var automationCompositionAck = Mockito.mock(AutomationCompositionDeployAck.class);
+        var automationCompositionAck = mock(AutomationCompositionDeployAck.class);
         assertThrows(AutomationCompositionRuntimeException.class,
-            () -> participantMessagePublisher.sendAutomationCompositionAck(automationCompositionAck));
+                () -> publisher.sendAutomationCompositionAck(automationCompositionAck));
 
         List<TopicSink> emptyList = Collections.emptyList();
-        assertThrows(IllegalArgumentException.class, () -> participantMessagePublisher.active(emptyList));
+        assertThrows(IllegalArgumentException.class, () -> publisher.active(emptyList));
 
-        participantMessagePublisher.stop();
+        publisher.stop();
     }
 
     @Test
     void messageSenderTest() throws CoderException {
-        var participantHandler = commonTestData.getParticipantHandlerAutomationCompositions();
+        var participantHandler = mock(ParticipantHandler.class);
         var participantParameters = CommonTestData.getParticipantParameters();
         var messageSender = new MessageSender(participantHandler, participantParameters);
         messageSender.run();
diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandlerTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandlerTest.java
new file mode 100644
index 0000000..3f022dc
--- /dev/null
+++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandlerTest.java
@@ -0,0 +1,142 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * 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.acm.participant.intermediary.handler;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Map;
+import java.util.UUID;
+import org.junit.jupiter.api.Test;
+import org.onap.policy.clamp.acm.participant.intermediary.comm.ParticipantMessagePublisher;
+import org.onap.policy.clamp.acm.participant.intermediary.main.parameters.CommonTestData;
+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;
+import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionDeployAck;
+import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantStatus;
+
+class AutomationCompositionOutHandlerTest {
+
+    @Test
+    void updateAutomationCompositionElementStateNullTest() {
+        var cacheProvider = mock(CacheProvider.class);
+        var acOutHandler = new AutomationCompositionOutHandler(mock(ParticipantMessagePublisher.class), cacheProvider);
+
+        assertDoesNotThrow(
+                () -> acOutHandler.updateAutomationCompositionElementState(null, null, null, null, null, null));
+        assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState(UUID.randomUUID(),
+                UUID.randomUUID(), null, null, null, null));
+        assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState(UUID.randomUUID(),
+                UUID.randomUUID(), DeployState.DEPLOYED, null, null, null));
+
+        var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
+        when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
+                .thenReturn(automationComposition);
+        assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState(
+                automationComposition.getInstanceId(), UUID.randomUUID(), DeployState.DEPLOYED, null, null, null));
+    }
+
+    @Test
+    void updateAutomationCompositionElementStateDeployedTest() {
+        var publisher = mock(ParticipantMessagePublisher.class);
+        var cacheProvider = mock(CacheProvider.class);
+        var acOutHandler = new AutomationCompositionOutHandler(publisher, cacheProvider);
+
+        var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
+        when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
+                .thenReturn(automationComposition);
+        var elementId = automationComposition.getElements().values().iterator().next().getId();
+        acOutHandler.updateAutomationCompositionElementState(automationComposition.getInstanceId(), elementId,
+                DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed");
+        verify(publisher).sendAutomationCompositionAck(any(AutomationCompositionDeployAck.class));
+    }
+
+    @Test
+    void updateAutomationCompositionElementStateLockTest() {
+        var publisher = mock(ParticipantMessagePublisher.class);
+        var cacheProvider = mock(CacheProvider.class);
+        var acOutHandler = new AutomationCompositionOutHandler(publisher, cacheProvider);
+
+        var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
+        when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
+                .thenReturn(automationComposition);
+        var elementId = automationComposition.getElements().values().iterator().next().getId();
+        acOutHandler.updateAutomationCompositionElementState(automationComposition.getInstanceId(), elementId, null,
+                LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked");
+        verify(publisher).sendAutomationCompositionAck(any(AutomationCompositionDeployAck.class));
+    }
+
+    @Test
+    void updateAutomationCompositionElementStateDeleteTest() {
+        var publisher = mock(ParticipantMessagePublisher.class);
+        var cacheProvider = mock(CacheProvider.class);
+        var acOutHandler = new AutomationCompositionOutHandler(publisher, cacheProvider);
+
+        var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
+        when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
+                .thenReturn(automationComposition);
+        for (var element : automationComposition.getElements().values()) {
+            acOutHandler.updateAutomationCompositionElementState(automationComposition.getInstanceId(), element.getId(),
+                    DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted");
+        }
+        verify(publisher, times(automationComposition.getElements().size()))
+                .sendAutomationCompositionAck(any(AutomationCompositionDeployAck.class));
+        verify(cacheProvider).removeAutomationComposition(automationComposition.getInstanceId());
+    }
+
+    @Test
+    void sendAcElementInfoTestNull() {
+        var publisher = mock(ParticipantMessagePublisher.class);
+        var cacheProvider = mock(CacheProvider.class);
+        var acOutHandler = new AutomationCompositionOutHandler(publisher, cacheProvider);
+
+        assertDoesNotThrow(() -> acOutHandler.sendAcElementInfo(null, null, null, null, null));
+        assertDoesNotThrow(() -> acOutHandler.sendAcElementInfo(UUID.randomUUID(), null, null, null, null));
+        assertDoesNotThrow(
+                () -> acOutHandler.sendAcElementInfo(UUID.randomUUID(), UUID.randomUUID(), null, null, null));
+
+        var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
+        when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
+                .thenReturn(automationComposition);
+        assertDoesNotThrow(() -> acOutHandler.sendAcElementInfo(automationComposition.getInstanceId(),
+                UUID.randomUUID(), null, null, null));
+    }
+
+    @Test
+    void sendAcElementInfoTest() {
+        var publisher = mock(ParticipantMessagePublisher.class);
+        var cacheProvider = mock(CacheProvider.class);
+        var acOutHandler = new AutomationCompositionOutHandler(publisher, cacheProvider);
+
+        var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
+        when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
+                .thenReturn(automationComposition);
+        var elementId = automationComposition.getElements().values().iterator().next().getId();
+        acOutHandler.sendAcElementInfo(automationComposition.getInstanceId(),
+                elementId, "", "", Map.of());
+        verify(publisher).sendParticipantStatus(any(ParticipantStatus.class));
+    }
+}
diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProviderTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProviderTest.java
new file mode 100644
index 0000000..bbce423
--- /dev/null
+++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProviderTest.java
@@ -0,0 +1,128 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * 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.acm.participant.intermediary.handler;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.junit.jupiter.api.Test;
+import org.onap.policy.clamp.acm.participant.intermediary.main.parameters.CommonTestData;
+import org.onap.policy.clamp.common.acm.exception.AutomationCompositionException;
+import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition;
+import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
+
+class CacheProviderTest {
+
+    @Test
+    void testgetSupportedAcElementTypes() {
+        var parameter = CommonTestData.getParticipantParameters();
+        var cacheProvider = new CacheProvider(parameter);
+        assertEquals(parameter.getIntermediaryParameters().getParticipantId(), cacheProvider.getParticipantId());
+        assertEquals(parameter.getIntermediaryParameters().getParticipantSupportedElementTypes().get(0),
+                cacheProvider.getSupportedAcElementTypes().get(0));
+    }
+
+    @Test
+    void testNotNull() {
+        var parameter = CommonTestData.getParticipantParameters();
+        var cacheProvider = new CacheProvider(parameter);
+        var instanceId = UUID.randomUUID();
+        assertThatThrownBy(() -> cacheProvider.initializeAutomationComposition(null, null, null))
+                .isInstanceOf(NullPointerException.class);
+        assertThatThrownBy(() -> cacheProvider.initializeAutomationComposition(instanceId, null, null))
+                .isInstanceOf(NullPointerException.class);
+        assertThatThrownBy(() -> cacheProvider.initializeAutomationComposition(instanceId, instanceId, null))
+                .isInstanceOf(NullPointerException.class);
+
+        assertThatThrownBy(() -> cacheProvider.addElementDefinition(null, null))
+                .isInstanceOf(NullPointerException.class);
+        assertThatThrownBy(() -> cacheProvider.addElementDefinition(instanceId, null))
+                .isInstanceOf(NullPointerException.class);
+
+        assertThatThrownBy(() -> cacheProvider.getAutomationComposition(null)).isInstanceOf(NullPointerException.class);
+
+        assertThatThrownBy(() -> cacheProvider.getCommonProperties(null, null))
+                .isInstanceOf(NullPointerException.class);
+        assertThatThrownBy(() -> cacheProvider.getCommonProperties(instanceId, null))
+                .isInstanceOf(NullPointerException.class);
+
+        assertThatThrownBy(() -> cacheProvider.removeAutomationComposition(null))
+                .isInstanceOf(NullPointerException.class);
+
+        assertThatThrownBy(() -> cacheProvider.removeElementDefinition(null)).isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    void testinitCommonProperties() throws AutomationCompositionException {
+        var parameter = CommonTestData.getParticipantParameters();
+        var cacheProvider = new CacheProvider(parameter);
+        var participantDeploy = new ParticipantDeploy();
+        participantDeploy.setParticipantId(cacheProvider.getParticipantId());
+
+        var compositionId = UUID.randomUUID();
+
+        List<AutomationCompositionElementDefinition> definitions = new ArrayList<>();
+        var automationComposition =
+                CommonTestData.getTestAutomationCompositions().getAutomationCompositionList().get(0);
+        automationComposition.setInstanceId(UUID.randomUUID());
+        automationComposition.setCompositionId(compositionId);
+        for (var element : automationComposition.getElements().values()) {
+            var acElementDefinition = new AutomationCompositionElementDefinition();
+            acElementDefinition.setAcElementDefinitionId(element.getDefinition());
+            var nodeTemplate = new ToscaNodeTemplate();
+            nodeTemplate.setProperties(Map.of("key", "value"));
+            acElementDefinition.setAutomationCompositionElementToscaNodeTemplate(nodeTemplate);
+            definitions.add(acElementDefinition);
+
+            var acElement = new AcElementDeploy();
+            acElement.setId(element.getId());
+            acElement.setDefinition(element.getDefinition());
+            participantDeploy.getAcElementList().add(acElement);
+        }
+        cacheProvider.addElementDefinition(compositionId, definitions);
+
+        cacheProvider.initializeAutomationComposition(compositionId, automationComposition.getInstanceId(),
+                participantDeploy);
+
+        for (var element : automationComposition.getElements().values()) {
+            var commonProperties =
+                    cacheProvider.getCommonProperties(automationComposition.getInstanceId(), element.getId());
+            assertEquals("value", commonProperties.get("key"));
+        }
+
+        assertEquals(automationComposition.getInstanceId(),
+                cacheProvider.getAutomationComposition(automationComposition.getInstanceId()).getInstanceId());
+
+        assertThat(cacheProvider.getAutomationCompositions()).hasSize(1);
+        cacheProvider.removeAutomationComposition(automationComposition.getInstanceId());
+        assertThat(cacheProvider.getAutomationCompositions()).isEmpty();
+
+        cacheProvider.removeElementDefinition(compositionId);
+        assertThat(cacheProvider.getAcElementsDefinitions()).isEmpty();
+    }
+}
diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/main/parameters/CommonTestData.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/main/parameters/CommonTestData.java
index e627da6..60812c2 100644
--- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/main/parameters/CommonTestData.java
+++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/main/parameters/CommonTestData.java
@@ -22,7 +22,6 @@
 
 import java.io.File;
 import java.time.Instant;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -39,6 +38,7 @@
 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions;
 import org.onap.policy.clamp.models.acm.concepts.DeployState;
+import org.onap.policy.clamp.models.acm.concepts.ParticipantSupportedElementType;
 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionStateChange;
 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantDeregisterAck;
 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
@@ -116,7 +116,10 @@
         map.put("description", DESCRIPTION);
         map.put("reportingTimeIntervalMs", TIME_INTERVAL);
         map.put("clampAutomationCompositionTopics", getTopicParametersMap(false));
-        map.put("participantSupportedElementTypes", new ArrayList<>());
+        var supportedElementType = new ParticipantSupportedElementType();
+        supportedElementType.setTypeName("org.onap.policy.clamp.acm.HttpAutomationCompositionElement");
+        supportedElementType.setTypeVersion("1.0.0");
+        map.put("participantSupportedElementTypes", List.of(supportedElementType));
 
         return map;
     }
@@ -237,7 +240,7 @@
      *
      * @throws CoderException if there is an error with .json file.
      */
-    public Map<UUID, AutomationComposition> getTestAutomationCompositionMap() {
+    public static Map<UUID, AutomationComposition> getTestAutomationCompositionMap() {
         var automationCompositions = getTestAutomationCompositions();
         var automationComposition = automationCompositions.getAutomationCompositionList().get(1);
         Map<UUID, AutomationComposition> automationCompositionMap = new LinkedHashMap<>();
@@ -252,7 +255,7 @@
      *
      * @throws CoderException if there is an error with .json file.
      */
-    public AutomationCompositions getTestAutomationCompositions() {
+    public static AutomationCompositions getTestAutomationCompositions() {
         try {
             var automationCompositions =
                     new StandardCoder().decode(new File("src/test/resources/providers/TestAutomationCompositions.json"),