Add participant controller in ACM 06/132906/3
authorsaul.gill <saul.gill@est.tech>
Tue, 10 Jan 2023 11:11:08 +0000 (11:11 +0000)
committersaul.gill <saul.gill@est.tech>
Thu, 12 Jan 2023 13:44:44 +0000 (13:44 +0000)
Added participant controller
Altered openapi spec
Added participantId

Issue-ID: POLICY-4496
Change-Id: I0c0ea93dacb6927e6f16bd4638d03db6266be3bd
Signed-off-by: saul.gill <saul.gill@est.tech>
18 files changed:
models/src/main/java/org/onap/policy/clamp/models/acm/concepts/Participant.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaParticipant.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProvider.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/ParticipantRepository.java
models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaParticipantTest.java
models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProviderTest.java
models/src/test/resources/providers/TestParticipant.json
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/ParticipantController.java [new file with mode: 0644]
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/participants/AcmParticipantProvider.java [new file with mode: 0644]
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java
runtime-acm/src/main/resources/openapi/openapi.yaml
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/participant/ParticipantControllerTest.java [new file with mode: 0644]
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandlerTest.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java
runtime-acm/src/test/resources/providers/TestParticipant.json [new file with mode: 0644]
runtime-acm/src/test/resources/providers/TestParticipant2.json [new file with mode: 0644]

index 6a523fa..c6da3c3 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.onap.policy.clamp.models.acm.concepts;
 
+import java.util.UUID;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.NoArgsConstructor;
@@ -35,6 +36,9 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaEntity;
 @Data
 @EqualsAndHashCode(callSuper = true)
 public class Participant extends ToscaEntity implements Comparable<Participant> {
+
+    @NonNull
+    private UUID participantId;
     @NonNull
     private ToscaConceptIdentifier definition = new ToscaConceptIdentifier(PfConceptKey.getNullKey());
 
@@ -69,5 +73,6 @@ public class Participant extends ToscaEntity implements Comparable<Participant>
         this.definition = new ToscaConceptIdentifier(otherParticipant.definition);
         this.participantState = otherParticipant.participantState;
         this.participantType = otherParticipant.participantType;
+        this.participantId = otherParticipant.participantId;
     }
 }
index aec2d32..398daa2 100644 (file)
@@ -22,6 +22,7 @@ package org.onap.policy.clamp.models.acm.persistence.concepts;
 
 import java.io.Serializable;
 import java.util.List;
+import java.util.UUID;
 import javax.persistence.AttributeOverride;
 import javax.persistence.Column;
 import javax.persistence.EmbeddedId;
@@ -56,6 +57,10 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 public class JpaParticipant extends PfConcept implements PfAuthorative<Participant>, Serializable {
     private static final long serialVersionUID = -4697758484642403483L;
 
+    @Column
+    @NotNull
+    private String participantId;
+
     @EmbeddedId
     @VerifyKey
     @NotNull
@@ -94,21 +99,25 @@ public class JpaParticipant extends PfConcept implements PfAuthorative<Participa
      * @param key the key
      */
     public JpaParticipant(@NonNull final PfConceptKey key) {
-        this(key, new PfConceptKey(), ParticipantState.ON_LINE);
+        this(UUID.randomUUID().toString(), key, new PfConceptKey(), ParticipantState.ON_LINE);
     }
 
     /**
      * The Key Constructor creates a {@link JpaParticipant} object with all mandatory fields.
      *
+     * @param participantId the participant id
      * @param key the key
      * @param definition the TOSCA definition of the participant
      * @param participantState the state of the participant
      */
-    public JpaParticipant(@NonNull final PfConceptKey key, @NonNull final PfConceptKey definition,
-            @NonNull final ParticipantState participantState) {
+    public JpaParticipant(@NotNull String participantId,
+                          @NonNull final PfConceptKey key,
+                          @NonNull final PfConceptKey definition,
+                          @NonNull final ParticipantState participantState) {
         this.key = key;
         this.definition = definition;
         this.participantState = participantState;
+        this.participantId = participantId;
     }
 
     /**
@@ -123,6 +132,7 @@ public class JpaParticipant extends PfConcept implements PfAuthorative<Participa
         this.participantState = copyConcept.participantState;
         this.description = copyConcept.description;
         this.participantType = copyConcept.participantType;
+        this.participantId = copyConcept.participantId;
     }
 
     /**
@@ -144,6 +154,7 @@ public class JpaParticipant extends PfConcept implements PfAuthorative<Participa
         participant.setParticipantState(participantState);
         participant.setDescription(description);
         participant.setParticipantType(new ToscaConceptIdentifier(participantType));
+        participant.setParticipantId(UUID.fromString(participantId));
 
         return participant;
     }
@@ -158,6 +169,7 @@ public class JpaParticipant extends PfConcept implements PfAuthorative<Participa
         this.setParticipantState(participant.getParticipantState());
         this.setDescription(participant.getDescription());
         this.participantType = participant.getParticipantType().asConceptKey();
+        this.participantId = participant.getParticipantId().toString();
     }
 
     @Override
index 3f7e297..9176680 100644 (file)
@@ -22,12 +22,14 @@ package org.onap.policy.clamp.models.acm.persistence.provider;
 
 import java.util.List;
 import java.util.Optional;
+import java.util.UUID;
 import javax.ws.rs.core.Response.Status;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import org.onap.policy.clamp.models.acm.concepts.Participant;
 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaParticipant;
 import org.onap.policy.clamp.models.acm.persistence.repository.ParticipantRepository;
+import org.onap.policy.models.base.PfModelException;
 import org.onap.policy.models.base.PfModelRuntimeException;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.springframework.stereotype.Service;
@@ -66,6 +68,24 @@ public class ParticipantProvider {
         return ProviderUtils.asEntityList(participantRepository.findAll());
     }
 
+    /**
+     * Get participant.
+     *
+     * @param participantId the id of the participant to get
+     * @return the participant found
+     * @throws PfModelException on errors getting participant
+     */
+    @Transactional(readOnly = true)
+    public Participant getParticipantById(String participantId) {
+        var participant = participantRepository.findByParticipantId(participantId);
+        if (participant.isEmpty()) {
+            throw new PfModelRuntimeException(Status.NOT_FOUND,
+                "Participant Not Found with ID: " + participantId);
+        } else {
+            return participant.get().toAuthorative();
+        }
+    }
+
     /**
      * Get participant.
      *
@@ -84,8 +104,23 @@ public class ParticipantProvider {
      * @return the participant created
      */
     public Participant saveParticipant(@NonNull final Participant participant) {
+        participant.setParticipantId(UUID.randomUUID());
+        var result = participantRepository
+            .save(ProviderUtils.getJpaAndValidate(participant, JpaParticipant::new, "participant"));
+
+        // Return the saved participant
+        return result.toAuthorative();
+    }
+
+    /**
+     * Updates an existing participant.
+     *
+     * @param participant participant to update
+     * @return the participant updated
+     */
+    public Participant updateParticipant(@NonNull final Participant participant) {
         var result = participantRepository
-                .save(ProviderUtils.getJpaAndValidate(participant, JpaParticipant::new, "participant"));
+            .save(ProviderUtils.getJpaAndValidate(participant, JpaParticipant::new, "participant"));
 
         // Return the saved participant
         return result.toAuthorative();
@@ -102,7 +137,7 @@ public class ParticipantProvider {
 
         if (jpaDeleteParticipantOpt.isEmpty()) {
             String errorMessage =
-                    "delete of participant \"" + participantId + "\" failed, participant does not exist";
+                "delete of participant \"" + participantId + "\" failed, participant does not exist";
             throw new PfModelRuntimeException(Status.BAD_REQUEST, errorMessage);
         }
         participantRepository.delete(jpaDeleteParticipantOpt.get());
index 2279a75..67ea188 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation.
+ *  Copyright (C) 2021-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.
@@ -20,6 +20,7 @@
 
 package org.onap.policy.clamp.models.acm.persistence.repository;
 
+import java.util.Optional;
 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaParticipant;
 import org.onap.policy.models.base.PfConceptKey;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -28,4 +29,5 @@ import org.springframework.stereotype.Repository;
 @Repository
 public interface ParticipantRepository extends JpaRepository<JpaParticipant, PfConceptKey>, FilterRepository {
 
+    Optional<JpaParticipant> findByParticipantId(String compositionId);
 }
index 9d1d7ff..0fbdaa2 100644 (file)
@@ -27,6 +27,7 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.util.UUID;
 import org.junit.jupiter.api.Test;
 import org.onap.policy.clamp.models.acm.concepts.Participant;
 import org.onap.policy.clamp.models.acm.concepts.ParticipantState;
@@ -47,52 +48,54 @@ class JpaParticipantTest {
 
         assertThatThrownBy(() -> new JpaParticipant((PfConceptKey) null)).hasMessageMatching(NULL_KEY_ERROR);
 
-        assertThatThrownBy(() -> new JpaParticipant(null, null, null)).hasMessageMatching(NULL_KEY_ERROR);
+        assertThatThrownBy(() -> new JpaParticipant(null, null, null, null)).hasMessageMatching(NULL_KEY_ERROR);
 
-        assertThatThrownBy(() -> new JpaParticipant(null, null, null))
+        assertThatThrownBy(() -> new JpaParticipant(null, null, null, null))
             .hasMessageMatching(NULL_KEY_ERROR);
 
-        assertThatThrownBy(() -> new JpaParticipant(null, null, ParticipantState.ON_LINE))
+        assertThatThrownBy(() -> new JpaParticipant(null, null, null, ParticipantState.ON_LINE))
             .hasMessageMatching(NULL_KEY_ERROR);
 
         assertThatThrownBy(
-            () -> new JpaParticipant(null, null, ParticipantState.ON_LINE))
+            () -> new JpaParticipant(null, null, null, ParticipantState.ON_LINE))
             .hasMessageMatching(NULL_KEY_ERROR);
 
-        assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), null))
+        assertThatThrownBy(() -> new JpaParticipant(null, null, new PfConceptKey(), null))
             .hasMessageMatching(NULL_KEY_ERROR);
 
-        assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), null))
+        assertThatThrownBy(() -> new JpaParticipant(null, null, new PfConceptKey(), null))
             .hasMessageMatching(NULL_KEY_ERROR);
 
-        assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), ParticipantState.ON_LINE))
+        assertThatThrownBy(() -> new JpaParticipant(null, null, new PfConceptKey(), ParticipantState.ON_LINE))
             .hasMessageMatching(NULL_KEY_ERROR);
 
-        assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), ParticipantState.ON_LINE))
+        assertThatThrownBy(() -> new JpaParticipant(null, null, new PfConceptKey(), ParticipantState.ON_LINE))
             .hasMessageMatching(NULL_KEY_ERROR);
 
-        assertThatThrownBy(() -> new JpaParticipant(new PfConceptKey(), null, null))
+        assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), null, null))
             .hasMessageMatching("definition is marked .*ull but is null");
 
-        assertThatThrownBy(() -> new JpaParticipant(new PfConceptKey(), null, null))
+        assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), null, null))
             .hasMessageMatching("definition is marked .*ull but is null");
 
-        assertThatThrownBy(() -> new JpaParticipant(new PfConceptKey(), null, ParticipantState.ON_LINE))
+        assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), null, ParticipantState.ON_LINE))
             .hasMessageMatching("definition is marked .*ull but is null");
 
-        assertThatThrownBy(() -> new JpaParticipant(new PfConceptKey(), null, ParticipantState.ON_LINE
-            )).hasMessageMatching("definition is marked .*ull but is null");
+        assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), null, ParticipantState.ON_LINE
+        )).hasMessageMatching("definition is marked .*ull but is null");
 
-        assertThatThrownBy(() -> new JpaParticipant(new PfConceptKey(), new PfConceptKey(), null))
+        assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), new PfConceptKey(), null))
             .hasMessageMatching("participantState is marked .*ull but is null");
 
         assertThatThrownBy(
-            () -> new JpaParticipant(new PfConceptKey(), new PfConceptKey(), null))
+            () -> new JpaParticipant(null, new PfConceptKey(), new PfConceptKey(), null))
             .hasMessageMatching("participantState is marked .*ull but is null");
 
         assertNotNull(new JpaParticipant());
         assertNotNull(new JpaParticipant((new PfConceptKey())));
-        assertNotNull(new JpaParticipant(new PfConceptKey(), new PfConceptKey(), ParticipantState.ON_LINE));
+        assertNotNull(new JpaParticipant(null, new PfConceptKey(), new PfConceptKey(), ParticipantState.ON_LINE));
+        assertNotNull(new JpaParticipant(UUID.randomUUID().toString(), new PfConceptKey(),
+            new PfConceptKey(), ParticipantState.ON_LINE));
     }
 
     @Test
@@ -100,6 +103,9 @@ class JpaParticipantTest {
         JpaParticipant testJpaParticipant = createJpaParticipantInstance();
 
         Participant participant = createParticipantInstance();
+
+        participant.setParticipantId(testJpaParticipant.toAuthorative().getParticipantId());
+
         assertEquals(participant, testJpaParticipant.toAuthorative());
 
         assertThatThrownBy(() -> testJpaParticipant.fromAuthorative(null))
@@ -110,6 +116,7 @@ class JpaParticipantTest {
         JpaParticipant testJpaParticipantFa = new JpaParticipant();
         testJpaParticipantFa.setKey(null);
         testJpaParticipantFa.fromAuthorative(participant);
+        testJpaParticipantFa.setParticipantId(testJpaParticipant.getParticipantId());
         assertEquals(testJpaParticipant, testJpaParticipantFa);
         testJpaParticipantFa.setKey(PfConceptKey.getNullKey());
         testJpaParticipantFa.fromAuthorative(participant);
@@ -119,9 +126,9 @@ class JpaParticipantTest {
         assertEquals(testJpaParticipant, testJpaParticipantFa);
 
         assertEquals("participant", testJpaParticipant.getKey().getName());
-        assertEquals("participant", new JpaParticipant(createParticipantInstance()).getKey().getName());
+        assertEquals("participant", new JpaParticipant(createJpaParticipantInstance()).getKey().getName());
         assertEquals("participant",
-            ((PfConceptKey) new JpaParticipant(createParticipantInstance()).getKeys().get(0)).getName());
+            ((PfConceptKey) new JpaParticipant(createJpaParticipantInstance()).getKeys().get(0)).getName());
 
         testJpaParticipant.clean();
         assertEquals("participant", testJpaParticipant.getKey().getName());
@@ -131,6 +138,7 @@ class JpaParticipantTest {
         assertEquals("A Message", testJpaParticipant.getDescription());
 
         JpaParticipant testJpaParticipant2 = new JpaParticipant(testJpaParticipant);
+        testJpaParticipant2.setParticipantId(testJpaParticipant.getParticipantId());
         assertEquals(testJpaParticipant, testJpaParticipant2);
     }
 
@@ -149,6 +157,7 @@ class JpaParticipantTest {
         JpaParticipant testJpaParticipant = createJpaParticipantInstance();
 
         JpaParticipant otherJpaParticipant = new JpaParticipant(testJpaParticipant);
+        otherJpaParticipant.setParticipantId(testJpaParticipant.getParticipantId());
         assertEquals(0, testJpaParticipant.compareTo(otherJpaParticipant));
         assertEquals(-1, testJpaParticipant.compareTo(null));
         assertEquals(0, testJpaParticipant.compareTo(testJpaParticipant));
@@ -169,6 +178,10 @@ class JpaParticipantTest {
         testJpaParticipant.setParticipantState(ParticipantState.ON_LINE);
         assertEquals(0, testJpaParticipant.compareTo(otherJpaParticipant));
         assertEquals(testJpaParticipant, new JpaParticipant(testJpaParticipant));
+
+        JpaParticipant newJpaParticipant = new JpaParticipant(testJpaParticipant);
+        newJpaParticipant.setParticipantId(testJpaParticipant.getParticipantId());
+        assertEquals(testJpaParticipant, newJpaParticipant);
     }
 
     @Test
@@ -197,6 +210,7 @@ class JpaParticipantTest {
         assertNotEquals(p1, p0);
 
         JpaParticipant p2 = new JpaParticipant();
+        p2.setParticipantId(p0.getParticipantId());
         assertEquals(p2, p0);
     }
 
@@ -204,6 +218,7 @@ class JpaParticipantTest {
         Participant testParticipant = createParticipantInstance();
         JpaParticipant testJpaParticipant = new JpaParticipant();
         testJpaParticipant.setKey(null);
+        testParticipant.setParticipantId(UUID.fromString(testJpaParticipant.getParticipantId()));
         testJpaParticipant.fromAuthorative(testParticipant);
         testJpaParticipant.setKey(PfConceptKey.getNullKey());
         testJpaParticipant.fromAuthorative(testParticipant);
index e115419..6e6637c 100644 (file)
@@ -64,7 +64,7 @@ class ParticipantProviderTest {
         var participantRepository = mock(ParticipantRepository.class);
         for (var participant : jpaParticipantList) {
             when(participantRepository.getById(new PfConceptKey(participant.getName(), participant.getVersion())))
-                    .thenReturn(participant);
+                .thenReturn(participant);
         }
         var participantProvider = new ParticipantProvider(participantRepository);
 
@@ -73,9 +73,29 @@ class ParticipantProviderTest {
         when(participantRepository.save(any())).thenReturn(jpaParticipantList.get(0));
 
         Participant savedParticipant = participantProvider.saveParticipant(inputParticipants.get(0));
+        savedParticipant.setParticipantId(inputParticipants.get(0).getParticipantId());
         assertEquals(savedParticipant, inputParticipants.get(0));
     }
 
+    @Test
+    void testParticipantUpdate() throws Exception {
+        var participantRepository = mock(ParticipantRepository.class);
+        for (var participant : jpaParticipantList) {
+            when(participantRepository.getById(new PfConceptKey(participant.getName(), participant.getVersion())))
+                .thenReturn(participant);
+        }
+        var participantProvider = new ParticipantProvider(participantRepository);
+
+        assertThatThrownBy(() -> participantProvider.updateParticipant(null))
+            .hasMessageMatching(LIST_IS_NULL);
+
+        when(participantRepository.save(any())).thenReturn(jpaParticipantList.get(0));
+
+        Participant updatedParticipant = participantProvider.updateParticipant(inputParticipants.get(0));
+        updatedParticipant.setParticipantId(inputParticipants.get(0).getParticipantId());
+        assertEquals(updatedParticipant, inputParticipants.get(0));
+    }
+
     @Test
     void testGetAutomationCompositions() throws Exception {
         var participantRepository = mock(ParticipantRepository.class);
@@ -88,7 +108,7 @@ class ParticipantProviderTest {
         String name = inputParticipants.get(0).getName();
         String version = inputParticipants.get(0).getVersion();
         when(participantRepository.getFiltered(any(), eq(name), eq(version)))
-                .thenReturn(List.of(jpaParticipantList.get(0)));
+            .thenReturn(List.of(jpaParticipantList.get(0)));
         assertEquals(1, participantProvider.getParticipants(name, version).size());
 
         assertThat(participantProvider.getParticipants("invalid_name", "1.0.1")).isEmpty();
@@ -97,6 +117,14 @@ class ParticipantProviderTest {
 
         when(participantRepository.findAll()).thenReturn(jpaParticipantList);
         assertThat(participantProvider.getParticipants()).hasSize(inputParticipants.size());
+
+        when(participantRepository.findByParticipantId(any())).thenReturn(
+            Optional.ofNullable(jpaParticipantList.get(0)));
+
+        var participant = participantProvider.getParticipantById(inputParticipants.get(0)
+            .getParticipantId().toString());
+
+        assertThat(participant).isEqualTo(inputParticipants.get(0));
     }
 
     @Test
@@ -105,12 +133,12 @@ class ParticipantProviderTest {
         var participantProvider = new ParticipantProvider(participantRepository);
 
         assertThatThrownBy(() -> participantProvider.deleteParticipant(INVALID_ID))
-                .hasMessageMatching(".*.failed, participant does not exist");
+            .hasMessageMatching(".*.failed, participant does not exist");
 
         when(participantRepository.findById(any())).thenReturn(Optional.of(jpaParticipantList.get(0)));
 
         Participant deletedParticipant =
-                participantProvider.deleteParticipant(inputParticipants.get(0).getDefinition());
+            participantProvider.deleteParticipant(inputParticipants.get(0).getDefinition());
         assertEquals(inputParticipants.get(0), deletedParticipant);
     }
 }
index 5d8a7ea..99284cb 100644 (file)
@@ -7,6 +7,7 @@
   },
   "participantState": "ON_LINE",
   "description": "A dummy PMSH participant1",
+  "participantId": "82fd8ef9-1d1e-4343-9b28-7f9564ee3de6",
   "participantType":{
     "name": "org.onap.domain.pmsh.PolicyAutomationCompositionDefinition",
     "version": "1.0.0"
diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/ParticipantController.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/ParticipantController.java
new file mode 100644 (file)
index 0000000..abcef7a
--- /dev/null
@@ -0,0 +1,67 @@
+/*-
+ * ============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.runtime.main.rest;
+
+import java.util.List;
+import java.util.UUID;
+import lombok.RequiredArgsConstructor;
+import org.onap.policy.clamp.acm.runtime.main.rest.gen.ParticipantMonitoringApi;
+import org.onap.policy.clamp.acm.runtime.main.web.AbstractRestController;
+import org.onap.policy.clamp.acm.runtime.participants.AcmParticipantProvider;
+import org.onap.policy.clamp.models.acm.concepts.ParticipantInformation;
+import org.springframework.context.annotation.Profile;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequiredArgsConstructor
+@Profile("default")
+public class ParticipantController extends AbstractRestController implements ParticipantMonitoringApi {
+
+    private final AcmParticipantProvider acmParticipantProvider;
+
+    @Override
+    public ResponseEntity<ParticipantInformation> getParticipant(UUID participantId, UUID requestId) {
+        ParticipantInformation participantInformation = acmParticipantProvider
+            .getParticipantById(participantId.toString());
+        return ResponseEntity.ok().body(participantInformation);
+    }
+
+    @Override
+    public ResponseEntity<Void> orderAllParticipantsReport(UUID requestId) {
+        acmParticipantProvider.sendAllParticipantStatusRequest();
+        return new ResponseEntity<>(HttpStatus.ACCEPTED);
+    }
+
+    @Override
+    public ResponseEntity<Void> orderParticipantReport(UUID participantId, UUID requestId) {
+        acmParticipantProvider.sendParticipantStatusRequest(participantId.toString());
+        return new ResponseEntity<>(HttpStatus.ACCEPTED);
+    }
+
+    @Override
+    public ResponseEntity<List<ParticipantInformation>> queryParticipants(String name, String version,
+                                                                          UUID requestId) {
+        List<ParticipantInformation> participantInformationList = acmParticipantProvider.getAllParticipants();
+        return ResponseEntity.ok().body(participantInformationList);
+    }
+}
diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/participants/AcmParticipantProvider.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/participants/AcmParticipantProvider.java
new file mode 100644 (file)
index 0000000..e1d0423
--- /dev/null
@@ -0,0 +1,102 @@
+/*-
+ * ============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.runtime.participants;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantStatusReqPublisher;
+import org.onap.policy.clamp.models.acm.concepts.Participant;
+import org.onap.policy.clamp.models.acm.concepts.ParticipantInformation;
+import org.onap.policy.clamp.models.acm.concepts.ParticipantState;
+import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@Transactional
+public class AcmParticipantProvider {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(AcmParticipantProvider.class);
+    private final ParticipantProvider participantProvider;
+    private final ParticipantStatusReqPublisher participantStatusReqPublisher;
+
+    public AcmParticipantProvider(ParticipantProvider participantProvider,
+                                  ParticipantStatusReqPublisher participantStatusReqPublisher) {
+        this.participantProvider = participantProvider;
+        this.participantStatusReqPublisher = participantStatusReqPublisher;
+    }
+
+    /**
+     * Get all participants.
+     *
+     * @return A list of available participants
+     */
+    public List<ParticipantInformation> getAllParticipants() {
+        List<Participant> participants = this.participantProvider.getParticipants();
+
+        List<ParticipantInformation> participantInformationList = new ArrayList<>();
+        participants.forEach(participant -> {
+            ParticipantInformation participantInformation = new ParticipantInformation();
+            participantInformation.setParticipant(participant);
+            participantInformationList.add(participantInformation);
+        });
+        return participantInformationList;
+    }
+
+    /**
+     * Get a participant.
+     *
+     * @param participantId The UUID of the participant to get
+     * @return The participant
+     */
+    public ParticipantInformation getParticipantById(String participantId) {
+        Participant participant = this.participantProvider.getParticipantById(participantId);
+        ParticipantInformation participantInformation = new ParticipantInformation();
+        participantInformation.setParticipant(participant);
+        return participantInformation;
+    }
+
+    /**
+     * Send a participant status request.
+     *
+     * @param participantId The UUID of the participant to send request to
+     */
+    public void sendParticipantStatusRequest(String participantId) {
+        Participant participant = this.participantProvider.getParticipantById(participantId);
+        ToscaConceptIdentifier id = participant.getKey().asIdentifier();
+
+        LOGGER.debug("Requesting Participant Status Now ParticipantStatusReq");
+        participantStatusReqPublisher.send(id);
+        participant.setParticipantState(ParticipantState.OFF_LINE);
+        participantProvider.updateParticipant(participant);
+    }
+
+    /**
+     * Send status request to all participants.
+     *
+     */
+    public void sendAllParticipantStatusRequest() {
+        this.participantStatusReqPublisher.send((ToscaConceptIdentifier) null);
+    }
+}
index c274474..761c380 100644 (file)
@@ -57,9 +57,9 @@ public class SupervisionHandler {
     private static final Logger LOGGER = LoggerFactory.getLogger(SupervisionHandler.class);
 
     private static final String AUTOMATION_COMPOSITION_CANNOT_TRANSITION_FROM_STATE =
-            "Automation composition can't transition from state ";
+        "Automation composition can't transition from state ";
     private static final String AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE =
-            "Automation composition is already in state ";
+        "Automation composition is already in state ";
     private static final String TO_STATE = " to state ";
     private static final String AND_TRANSITIONING_TO_STATE = " and transitioning to state ";
 
@@ -78,7 +78,7 @@ public class SupervisionHandler {
      */
     public void handleSendCommissionMessage(AutomationCompositionDefinition acmDefinition) {
         LOGGER.debug("Participant update message with serviveTemplate {} being sent to all participants",
-                acmDefinition.getCompositionId());
+            acmDefinition.getCompositionId());
         participantUpdatePublisher.sendComissioningBroadcast(acmDefinition);
     }
 
@@ -98,8 +98,8 @@ public class SupervisionHandler {
      */
     @MessageIntercept
     @Timed(
-            value = "listener.automation_composition_update_ack",
-            description = "AUTOMATION_COMPOSITION_UPDATE_ACK messages received")
+        value = "listener.automation_composition_update_ack",
+        description = "AUTOMATION_COMPOSITION_UPDATE_ACK messages received")
     public void handleAutomationCompositionUpdateAckMessage(AutomationCompositionAck automationCompositionAckMessage) {
         LOGGER.debug("AutomationComposition Update Ack message received {}", automationCompositionAckMessage);
         setAcElementStateInDb(automationCompositionAckMessage);
@@ -123,10 +123,10 @@ public class SupervisionHandler {
      */
     @MessageIntercept
     @Timed(
-            value = "listener.automation_composition_statechange_ack",
-            description = "AUTOMATION_COMPOSITION_STATECHANGE_ACK messages received")
+        value = "listener.automation_composition_statechange_ack",
+        description = "AUTOMATION_COMPOSITION_STATECHANGE_ACK messages received")
     public void handleAutomationCompositionStateChangeAckMessage(
-            AutomationCompositionAck automationCompositionAckMessage) {
+        AutomationCompositionAck automationCompositionAckMessage) {
         LOGGER.debug("AutomationComposition StateChange Ack message received {}", automationCompositionAckMessage);
         setAcElementStateInDb(automationCompositionAckMessage);
     }
@@ -134,23 +134,23 @@ public class SupervisionHandler {
     private void setAcElementStateInDb(AutomationCompositionAck automationCompositionAckMessage) {
         if (automationCompositionAckMessage.getAutomationCompositionResultMap() != null) {
             var automationComposition = automationCompositionProvider
-                    .findAutomationComposition(automationCompositionAckMessage.getAutomationCompositionId());
+                .findAutomationComposition(automationCompositionAckMessage.getAutomationCompositionId());
             if (automationComposition.isPresent()) {
                 var updated = updateState(automationComposition.get(),
-                        automationCompositionAckMessage.getAutomationCompositionResultMap().entrySet());
+                    automationCompositionAckMessage.getAutomationCompositionResultMap().entrySet());
                 updated |= setPrimed(automationComposition.get());
                 if (updated) {
                     automationCompositionProvider.updateAutomationComposition(automationComposition.get());
                 }
             } else {
                 LOGGER.warn("AutomationComposition not found in database {}",
-                        automationCompositionAckMessage.getAutomationCompositionId());
+                    automationCompositionAckMessage.getAutomationCompositionId());
             }
         }
     }
 
     private boolean updateState(AutomationComposition automationComposition,
-            Set<Map.Entry<UUID, AutomationCompositionElementAck>> automationCompositionResultSet) {
+                                Set<Map.Entry<UUID, AutomationCompositionElementAck>> automationCompositionResultSet) {
         var updated = false;
         for (var acElementAck : automationCompositionResultSet) {
             var element = automationComposition.getElements().get(acElementAck.getKey());
@@ -167,9 +167,9 @@ public class SupervisionHandler {
         if (acElements != null) {
             Boolean primedFlag = true;
             var checkOpt = automationComposition.getElements().values().stream()
-                    .filter(acElement -> (!acElement.getState().equals(AutomationCompositionState.PASSIVE)
-                            || !acElement.getState().equals(AutomationCompositionState.RUNNING)))
-                    .findAny();
+                .filter(acElement -> (!acElement.getState().equals(AutomationCompositionState.PASSIVE)
+                    || !acElement.getState().equals(AutomationCompositionState.RUNNING)))
+                .findAny();
             if (checkOpt.isEmpty()) {
                 primedFlag = false;
             }
@@ -188,7 +188,7 @@ public class SupervisionHandler {
      * @throws AutomationCompositionException on supervision errors
      */
     public void triggerAutomationCompositionSupervision(AutomationComposition automationComposition)
-            throws AutomationCompositionException {
+        throws AutomationCompositionException {
         switch (automationComposition.getOrderedState()) {
             case UNINITIALISED:
                 superviseAutomationCompositionUninitialization(automationComposition);
@@ -204,8 +204,8 @@ public class SupervisionHandler {
 
             default:
                 exceptionOccured(Response.Status.NOT_ACCEPTABLE,
-                        "A automation composition cannot be commanded to go into state "
-                                + automationComposition.getOrderedState().name());
+                    "A automation composition cannot be commanded to go into state "
+                        + automationComposition.getOrderedState().name());
         }
     }
 
@@ -218,39 +218,39 @@ public class SupervisionHandler {
      * @throws AutomationCompositionException on supervision errors
      */
     private void superviseAutomationCompositionUninitialization(AutomationComposition automationComposition)
-            throws AutomationCompositionException {
+        throws AutomationCompositionException {
         switch (automationComposition.getState()) {
             case UNINITIALISED:
                 exceptionOccured(Response.Status.NOT_ACCEPTABLE,
-                        AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name());
+                    AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name());
                 break;
 
             case UNINITIALISED2PASSIVE:
             case PASSIVE:
                 automationComposition.setState(AutomationCompositionState.PASSIVE2UNINITIALISED);
                 automationCompositionStateChangePublisher.send(automationComposition,
-                        getFirstStartPhase(automationComposition));
+                    getFirstStartPhase(automationComposition));
                 break;
 
             case PASSIVE2UNINITIALISED:
                 exceptionOccured(Response.Status.NOT_ACCEPTABLE,
-                        AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name()
-                                + AND_TRANSITIONING_TO_STATE + automationComposition.getOrderedState());
+                    AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name()
+                        + AND_TRANSITIONING_TO_STATE + automationComposition.getOrderedState());
                 break;
 
             default:
                 exceptionOccured(Response.Status.NOT_ACCEPTABLE, AUTOMATION_COMPOSITION_CANNOT_TRANSITION_FROM_STATE
-                        + automationComposition.getState().name() + TO_STATE + automationComposition.getOrderedState());
+                    + automationComposition.getState().name() + TO_STATE + automationComposition.getOrderedState());
                 break;
         }
     }
 
     private void superviseAutomationCompositionPassivation(AutomationComposition automationComposition)
-            throws AutomationCompositionException {
+        throws AutomationCompositionException {
         switch (automationComposition.getState()) {
             case PASSIVE:
                 exceptionOccured(Response.Status.NOT_ACCEPTABLE,
-                        AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name());
+                    AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name());
                 break;
             case UNINITIALISED:
                 automationComposition.setState(AutomationCompositionState.UNINITIALISED2PASSIVE);
@@ -260,46 +260,46 @@ public class SupervisionHandler {
             case UNINITIALISED2PASSIVE:
             case RUNNING2PASSIVE:
                 exceptionOccured(Response.Status.NOT_ACCEPTABLE,
-                        AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name()
-                                + AND_TRANSITIONING_TO_STATE + automationComposition.getOrderedState());
+                    AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name()
+                        + AND_TRANSITIONING_TO_STATE + automationComposition.getOrderedState());
                 break;
 
             case RUNNING:
                 automationComposition.setState(AutomationCompositionState.RUNNING2PASSIVE);
                 automationCompositionStateChangePublisher.send(automationComposition,
-                        getFirstStartPhase(automationComposition));
+                    getFirstStartPhase(automationComposition));
                 break;
 
             default:
                 exceptionOccured(Response.Status.NOT_ACCEPTABLE, AUTOMATION_COMPOSITION_CANNOT_TRANSITION_FROM_STATE
-                        + automationComposition.getState().name() + TO_STATE + automationComposition.getOrderedState());
+                    + automationComposition.getState().name() + TO_STATE + automationComposition.getOrderedState());
                 break;
         }
     }
 
     private void superviseAutomationCompositionActivation(AutomationComposition automationComposition)
-            throws AutomationCompositionException {
+        throws AutomationCompositionException {
         switch (automationComposition.getState()) {
             case RUNNING:
                 exceptionOccured(Response.Status.NOT_ACCEPTABLE,
-                        AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name());
+                    AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name());
                 break;
 
             case PASSIVE2RUNNING:
                 exceptionOccured(Response.Status.NOT_ACCEPTABLE,
-                        AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name()
-                                + AND_TRANSITIONING_TO_STATE + automationComposition.getOrderedState());
+                    AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name()
+                        + AND_TRANSITIONING_TO_STATE + automationComposition.getOrderedState());
                 break;
 
             case PASSIVE:
                 automationComposition.setState(AutomationCompositionState.PASSIVE2RUNNING);
                 automationCompositionStateChangePublisher.send(automationComposition,
-                        getFirstStartPhase(automationComposition));
+                    getFirstStartPhase(automationComposition));
                 break;
 
             default:
                 exceptionOccured(Response.Status.NOT_ACCEPTABLE, AUTOMATION_COMPOSITION_CANNOT_TRANSITION_FROM_STATE
-                        + automationComposition.getState().name() + TO_STATE + automationComposition.getOrderedState());
+                    + automationComposition.getState().name() + TO_STATE + automationComposition.getOrderedState());
                 break;
         }
     }
index da9187d..2c9e84b 100644 (file)
@@ -59,7 +59,7 @@ public class SupervisionParticipantHandler {
         saveParticipantStatus(participantRegisterMsg);
 
         participantRegisterAckPublisher.send(participantRegisterMsg.getMessageId(),
-                participantRegisterMsg.getParticipantId(), participantRegisterMsg.getParticipantType());
+            participantRegisterMsg.getParticipantId(), participantRegisterMsg.getParticipantType());
     }
 
     /**
@@ -76,7 +76,7 @@ public class SupervisionParticipantHandler {
         if (participantOpt.isPresent()) {
             var participant = participantOpt.get();
             participant.setParticipantState(ParticipantState.OFF_LINE);
-            participantProvider.saveParticipant(participant);
+            participantProvider.updateParticipant(participant);
         }
 
         participantDeregisterAckPublisher.send(participantDeregisterMsg.getMessageId());
@@ -110,7 +110,7 @@ public class SupervisionParticipantHandler {
             var participant = participantOpt.get();
             participant.setParticipantState(ParticipantState.ON_LINE);
 
-            participantProvider.saveParticipant(participant);
+            participantProvider.updateParticipant(participant);
         }
     }
 }
index e595f3b..f758c98 100644 (file)
@@ -71,10 +71,11 @@ public class SupervisionScanner {
      * @param acRuntimeParameterGroup the parameters for the automation composition runtime
      */
     public SupervisionScanner(final AutomationCompositionProvider automationCompositionProvider,
-            AcDefinitionProvider acDefinitionProvider,
-            final AutomationCompositionStateChangePublisher automationCompositionStateChangePublisher,
-            AutomationCompositionUpdatePublisher automationCompositionUpdatePublisher,
-            ParticipantProvider participantProvider, final AcRuntimeParameterGroup acRuntimeParameterGroup) {
+                              AcDefinitionProvider acDefinitionProvider,
+                              final AutomationCompositionStateChangePublisher automationCompositionStateChangePublisher,
+                              AutomationCompositionUpdatePublisher automationCompositionUpdatePublisher,
+                              ParticipantProvider participantProvider,
+                              final AcRuntimeParameterGroup acRuntimeParameterGroup) {
         this.automationCompositionProvider = automationCompositionProvider;
         this.acDefinitionProvider = acDefinitionProvider;
         this.automationCompositionStateChangePublisher = automationCompositionStateChangePublisher;
@@ -82,12 +83,12 @@ public class SupervisionScanner {
         this.participantProvider = participantProvider;
 
         automationCompositionCounter.setMaxRetryCount(
-                acRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount());
+            acRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount());
         automationCompositionCounter
-                .setMaxWaitMs(acRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs());
+            .setMaxWaitMs(acRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs());
 
         participantStatusCounter.setMaxRetryCount(
-                acRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount());
+            acRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount());
         participantStatusCounter.setMaxWaitMs(acRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs());
     }
 
@@ -123,11 +124,11 @@ public class SupervisionScanner {
             return;
         }
         if (participantStatusCounter.getDuration(id) > participantStatusCounter.getMaxWaitMs()
-                && !participantStatusCounter.count(id)) {
+            && !participantStatusCounter.count(id)) {
             LOGGER.debug("report Participant fault");
             participantStatusCounter.setFault(id);
             participant.setParticipantState(ParticipantState.OFF_LINE);
-            participantProvider.saveParticipant(participant);
+            participantProvider.updateParticipant(participant);
         }
     }
 
@@ -139,7 +140,7 @@ public class SupervisionScanner {
     }
 
     private void scanAutomationComposition(final AutomationComposition automationComposition,
-            ToscaServiceTemplate toscaServiceTemplate, boolean counterCheck) {
+                                           ToscaServiceTemplate toscaServiceTemplate, boolean counterCheck) {
         LOGGER.debug("scanning automation composition {} . . .", automationComposition.getInstanceId());
 
         if (automationComposition.getState().equals(automationComposition.getOrderedState().asState())) {
@@ -157,7 +158,7 @@ public class SupervisionScanner {
         var defaultMax = 0; // max startPhase
         for (var element : automationComposition.getElements().values()) {
             var toscaNodeTemplate = toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates()
-                    .get(element.getDefinition().getName());
+                .get(element.getDefinition().getName());
             int startPhase = ParticipantUtils.findStartPhase(toscaNodeTemplate.getProperties());
             defaultMin = Math.min(defaultMin, startPhase);
             defaultMax = Math.max(defaultMax, startPhase);
@@ -170,7 +171,7 @@ public class SupervisionScanner {
 
         if (completed) {
             LOGGER.debug("automation composition scan: transition from state {} to {} completed",
-                    automationComposition.getState(), automationComposition.getOrderedState());
+                automationComposition.getState(), automationComposition.getOrderedState());
 
             automationComposition.setState(automationComposition.getOrderedState().asState());
             automationCompositionProvider.updateAutomationComposition(automationComposition);
@@ -179,19 +180,19 @@ public class SupervisionScanner {
             clearFaultAndCounter(automationComposition);
         } else {
             LOGGER.debug("automation composition scan: transition from state {} to {} not completed",
-                    automationComposition.getState(), automationComposition.getOrderedState());
+                automationComposition.getState(), automationComposition.getOrderedState());
 
             var nextSpNotCompleted =
-                    AutomationCompositionState.UNINITIALISED2PASSIVE.equals(automationComposition.getState())
-                            || AutomationCompositionState.PASSIVE2RUNNING.equals(automationComposition.getState())
-                                    ? minSpNotCompleted
-                                    : maxSpNotCompleted;
+                AutomationCompositionState.UNINITIALISED2PASSIVE.equals(automationComposition.getState())
+                    || AutomationCompositionState.PASSIVE2RUNNING.equals(automationComposition.getState())
+                    ? minSpNotCompleted
+                    : maxSpNotCompleted;
 
             var firstStartPhase =
-                    AutomationCompositionState.UNINITIALISED2PASSIVE.equals(automationComposition.getState())
-                            || AutomationCompositionState.PASSIVE2RUNNING.equals(automationComposition.getState())
-                                    ? defaultMin
-                                    : defaultMax;
+                AutomationCompositionState.UNINITIALISED2PASSIVE.equals(automationComposition.getState())
+                    || AutomationCompositionState.PASSIVE2RUNNING.equals(automationComposition.getState())
+                    ? defaultMin
+                    : defaultMax;
 
             if (nextSpNotCompleted != phaseMap.getOrDefault(automationComposition.getInstanceId(), firstStartPhase)) {
                 phaseMap.put(automationComposition.getInstanceId(), nextSpNotCompleted);
index 655ce7e..f2692a9 100644 (file)
@@ -1,5 +1,5 @@
 #  ============LICENSE_START=======================================================
-#  Copyright (C) 2022 Nordix Foundation
+#  Copyright (C) 2022-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.
@@ -65,7 +65,6 @@ paths:
       - name: X-onap-RequestId
         in: header
         description: RequestID for http transaction
-        required: true
         schema:
           type: string
           format: uuid
@@ -138,7 +137,7 @@ paths:
       description: Requests all participants to immediately generate a heartbeat report with their information and status
         and the information and status of all their AC Element Types and Instances. The results are published on subsequent
         GET REST requests on the "participants" endpoint.
-      operationId: orderAllParticiantsReport
+      operationId: orderAllParticipantsReport
       parameters:
       - name: X-onap-RequestId
         in: header
@@ -230,7 +229,6 @@ paths:
       - name: X-onap-RequestId
         in: header
         description: RequestID for http transaction
-        required: true
         schema:
           type: string
           format: uuid
@@ -331,7 +329,6 @@ paths:
           format: uuid
       - name: X-onap-RequestId
         in: header
-        required: true
         description: RequestID for http transaction
         schema:
           type: string
diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/participant/ParticipantControllerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/participant/ParticipantControllerTest.java
new file mode 100644 (file)
index 0000000..e6f7118
--- /dev/null
@@ -0,0 +1,176 @@
+/*-
+ * ============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.runtime.participant;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.onap.policy.clamp.acm.runtime.main.rest.ParticipantController;
+import org.onap.policy.clamp.acm.runtime.util.rest.CommonRestController;
+import org.onap.policy.clamp.models.acm.concepts.Participant;
+import org.onap.policy.clamp.models.acm.concepts.ParticipantInformation;
+import org.onap.policy.clamp.models.acm.persistence.concepts.JpaParticipant;
+import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider;
+import org.onap.policy.clamp.models.acm.persistence.provider.ProviderUtils;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.models.base.PfModelException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+/**
+ * Class to perform unit test of {@link ParticipantController}.
+ *
+ */
+
+@ExtendWith(SpringExtension.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ActiveProfiles({ "test", "default" })
+public class ParticipantControllerTest extends CommonRestController {
+    private static final String PARTICIPANTS_ENDPOINT = "participants";
+
+    @LocalServerPort
+    private int randomServerPort;
+
+    private static final Coder CODER = new StandardCoder();
+    private static final String PARTICIPANT_JSON = "src/test/resources/providers/TestParticipant.json";
+    private static final String PARTICIPANT_JSON2 = "src/test/resources/providers/TestParticipant2.json";
+    private static final String LIST_IS_NULL = ".*. is marked .*ull but is null";
+
+    private static final List<Participant> inputParticipants = new ArrayList<>();
+    private static List<JpaParticipant> jpaParticipantList;
+    private static final String originalJson = ResourceUtils.getResourceAsString(PARTICIPANT_JSON);
+    private static final String originalJson2 = ResourceUtils.getResourceAsString(PARTICIPANT_JSON2);
+
+    @Autowired
+    private ParticipantProvider participantProvider;
+
+    /**
+     * Adds participants to the db from json file.
+     */
+    @BeforeAll
+    public static void setUpBeforeClass() throws CoderException {
+        inputParticipants.add(CODER.decode(originalJson, Participant.class));
+        inputParticipants.add(CODER.decode(originalJson2, Participant.class));
+        jpaParticipantList = ProviderUtils.getJpaAndValidateList(
+            inputParticipants, JpaParticipant::new, "participant");
+    }
+
+    @BeforeEach
+    public void setUpPort() {
+        super.setHttpPrefix(randomServerPort);
+    }
+
+    @Test
+    void testSwagger() {
+        super.testSwagger(PARTICIPANTS_ENDPOINT);
+    }
+
+    @Test
+    void testUnauthorizedQuery() {
+        assertUnauthorizedGet(PARTICIPANTS_ENDPOINT);
+    }
+
+    @Test
+    void testQueryParticipant() {
+        participantProvider.saveParticipant(inputParticipants.get(0));
+        UUID participantId = participantProvider.getParticipants().get(0).getParticipantId();
+        var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT + "/" + participantId);
+        var response = invocationBuilder.buildGet().invoke();
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+        var entityList = response.readEntity(ParticipantInformation.class);
+        assertNotNull(entityList);
+    }
+
+    @Test
+    void testBadQueryParticipant() {
+        participantProvider.saveParticipant(inputParticipants.get(0));
+        UUID participantId = participantProvider.getParticipants().get(0).getParticipantId();
+        var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT + "/" + UUID.randomUUID());
+        var response = invocationBuilder.buildGet().invoke();
+        assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus());
+    }
+
+    @Test
+    void getAllParticipants() {
+        inputParticipants.forEach(p -> {
+            participantProvider.saveParticipant(p);
+        });
+        var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT);
+        var response = invocationBuilder.buildGet().invoke();
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+        List<ParticipantInformation> entityList = response.readEntity(new GenericType<>() {});
+        assertThat(entityList.size() == inputParticipants.size());
+    }
+
+    @Test
+    void testOrderParticipantReport() throws PfModelException {
+        participantProvider.saveParticipant(inputParticipants.get(0));
+        UUID participantId = participantProvider.getParticipants().get(0).getParticipantId();
+        var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT
+            + "/"
+            + participantId);
+        var response = invocationBuilder.header("Content-Length", 0).put(Entity.entity(""
+            +
+            "", MediaType.APPLICATION_JSON));
+        assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatus());
+    }
+
+    @Test
+    void testBadOrderParticipantReport() throws PfModelException {
+        var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT
+            + "/"
+            + UUID.randomUUID());
+        var response = invocationBuilder.header("Content-Length", 0).put(Entity.entity(""
+            +
+            "", MediaType.APPLICATION_JSON));
+        assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus());
+    }
+
+    @Test
+    void testOrderAllParticipantReport() {
+        inputParticipants.forEach(p -> {
+            participantProvider.saveParticipant(p);
+        });
+        var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT);
+        var response = invocationBuilder.header("Content-Length", 0).put(Entity.entity(""
+            +
+            "", MediaType.APPLICATION_JSON));
+        assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatus());
+    }
+}
index 9e35f2c..f7c18b6 100644 (file)
@@ -41,7 +41,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 class SupervisionParticipantHandlerTest {
     private static final ToscaConceptIdentifier PARTICIPANT_ID = new ToscaConceptIdentifier("ParticipantId", "1.0.0");
     private static final ToscaConceptIdentifier PARTICIPANT_TYPE =
-            new ToscaConceptIdentifier("ParticipantType", "1.0.0");
+        new ToscaConceptIdentifier("ParticipantType", "1.0.0");
 
     @Test
     void testHandleParticipantDeregister() {
@@ -59,11 +59,11 @@ class SupervisionParticipantHandlerTest {
         participantDeregisterMessage.setParticipantType(PARTICIPANT_TYPE);
         var participantDeregisterAckPublisher = mock(ParticipantDeregisterAckPublisher.class);
         var handler = new SupervisionParticipantHandler(participantProvider,
-                mock(ParticipantRegisterAckPublisher.class), participantDeregisterAckPublisher);
+            mock(ParticipantRegisterAckPublisher.class), participantDeregisterAckPublisher);
 
         handler.handleParticipantMessage(participantDeregisterMessage);
 
-        verify(participantProvider).saveParticipant(any());
+        verify(participantProvider).updateParticipant(any());
         verify(participantDeregisterAckPublisher).send(participantDeregisterMessage.getMessageId());
     }
 
@@ -81,13 +81,13 @@ class SupervisionParticipantHandlerTest {
         var participantProvider = mock(ParticipantProvider.class);
         var participantRegisterAckPublisher = mock(ParticipantRegisterAckPublisher.class);
         var handler = new SupervisionParticipantHandler(participantProvider, participantRegisterAckPublisher,
-                mock(ParticipantDeregisterAckPublisher.class));
+            mock(ParticipantDeregisterAckPublisher.class));
 
         handler.handleParticipantMessage(participantRegisterMessage);
 
         verify(participantProvider).saveParticipant(any());
         verify(participantRegisterAckPublisher).send(participantRegisterMessage.getMessageId(), PARTICIPANT_ID,
-                PARTICIPANT_TYPE);
+            PARTICIPANT_TYPE);
     }
 
     @Test
@@ -99,7 +99,7 @@ class SupervisionParticipantHandlerTest {
 
         var participantProvider = mock(ParticipantProvider.class);
         var handler = new SupervisionParticipantHandler(participantProvider,
-                mock(ParticipantRegisterAckPublisher.class), mock(ParticipantDeregisterAckPublisher.class));
+            mock(ParticipantRegisterAckPublisher.class), mock(ParticipantDeregisterAckPublisher.class));
         handler.handleParticipantMessage(participantStatusMessage);
 
         verify(participantProvider).saveParticipant(any());
index 0142f29..1e07ec9 100644 (file)
@@ -61,7 +61,7 @@ class SupervisionScannerTest {
     private static UUID compositionId;
 
     private static final ToscaConceptIdentifier PARTICIPANT_TYPE =
-            new ToscaConceptIdentifier("org.onap.policy.clamp.acm.PolicyParticipant", PARTICIPANT_VERSION);
+        new ToscaConceptIdentifier("org.onap.policy.clamp.acm.PolicyParticipant", PARTICIPANT_VERSION);
 
     @BeforeAll
     public static void setUpBeforeAll() {
@@ -83,11 +83,11 @@ class SupervisionScannerTest {
 
         var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud");
         when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId))
-                .thenReturn(List.of(automationComposition));
+            .thenReturn(List.of(automationComposition));
 
         var supervisionScanner = new SupervisionScanner(automationCompositionProvider, acDefinitionProvider,
-                automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider,
-                acRuntimeParameterGroup);
+            automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider,
+            acRuntimeParameterGroup);
         supervisionScanner.run(false);
 
         verify(automationCompositionProvider, times(0)).updateAutomationComposition(any(AutomationComposition.class));
@@ -100,7 +100,7 @@ class SupervisionScannerTest {
         automationComposition.setOrderedState(AutomationCompositionOrderedState.UNINITIALISED);
         var automationCompositionProvider = mock(AutomationCompositionProvider.class);
         when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId))
-                .thenReturn(List.of(automationComposition));
+            .thenReturn(List.of(automationComposition));
 
         var automationCompositionUpdatePublisher = mock(AutomationCompositionUpdatePublisher.class);
         var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class);
@@ -108,8 +108,8 @@ class SupervisionScannerTest {
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
 
         var supervisionScanner = new SupervisionScanner(automationCompositionProvider, acDefinitionProvider,
-                automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider,
-                acRuntimeParameterGroup);
+            automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider,
+            acRuntimeParameterGroup);
         supervisionScanner.run(false);
 
         verify(automationCompositionProvider, times(1)).updateAutomationComposition(any(AutomationComposition.class));
@@ -120,7 +120,7 @@ class SupervisionScannerTest {
         var automationCompositionProvider = mock(AutomationCompositionProvider.class);
         var automationComposition = new AutomationComposition();
         when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId))
-                .thenReturn(List.of(automationComposition));
+            .thenReturn(List.of(automationComposition));
 
         var participantProvider = mock(ParticipantProvider.class);
         var participant = new Participant();
@@ -133,8 +133,8 @@ class SupervisionScannerTest {
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
 
         var supervisionScanner = new SupervisionScanner(automationCompositionProvider, acDefinitionProvider,
-                automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider,
-                acRuntimeParameterGroup);
+            automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider,
+            acRuntimeParameterGroup);
 
         supervisionScanner.handleParticipantStatus(participant.getKey().asIdentifier());
         supervisionScanner.run(true);
@@ -148,7 +148,7 @@ class SupervisionScannerTest {
         automationComposition.setOrderedState(AutomationCompositionOrderedState.PASSIVE);
         for (var element : automationComposition.getElements().values()) {
             if ("org.onap.domain.database.Http_PMSHMicroserviceAutomationCompositionElement"
-                    .equals(element.getDefinition().getName())) {
+                .equals(element.getDefinition().getName())) {
                 element.setOrderedState(AutomationCompositionOrderedState.PASSIVE);
                 element.setState(AutomationCompositionState.UNINITIALISED);
             } else {
@@ -159,7 +159,7 @@ class SupervisionScannerTest {
 
         var automationCompositionProvider = mock(AutomationCompositionProvider.class);
         when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId))
-                .thenReturn(List.of(automationComposition));
+            .thenReturn(List.of(automationComposition));
 
         var participantProvider = mock(ParticipantProvider.class);
         var automationCompositionUpdatePublisher = mock(AutomationCompositionUpdatePublisher.class);
@@ -167,8 +167,8 @@ class SupervisionScannerTest {
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
 
         var supervisionScanner = new SupervisionScanner(automationCompositionProvider, acDefinitionProvider,
-                automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider,
-                acRuntimeParameterGroup);
+            automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider,
+            acRuntimeParameterGroup);
 
         supervisionScanner.run(false);
 
@@ -180,7 +180,7 @@ class SupervisionScannerTest {
         var automationCompositionProvider = mock(AutomationCompositionProvider.class);
         var automationComposition = new AutomationComposition();
         when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId))
-                .thenReturn(List.of(automationComposition));
+            .thenReturn(List.of(automationComposition));
 
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanParticipant");
         acRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().setMaxWaitMs(-1);
@@ -199,14 +199,14 @@ class SupervisionScannerTest {
         var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class);
 
         var supervisionScanner = new SupervisionScanner(automationCompositionProvider, acDefinitionProvider,
-                automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider,
-                acRuntimeParameterGroup);
+            automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider,
+            acRuntimeParameterGroup);
 
         supervisionScanner.handleParticipantStatus(participant.getKey().asIdentifier());
         supervisionScanner.run(true);
-        verify(participantProvider, times(0)).saveParticipant(any());
+        verify(participantProvider, times(0)).updateParticipant(any());
 
         supervisionScanner.run(true);
-        verify(participantProvider, times(1)).saveParticipant(any());
+        verify(participantProvider, times(1)).updateParticipant(any());
     }
 }
diff --git a/runtime-acm/src/test/resources/providers/TestParticipant.json b/runtime-acm/src/test/resources/providers/TestParticipant.json
new file mode 100644 (file)
index 0000000..fe06ba0
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "name": "dummy_participant1",
+  "version": "1.0.1",
+  "definition": {
+    "name": "org.onap.domain.pmsh.PMSHAutomationCompositionDefinition",
+    "version": "1.0.0"
+  },
+  "participantState": "ON_LINE",
+  "description": "A dummy PMSH participant1",
+  "participantId": "82fd8ef9-1d1e-4343-9b28-7f9564ee3de6",
+  "participantType": {
+    "name": "org.onap.domain.pmsh.PolicyAutomationCompositionDefinition",
+    "version": "1.0.0"
+  }
+}
diff --git a/runtime-acm/src/test/resources/providers/TestParticipant2.json b/runtime-acm/src/test/resources/providers/TestParticipant2.json
new file mode 100644 (file)
index 0000000..9a34184
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "name": "dummy_participant2",
+  "version": "1.0.1",
+  "definition": {
+    "name": "org.onap.domain.pmsh.PMSHAutomationCompositionDefinition2",
+    "version": "1.0.0"
+  },
+  "participantState": "ON_LINE",
+  "description": "A dummy PMSH participant2",
+  "participantId": "cac01d0a-7ba8-4dda-b9be-6983c46c0546",
+  "participantType": {
+    "name": "org.onap.domain.pmsh.PolicyAutomationCompositionDefinition2",
+    "version": "1.0.0"
+  }
+}