Merge "Add distribution of policies to Policy Participant"
diff --git a/participant/participant-impl/participant-impl-dcae/src/main/resources/config/application.yaml b/participant/participant-impl/participant-impl-dcae/src/main/resources/config/application.yaml
index 44ba5b3..115170e 100644
--- a/participant/participant-impl/participant-impl-dcae/src/main/resources/config/application.yaml
+++ b/participant/participant-impl/participant-impl-dcae/src/main/resources/config/application.yaml
@@ -28,7 +28,7 @@
     aaf: false
   intermediaryParameters:
     name: Participant parameters
-    reportingTimeInterval: 120000
+    reportingTimeIntervalMs: 120000
     description: Participant Description
     participantId:
       name: DCAEParticipant0
diff --git a/participant/participant-impl/participant-impl-dcae/src/test/java/org/onap/policy/clamp/controlloop/participant/dcae/main/parameters/CommonTestData.java b/participant/participant-impl/participant-impl-dcae/src/test/java/org/onap/policy/clamp/controlloop/participant/dcae/main/parameters/CommonTestData.java
index 4b6dcd6..a28a6ec 100644
--- a/participant/participant-impl/participant-impl-dcae/src/test/java/org/onap/policy/clamp/controlloop/participant/dcae/main/parameters/CommonTestData.java
+++ b/participant/participant-impl/participant-impl-dcae/src/test/java/org/onap/policy/clamp/controlloop/participant/dcae/main/parameters/CommonTestData.java
@@ -172,7 +172,7 @@
         final Map<String, Object> map = new TreeMap<>();
         if (!isEmpty) {
             map.put("name", "Participant parameters");
-            map.put("reportingTimeInterval", TIME_INTERVAL);
+            map.put("reportingTimeIntervalMs", TIME_INTERVAL);
             map.put("description", DESCRIPTION);
             map.put("participantId", getParticipantId());
             map.put("participantType", getParticipantId());
diff --git a/participant/participant-impl/participant-impl-kubernetes/src/main/resources/config/application.yaml b/participant/participant-impl/participant-impl-kubernetes/src/main/resources/config/application.yaml
index 9d35237..68a1afd 100644
--- a/participant/participant-impl/participant-impl-kubernetes/src/main/resources/config/application.yaml
+++ b/participant/participant-impl/participant-impl-kubernetes/src/main/resources/config/application.yaml
@@ -10,7 +10,7 @@
   localChartDirectory: /var/helm-manager/local-charts
   infoFileName: CHART_INFO.json
   intermediaryParameters:
-    reportingTimeInterval: 120000
+    reportingTimeIntervalMs: 120000
     description: Participant Description
     participantId:
       name: K8sParticipant0
diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/parameters/CommonTestData.java b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/parameters/CommonTestData.java
index d8d477d..9255ee6 100644
--- a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/parameters/CommonTestData.java
+++ b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/parameters/CommonTestData.java
@@ -99,7 +99,7 @@
         final Map<String, Object> map = new TreeMap<>();
         if (!isEmpty) {
             map.put("name", "Participant parameters");
-            map.put("reportingTimeInterval", TIME_INTERVAL);
+            map.put("reportingTimeIntervalMs", TIME_INTERVAL);
             map.put("description", DESCRIPTION);
             map.put("participantId", getParticipantId());
             map.put("participantType", getParticipantId());
diff --git a/participant/participant-impl/participant-impl-policy/src/main/resources/config/application.yaml b/participant/participant-impl/participant-impl-policy/src/main/resources/config/application.yaml
index d4c7d75..ef158ce 100644
--- a/participant/participant-impl/participant-impl-policy/src/main/resources/config/application.yaml
+++ b/participant/participant-impl/participant-impl-policy/src/main/resources/config/application.yaml
@@ -9,7 +9,7 @@
     https: true
     allowSelfSignedCerts: true
   intermediaryParameters:
-    reportingTimeInterval: 120000
+    reportingTimeIntervalMs: 120000
     description: Participant Description
     participantId:
       name: org.onap.PM_Policy
diff --git a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/endtoend/ParticipantMessagesTest.java b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/endtoend/ParticipantMessagesTest.java
index 4b4558b..093ac19 100644
--- a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/endtoend/ParticipantMessagesTest.java
+++ b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/endtoend/ParticipantMessagesTest.java
@@ -20,6 +20,8 @@
 
 package org.onap.policy.clamp.controlloop.participant.policy.endtoend;
 
+import static org.assertj.core.api.Assertions.assertThatCode;
+
 import java.time.Instant;
 import java.util.Collections;
 import java.util.UUID;
@@ -30,6 +32,8 @@
 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantDeregisterAck;
 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegister;
 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegisterAck;
+import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseDetails;
+import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatus;
 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdate;
 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdateAck;
 import org.onap.policy.clamp.controlloop.participant.intermediary.comm.ParticipantDeregisterAckListener;
@@ -139,6 +143,20 @@
         }
     }
 
+    @Test
+    void testParticipantStatusHeartbeat() throws Exception {
+        final ParticipantStatus heartbeat = new ParticipantStatus();
+        heartbeat.setMessage("ParticipantStatus message");
+        heartbeat.setResponse(new ParticipantResponseDetails());
+        heartbeat.setParticipantId(getParticipantId());
+        synchronized (lockit) {
+            ParticipantMessagePublisher publisher =
+                    new ParticipantMessagePublisher(Collections.singletonList(Mockito.mock(TopicSink.class)));
+            assertThatCode(() -> publisher.sendHeartbeat(heartbeat)).doesNotThrowAnyException();
+        }
+    }
+
+
     private ToscaConceptIdentifier getParticipantId() {
         return new ToscaConceptIdentifier("org.onap.PM_Policy", "1.0.0");
     }
diff --git a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/parameters/CommonTestData.java b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/parameters/CommonTestData.java
index 3886147..a34c9cd 100644
--- a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/parameters/CommonTestData.java
+++ b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/parameters/CommonTestData.java
@@ -99,7 +99,7 @@
         final Map<String, Object> map = new TreeMap<>();
         if (!isEmpty) {
             map.put("name", "Participant parameters");
-            map.put("reportingTimeInterval", TIME_INTERVAL);
+            map.put("reportingTimeIntervalMs", TIME_INTERVAL);
             map.put("description", DESCRIPTION);
             map.put("participantId", getParticipantId());
             map.put("participantType", getParticipantId());
diff --git a/participant/participant-impl/participant-impl-simulator/src/main/resources/config/application.yaml b/participant/participant-impl/participant-impl-simulator/src/main/resources/config/application.yaml
index 5a9cf14..917c50d 100644
--- a/participant/participant-impl/participant-impl-simulator/src/main/resources/config/application.yaml
+++ b/participant/participant-impl/participant-impl-simulator/src/main/resources/config/application.yaml
@@ -13,7 +13,7 @@
 
 participant:
   intermediaryParameters:
-    reportingTimeInterval: 120000
+    reportingTimeIntervalMs: 120000
     description: Participant Description
     participantId:
       name: org.onap.PM_CDS_Blueprint
diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/controlloop/participant/simulator/main/parameters/CommonTestData.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/controlloop/participant/simulator/main/parameters/CommonTestData.java
index e85b3eb..9c41c8b 100644
--- a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/controlloop/participant/simulator/main/parameters/CommonTestData.java
+++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/controlloop/participant/simulator/main/parameters/CommonTestData.java
@@ -79,7 +79,7 @@
         final Map<String, Object> map = new TreeMap<>();
         if (!isEmpty) {
             map.put("name", "Participant parameters");
-            map.put("reportingTimeInterval", TIME_INTERVAL);
+            map.put("reportingTimeIntervalMs", TIME_INTERVAL);
             map.put("description", DESCRIPTION);
             map.put("participantId", getParticipantId());
             map.put("participantType", getParticipantId());
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/MessageSender.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/MessageSender.java
index 1bfce13..1741d95 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/MessageSender.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/MessageSender.java
@@ -67,18 +67,13 @@
 
         // Kick off the timer
         timerPool = makeTimerPool();
-        timerPool.scheduleAtFixedRate(this, 0, interval, TimeUnit.SECONDS);
+        timerPool.scheduleAtFixedRate(this, 0, interval, TimeUnit.MILLISECONDS);
     }
 
     @Override
     public void run() {
         LOGGER.debug("Sent heartbeat to CLAMP");
-
-        var response = new ParticipantResponseDetails();
-
-        response.setResponseTo(null);
-        response.setResponseStatus(ParticipantResponseStatus.PERIODIC);
-        response.setResponseMessage("Periodic response from participant");
+        this.sendHeartbeat();
     }
 
     @Override
@@ -161,6 +156,13 @@
     }
 
     /**
+     * Dispatch a heartbeat for this participant.
+     */
+    public void sendHeartbeat() {
+        publisher.sendHeartbeat(participantHandler.makeHeartbeat());
+    }
+
+    /**
      * Update ControlLoopElement statistics. The control loop elements listening will be
      * notified to retrieve statistics from respective controlloop elements, and controlloopelements
      * data on the handler will be updated.
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantMessagePublisher.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantMessagePublisher.java
index 9e1b846..051f000 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantMessagePublisher.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantMessagePublisher.java
@@ -90,4 +90,14 @@
         topicSinkClient.send(participantUpdateAck);
         LOGGER.debug("Sent Participant Update Ack message to CLAMP - {}", participantUpdateAck);
     }
+
+    /**
+     * Method to send Participant heartbeat to clamp on demand.
+     *
+     * @param participantStatus the Participant Status
+     */
+    public void sendHeartbeat(final ParticipantStatus participantStatus) {
+        topicSinkClient.send(participantStatus);
+        LOGGER.debug("Sent Participant heartbeat to CLAMP - {}", participantStatus);
+    }
 }
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 a8913c1..c94d5ad 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
@@ -43,6 +43,7 @@
 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseDetails;
 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseStatus;
 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStateChange;
+import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatus;
 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdate;
 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdateAck;
 import org.onap.policy.clamp.controlloop.participant.intermediary.comm.MessageSender;
@@ -85,7 +86,8 @@
         this.participantType = parameters.getIntermediaryParameters().getParticipantType();
         this.participantId = parameters.getIntermediaryParameters().getParticipantId();
         this.sender =
-                new MessageSender(this, publisher, parameters.getIntermediaryParameters().getReportingTimeInterval());
+                new MessageSender(this, publisher,
+                        parameters.getIntermediaryParameters().getReportingTimeIntervalMs());
         this.controlLoopHandler = new ControlLoopHandler(parameters.getIntermediaryParameters(), sender);
         this.participantStatistics = new ParticipantStatistics();
     }
@@ -344,4 +346,17 @@
 
         sender.sendParticipantUpdateAck(participantUpdateAck);
     }
+
+    /**
+     * Method to send heartbeat to controlloop runtime.
+     */
+    public ParticipantStatus makeHeartbeat() {
+        ParticipantStatus heartbeat = new ParticipantStatus();
+        heartbeat.setParticipantId(participantId);
+        heartbeat.setParticipantStatistics(participantStatistics);
+        heartbeat.setParticipantType(participantType);
+        heartbeat.setHealthStatus(healthStatus);
+        heartbeat.setMessage("Participant heartbeat message sent from -> " + participantId.getName());
+        return heartbeat;
+    }
 }
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/parameters/ParticipantIntermediaryParameters.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/parameters/ParticipantIntermediaryParameters.java
index 5627abf..fdc451e 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/parameters/ParticipantIntermediaryParameters.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/parameters/ParticipantIntermediaryParameters.java
@@ -23,6 +23,7 @@
 import javax.validation.Valid;
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Positive;
 import lombok.Getter;
 import lombok.Setter;
 import org.onap.policy.common.endpoints.parameters.TopicParameterGroup;
@@ -50,7 +51,9 @@
     private ToscaConceptIdentifier participantType;
 
     // The time interval for periodic reporting of status to the CLAMP control loop server
-    private long reportingTimeInterval;
+    @Valid
+    @Positive
+    private long reportingTimeIntervalMs;
 
     @NotNull
     @ParameterGroupConstraint
diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/controlloop/participant/intermediary/main/parameters/CommonTestData.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/controlloop/participant/intermediary/main/parameters/CommonTestData.java
index 93ba158..9353cde 100644
--- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/controlloop/participant/intermediary/main/parameters/CommonTestData.java
+++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/controlloop/participant/intermediary/main/parameters/CommonTestData.java
@@ -68,7 +68,7 @@
         map.put("participantId", getParticipantId());
         map.put("description", DESCRIPTION);
         map.put("participantType", getParticipantId());
-        map.put("reportingTimeInterval", TIME_INTERVAL);
+        map.put("reportingTimeIntervalMs", TIME_INTERVAL);
         map.put("clampControlLoopTopics", getTopicParametersMap(false));
 
         return map;