From 6b3c8bd96a66160714f768b185290ed765e23ec7 Mon Sep 17 00:00:00 2001
From: FrancescoFioraEst <francesco.fiora@est.tech>
Date: Fri, 3 Sep 2021 17:22:30 +0100
Subject: Verify participant Simulator and messages
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Add missing ControlLoopElementHandler in participant Simulator
and fix some message issues.

Issue-ID: POLICY-3628
Change-Id: I9f058c19aa18e070bac6ccaf98fdf7600d66d71e
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
---
 .../api/ParticipantIntermediaryApi.java            |  10 --
 .../api/impl/ParticipantIntermediaryApiImpl.java   |  35 +++----
 .../intermediary/handler/ControlLoopHandler.java   | 102 ++++++++++-----------
 .../handler/IntermediaryActivator.java             |  12 +--
 .../intermediary/handler/ParticipantHandler.java   |  24 +++--
 5 files changed, 84 insertions(+), 99 deletions(-)

(limited to 'participant/participant-intermediary/src/main/java/org')

diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/api/ParticipantIntermediaryApi.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/api/ParticipantIntermediaryApi.java
index 3859e0c39..891d67e2d 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/api/ParticipantIntermediaryApi.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/api/ParticipantIntermediaryApi.java
@@ -47,16 +47,6 @@ public interface ParticipantIntermediaryApi {
      */
     void registerControlLoopElementListener(ControlLoopElementListener controlLoopElementListener);
 
-    /**
-     * Send participant register message to controlloop runtime.
-     */
-    void sendParticipantRegister();
-
-    /**
-     * Send participant deregister message to controlloop runtime.
-     */
-    void sendParticipantDeregister();
-
     /**
      * Get participants loops from the intermediary API.
      *
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/api/impl/ParticipantIntermediaryApiImpl.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/api/impl/ParticipantIntermediaryApiImpl.java
index 1f79d7179..aa1febadd 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/api/impl/ParticipantIntermediaryApiImpl.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/api/impl/ParticipantIntermediaryApiImpl.java
@@ -37,6 +37,7 @@ import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant
 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantMessageType;
 import org.onap.policy.clamp.controlloop.participant.intermediary.api.ControlLoopElementListener;
 import org.onap.policy.clamp.controlloop.participant.intermediary.api.ParticipantIntermediaryApi;
+import org.onap.policy.clamp.controlloop.participant.intermediary.handler.ControlLoopHandler;
 import org.onap.policy.clamp.controlloop.participant.intermediary.handler.ParticipantHandler;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.springframework.stereotype.Component;
@@ -48,30 +49,26 @@ import org.springframework.stereotype.Component;
 public class ParticipantIntermediaryApiImpl implements ParticipantIntermediaryApi {
 
     // The handler for the participant intermediary
-    private ParticipantHandler participantHandler;
+    private final ParticipantHandler participantHandler;
+
+    // The handler for the controlLoop intermediary
+    private final ControlLoopHandler controlLoopHandler;
 
     /**
      * Constructor.
      *
      * @param participantHandler ParticipantHandler
+     * @param controlLoopHandler ControlLoopHandler
      */
-    public ParticipantIntermediaryApiImpl(ParticipantHandler participantHandler) {
+    public ParticipantIntermediaryApiImpl(ParticipantHandler participantHandler,
+            ControlLoopHandler controlLoopHandler) {
         this.participantHandler = participantHandler;
+        this.controlLoopHandler = controlLoopHandler;
     }
 
     @Override
     public void registerControlLoopElementListener(ControlLoopElementListener controlLoopElementListener) {
-        participantHandler.getControlLoopHandler().registerControlLoopElementListener(controlLoopElementListener);
-    }
-
-    @Override
-    public void sendParticipantRegister() {
-        participantHandler.sendParticipantRegister();
-    }
-
-    @Override
-    public void sendParticipantDeregister() {
-        participantHandler.sendParticipantDeregister();
+        controlLoopHandler.registerControlLoopElementListener(controlLoopElementListener);
     }
 
     @Override
@@ -91,13 +88,12 @@ public class ParticipantIntermediaryApiImpl implements ParticipantIntermediaryAp
 
     @Override
     public ControlLoops getControlLoops(String name, String version) {
-        return participantHandler.getControlLoopHandler().getControlLoops();
+        return controlLoopHandler.getControlLoops();
     }
 
     @Override
     public Map<UUID, ControlLoopElement> getControlLoopElements(String name, String version) {
-        List<ControlLoop> controlLoops =
-                participantHandler.getControlLoopHandler().getControlLoops().getControlLoopList();
+        List<ControlLoop> controlLoops = controlLoopHandler.getControlLoops().getControlLoopList();
 
         for (ControlLoop controlLoop : controlLoops) {
             if (name.equals(controlLoop.getDefinition().getName())) {
@@ -109,8 +105,7 @@ public class ParticipantIntermediaryApiImpl implements ParticipantIntermediaryAp
 
     @Override
     public ControlLoopElement getControlLoopElement(UUID id) {
-        List<ControlLoop> controlLoops =
-                participantHandler.getControlLoopHandler().getControlLoops().getControlLoopList();
+        List<ControlLoop> controlLoops = controlLoopHandler.getControlLoops().getControlLoopList();
 
         for (ControlLoop controlLoop : controlLoops) {
             ControlLoopElement clElement = controlLoop.getElements().get(id);
@@ -125,12 +120,12 @@ public class ParticipantIntermediaryApiImpl implements ParticipantIntermediaryAp
     public ControlLoopElement updateControlLoopElementState(ToscaConceptIdentifier controlLoopId,
             UUID id, ControlLoopOrderedState currentState,
             ControlLoopState newState, ParticipantMessageType messageType) {
-        return participantHandler.getControlLoopHandler().updateControlLoopElementState(controlLoopId,
+        return controlLoopHandler.updateControlLoopElementState(controlLoopId,
             id, currentState, newState);
     }
 
     @Override
     public void updateControlLoopElementStatistics(UUID id, ClElementStatistics elementStatistics) {
-        participantHandler.getControlLoopHandler().updateControlLoopElementStatistics(id, elementStatistics);
+        controlLoopHandler.updateControlLoopElementStatistics(id, elementStatistics);
     }
 }
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ControlLoopHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ControlLoopHandler.java
index 6e1b31cfe..8bdf91824 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ControlLoopHandler.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ControlLoopHandler.java
@@ -28,7 +28,6 @@ import java.util.Map;
 import java.util.UUID;
 import java.util.stream.Collectors;
 import lombok.Getter;
-import org.apache.commons.collections4.CollectionUtils;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatistics;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
@@ -45,7 +44,6 @@ import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.Parti
 import org.onap.policy.clamp.controlloop.participant.intermediary.api.ControlLoopElementListener;
 import org.onap.policy.clamp.controlloop.participant.intermediary.comm.ParticipantMessagePublisher;
 import org.onap.policy.clamp.controlloop.participant.intermediary.parameters.ParticipantParameters;
-import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.models.base.PfModelException;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
@@ -97,33 +95,37 @@ public class ControlLoopHandler {
      * @param newState the ordered state
      * @return controlLoopElement the updated controlloop element
      */
-    public ControlLoopElement updateControlLoopElementState(ToscaConceptIdentifier controlLoopId,
-            UUID id, ControlLoopOrderedState orderedState,
-            ControlLoopState newState) {
+    public ControlLoopElement updateControlLoopElementState(ToscaConceptIdentifier controlLoopId, UUID id,
+            ControlLoopOrderedState orderedState, ControlLoopState newState) {
 
         if (id == null) {
             LOGGER.warn("Cannot update Control loop element state, id is null");
+            return null;
         }
 
-        ControlLoopElement clElement = elementsOnThisParticipant.get(id);
         for (var controlLoop : controlLoopMap.values()) {
             var element = controlLoop.getElements().get(id);
             if (element != null) {
                 element.setState(newState);
             }
+            var checkOpt = controlLoop.getElements().values().stream()
+                    .filter(clElement -> !newState.equals(clElement.getState())).findAny();
+            if (checkOpt.isEmpty()) {
+                controlLoop.setState(newState);
+                controlLoop.setOrderedState(orderedState);
+            }
         }
 
+        var clElement = elementsOnThisParticipant.get(id);
         if (clElement != null) {
-            var controlLoopStateChangeAck =
-                    new ControlLoopAck(ParticipantMessageType.CONTROLLOOP_STATECHANGE_ACK);
+            var controlLoopStateChangeAck = new ControlLoopAck(ParticipantMessageType.CONTROLLOOP_STATECHANGE_ACK);
             controlLoopStateChangeAck.setParticipantId(participantId);
             controlLoopStateChangeAck.setParticipantType(participantType);
             controlLoopStateChangeAck.setControlLoopId(controlLoopId);
             clElement.setOrderedState(orderedState);
             clElement.setState(newState);
-            controlLoopStateChangeAck.getControlLoopResultMap().put(clElement.getId(),
-                new  ControlLoopElementAck(newState, true,
-                    "Control loop element {} state changed to {}\", id, newState)"));
+            controlLoopStateChangeAck.getControlLoopResultMap().put(clElement.getId(), new ControlLoopElementAck(
+                    newState, true, "Control loop element {} state changed to {}\", id, newState)"));
             LOGGER.debug("Control loop element {} state changed to {}", id, newState);
             controlLoopStateChangeAck.setMessage("ControlLoopElement state changed to {} " + newState);
             controlLoopStateChangeAck.setResult(true);
@@ -140,7 +142,7 @@ public class ControlLoopHandler {
      * @param elementStatistics control loop element Statistics
      */
     public void updateControlLoopElementStatistics(UUID id, ClElementStatistics elementStatistics) {
-        ControlLoopElement clElement = elementsOnThisParticipant.get(id);
+        var clElement = elementsOnThisParticipant.get(id);
         if (clElement != null) {
             elementStatistics.setParticipantId(participantId);
             elementStatistics.setId(id);
@@ -165,7 +167,7 @@ public class ControlLoopHandler {
             controlLoopAck.setParticipantId(participantId);
             controlLoopAck.setParticipantType(participantType);
             controlLoopAck.setMessage("Control loop " + stateChangeMsg.getControlLoopId()
-                + " does not use this participant " + participantId);
+                    + " does not use this participant " + participantId);
             controlLoopAck.setResult(false);
             controlLoopAck.setResponseTo(stateChangeMsg.getMessageId());
             controlLoopAck.setControlLoopId(stateChangeMsg.getControlLoopId());
@@ -206,7 +208,7 @@ public class ControlLoopHandler {
      * @param updateMsg the update message
      */
     public void handleControlLoopUpdate(ControlLoopUpdate updateMsg,
-                List<ControlLoopElementDefinition> clElementDefinitions) {
+            List<ControlLoopElementDefinition> clElementDefinitions) {
 
         if (!updateMsg.appliesTo(participantType, participantId)) {
             return;
@@ -222,7 +224,7 @@ public class ControlLoopHandler {
             controlLoopUpdateAck.setParticipantType(participantType);
 
             controlLoopUpdateAck.setMessage("Control loop " + updateMsg.getControlLoopId()
-                + " already defined on participant " + participantId);
+                    + " already defined on participant " + participantId);
             controlLoopUpdateAck.setResult(false);
             controlLoopUpdateAck.setResponseTo(updateMsg.getMessageId());
             controlLoopUpdateAck.setControlLoopId(updateMsg.getControlLoopId());
@@ -235,22 +237,22 @@ public class ControlLoopHandler {
             return;
         }
 
-        List<ControlLoopElement> clElements = storeElementsOnThisParticipant(updateMsg.getParticipantUpdatesList());
+        var clElements = storeElementsOnThisParticipant(updateMsg.getParticipantUpdatesList());
 
         try {
-            for (ControlLoopElement element : clElements) {
-                ToscaNodeTemplate clElementNodeTemplate = getClElementNodeTemplate(
-                        clElementDefinitions, element.getDefinition());
-                for (ControlLoopElementListener clElementListener : listeners) {
-                    clElementListener.controlLoopElementUpdate(updateMsg.getControlLoopId(),
-                        element, clElementNodeTemplate);
+            for (var element : clElements) {
+                var clElementNodeTemplate =
+                        getClElementNodeTemplate(clElementDefinitions, element.getDefinition());
+                for (var clElementListener : listeners) {
+                    clElementListener.controlLoopElementUpdate(updateMsg.getControlLoopId(), element,
+                            clElementNodeTemplate);
                 }
             }
         } catch (PfModelException e) {
             LOGGER.debug("Control loop element update failed {}", updateMsg.getControlLoopId());
         }
 
-        Map<UUID, ControlLoopElement> clElementMap = prepareClElementMap(clElements);
+        var clElementMap = prepareClElementMap(clElements);
         controlLoop = new ControlLoop();
         controlLoop.setDefinition(updateMsg.getControlLoopId());
         controlLoop.setElements(clElementMap);
@@ -258,8 +260,8 @@ public class ControlLoopHandler {
     }
 
     private ToscaNodeTemplate getClElementNodeTemplate(List<ControlLoopElementDefinition> clElementDefinitions,
-                ToscaConceptIdentifier clElementDefId) {
-        for (ControlLoopElementDefinition clElementDefinition : clElementDefinitions) {
+            ToscaConceptIdentifier clElementDefId) {
+        for (var clElementDefinition : clElementDefinitions) {
             if (clElementDefinition.getClElementDefinitionId().equals(clElementDefId)) {
                 return clElementDefinition.getControlLoopElementToscaNodeTemplate();
             }
@@ -268,11 +270,9 @@ public class ControlLoopHandler {
     }
 
     private List<ControlLoopElement> storeElementsOnThisParticipant(List<ParticipantUpdates> participantUpdates) {
-        var clElementMap =
-                participantUpdates.stream()
+        var clElementMap = participantUpdates.stream()
                 .flatMap(participantUpdate -> participantUpdate.getControlLoopElementList().stream())
-                .filter(element -> participantType.equals(element.getParticipantType()))
-                .collect(Collectors.toList());
+                .filter(element -> participantType.equals(element.getParticipantType())).collect(Collectors.toList());
 
         for (var element : clElementMap) {
             elementsOnThisParticipant.put(element.getId(), element);
@@ -282,7 +282,7 @@ public class ControlLoopHandler {
 
     private Map<UUID, ControlLoopElement> prepareClElementMap(List<ControlLoopElement> clElements) {
         Map<UUID, ControlLoopElement> clElementMap = new LinkedHashMap<>();
-        for (ControlLoopElement element : clElements) {
+        for (var element : clElements) {
             clElementMap.put(element.getId(), element);
         }
         return clElementMap;
@@ -295,19 +295,9 @@ public class ControlLoopHandler {
      * @param orderedState orderedState
      */
     private void handleUninitialisedState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState) {
-        handleStateChange(controlLoop, orderedState, ControlLoopState.UNINITIALISED);
-        controlLoopMap.remove(controlLoop.getKey().asIdentifier());
-
-        for (ControlLoopElementListener clElementListener : listeners) {
-            try {
-                for (ControlLoopElement element : controlLoop.getElements().values()) {
-                    clElementListener.controlLoopElementStateChange(controlLoop.getDefinition(),
-                        element.getId(), element.getState(), orderedState);
-                }
-            } catch (PfModelException e) {
-                LOGGER.debug("Control loop element update failed {}", controlLoop.getDefinition());
-            }
-        }
+        handleStateChange(controlLoop, orderedState);
+        controlLoopMap.remove(controlLoop.getDefinition());
+        controlLoop.getElements().values().forEach(element -> elementsOnThisParticipant.remove(element.getId()));
     }
 
     /**
@@ -317,7 +307,7 @@ public class ControlLoopHandler {
      * @param orderedState orderedState
      */
     private void handlePassiveState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState) {
-        handleStateChange(controlLoop, orderedState, ControlLoopState.PASSIVE);
+        handleStateChange(controlLoop, orderedState);
     }
 
     /**
@@ -327,7 +317,7 @@ public class ControlLoopHandler {
      * @param orderedState orderedState
      */
     private void handleRunningState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState) {
-        handleStateChange(controlLoop, orderedState, ControlLoopState.RUNNING);
+        handleStateChange(controlLoop, orderedState);
     }
 
     /**
@@ -335,30 +325,30 @@ public class ControlLoopHandler {
      *
      * @param controlLoop participant status in memory
      * @param orderedState orderedState the new ordered state the participant should have
-     * @param newState new state of the control loop elements
      */
-    private void handleStateChange(ControlLoop controlLoop, final ControlLoopOrderedState orderedState,
-            ControlLoopState newState) {
+    private void handleStateChange(ControlLoop controlLoop, final ControlLoopOrderedState orderedState) {
 
         if (orderedState.equals(controlLoop.getOrderedState())) {
             var controlLoopAck = new ControlLoopAck(ParticipantMessageType.CONTROL_LOOP_STATE_CHANGE);
             controlLoopAck.setParticipantId(participantId);
             controlLoopAck.setParticipantType(participantType);
-            controlLoopAck.setMessage("Control loop is already in state" + orderedState);
+            controlLoopAck.setMessage("Control loop is already in state " + orderedState);
             controlLoopAck.setResult(false);
             controlLoopAck.setControlLoopId(controlLoop.getDefinition());
             publisher.sendControlLoopAck(controlLoopAck);
             return;
         }
 
-        if (!CollectionUtils.isEmpty(controlLoop.getElements().values())) {
-            controlLoop.getElements().values().forEach(element -> {
-                element.setState(newState);
-                element.setOrderedState(orderedState);
-            });
+        for (var clElementListener : listeners) {
+            try {
+                for (var element : controlLoop.getElements().values()) {
+                    clElementListener.controlLoopElementStateChange(controlLoop.getDefinition(), element.getId(),
+                            element.getState(), orderedState);
+                }
+            } catch (PfModelException e) {
+                LOGGER.debug("Control loop element update failed {}", controlLoop.getDefinition());
+            }
         }
-
-        controlLoop.setOrderedState(orderedState);
     }
 
     /**
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/IntermediaryActivator.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/IntermediaryActivator.java
index 5458f7c34..1d445324b 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/IntermediaryActivator.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/IntermediaryActivator.java
@@ -24,7 +24,6 @@ package org.onap.policy.clamp.controlloop.participant.intermediary.handler;
 import java.io.Closeable;
 import java.io.IOException;
 import java.util.List;
-import org.onap.policy.clamp.controlloop.participant.intermediary.api.ParticipantIntermediaryApi;
 import org.onap.policy.clamp.controlloop.participant.intermediary.parameters.ParticipantParameters;
 import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
 import org.onap.policy.common.endpoints.event.comm.TopicSink;
@@ -48,7 +47,7 @@ public class IntermediaryActivator extends ServiceManagerContainer implements Cl
     private List<TopicSink> topicSinks;
     private List<TopicSource> topicSources;
 
-    ParticipantIntermediaryApi participantIntermediaryApi;
+    private ParticipantHandler participantHandler;
 
     private final MessageTypeDispatcher msgDispatcher;
 
@@ -56,13 +55,14 @@ public class IntermediaryActivator extends ServiceManagerContainer implements Cl
      * Instantiate the activator for participant.
      *
      * @param parameters the ParticipantParameters
+     * @param participantHandler the ParticipantHandler
      * @param publishers list of Publishers
      * @param listeners list of Listeners
      */
     public <T> IntermediaryActivator(final ParticipantParameters parameters,
-            ParticipantIntermediaryApi participantIntermediaryApi, List<Publisher> publishers,
+            ParticipantHandler participantHandler, List<Publisher> publishers,
             List<Listener<T>> listeners) {
-        this.participantIntermediaryApi = participantIntermediaryApi;
+        this.participantHandler = participantHandler;
 
         topicSinks = TopicEndpointManager.getManager()
                 .addTopicSinks(parameters.getIntermediaryParameters().getClampControlLoopTopics().getTopicSinks());
@@ -118,11 +118,11 @@ public class IntermediaryActivator extends ServiceManagerContainer implements Cl
     }
 
     private void sendParticipantRegister() {
-        participantIntermediaryApi.sendParticipantRegister();
+        participantHandler.sendParticipantRegister();
     }
 
     private void sendParticipantDeregister() {
-        participantIntermediaryApi.sendParticipantDeregister();
+        participantHandler.sendParticipantDeregister();
     }
 
     /**
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ParticipantHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ParticipantHandler.java
index 19641b0d5..69f8febb8 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ParticipantHandler.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ParticipantHandler.java
@@ -28,6 +28,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.UUID;
+import java.util.stream.Collectors;
 import lombok.Getter;
 import lombok.Setter;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatisticsList;
@@ -66,13 +67,16 @@ import org.springframework.stereotype.Component;
 /**
  * This class is responsible for managing the state of a participant.
  */
-@Getter
 @Component
 public class ParticipantHandler {
     private static final Logger LOGGER = LoggerFactory.getLogger(ParticipantHandler.class);
 
+    @Getter
     private final ToscaConceptIdentifier participantType;
+
+    @Getter
     private final ToscaConceptIdentifier participantId;
+
     private final ControlLoopHandler controlLoopHandler;
     private final ParticipantStatistics participantStatistics;
     private final ParticipantMessagePublisher publisher;
@@ -110,11 +114,6 @@ public class ParticipantHandler {
      * @param participantStatusReqMsg participant participantStatusReq message
      */
     public void handleParticipantStatusReq(final ParticipantStatusReq participantStatusReqMsg) {
-        var controlLoops = controlLoopHandler.getControlLoops();
-        for (ControlLoopElementListener clElementListener : controlLoopHandler.getListeners()) {
-            updateClElementStatistics(controlLoops, clElementListener);
-        }
-
         var participantStatus = makeHeartbeat(true);
         publisher.sendParticipantStatus(participantStatus);
     }
@@ -331,6 +330,12 @@ public class ParticipantHandler {
      * Method to send heartbeat to controlloop runtime.
      */
     public ParticipantStatus makeHeartbeat(boolean responseToParticipantStatusReq) {
+        if (!responseToParticipantStatusReq) {
+            var controlLoops = controlLoopHandler.getControlLoops();
+            for (var clElementListener : controlLoopHandler.getListeners()) {
+                updateClElementStatistics(controlLoops, clElementListener);
+            }
+        }
         this.participantStatistics.setState(state);
         this.participantStatistics.setHealthStatus(healthStatus);
         this.participantStatistics.setTimeStamp(Instant.now());
@@ -363,10 +368,15 @@ public class ParticipantHandler {
             clStatitistics.setControlLoopId(entry.getKey());
             ClElementStatisticsList clElementStatisticsList = new ClElementStatisticsList();
             clElementStatisticsList
-                    .setClElementStatistics(entry.getValue().getControlLoopElementStatisticsList(entry.getValue()));
+                    .setClElementStatistics(entry.getValue().getElements().values()
+                            .stream()
+                            .map(ControlLoopElement::getClElementStatistics)
+                            .filter(Objects::nonNull)
+                            .collect(Collectors.toList()));
             clStatitistics.setClElementStatisticsList(clElementStatisticsList);
             clInfo.setControlLoopStatistics(clStatitistics);
             clInfo.setState(entry.getValue().getState());
+            controlLoopInfoList.add(clInfo);
         }
         return controlLoopInfoList;
     }
-- 
cgit