From 4d9c538ae83a4ca78ce468fa795b925e24ca5520 Mon Sep 17 00:00:00 2001 From: FrancescoFioraEst Date: Fri, 16 May 2025 15:06:01 +0100 Subject: [PATCH] Add pagination support in endpoint GET /participants Issue-ID: POLICY-5363 Change-Id: I7b32f324a3fff681ccf77a6d9e3c29dac6503f0e Signed-off-by: FrancescoFioraEst --- .../persistence/provider/ParticipantProvider.java | 15 ++- .../AutomationCompositionElementRepository.java | 5 +- .../repository/NodeTemplateStateRepository.java | 10 +- .../provider/ParticipantProviderTest.java | 37 ++++-- .../runtime/main/rest/CommissioningController.java | 4 +- .../runtime/main/rest/InstantiationController.java | 4 +- .../runtime/main/rest/ParticipantController.java | 13 +- .../main/rest/stub/ParticipantControllerStub.java | 7 +- .../runtime/main/web/AbstractRestController.java | 8 +- .../participants/AcmParticipantProvider.java | 66 +++++----- .../src/main/resources/openapi/openapi.yaml | 24 ++++ .../participant/ParticipantControllerTest.java | 136 ++++++++++++++++++--- 12 files changed, 242 insertions(+), 87 deletions(-) diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProvider.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProvider.java index 85c9e67cb..7715ccc1d 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProvider.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProvider.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation. + * Copyright (C) 2021-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,6 +44,7 @@ import org.onap.policy.clamp.models.acm.persistence.repository.ParticipantReplic import org.onap.policy.clamp.models.acm.persistence.repository.ParticipantRepository; import org.onap.policy.models.base.PfModelRuntimeException; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -155,22 +156,26 @@ public class ParticipantProvider { * Retrieve a list of automation composition elements associated with a participantId. * * @param participantId the participant id associated with the automation composition elements + * @param pageable the Pageable * @return the list of associated elements */ - public List getAutomationCompositionElements(@NonNull final UUID participantId) { + public List getAutomationCompositionElements( + @NonNull final UUID participantId, @NonNull final Pageable pageable) { return ProviderUtils.asEntityList(automationCompositionElementRepository - .findByParticipantId(participantId.toString())); + .findByParticipantId(participantId.toString(), pageable)); } /** * Retrieve a list of node template states elements associated with a participantId from ac definitions. * * @param participantId the participant id associated with the automation composition elements + * @param pageable the Pageable * @return the list of associated elements */ - public List getAcNodeTemplateStates(@NonNull final UUID participantId) { + public List getAcNodeTemplateStates( + @NonNull final UUID participantId, @NonNull final Pageable pageable) { return ProviderUtils.asEntityList(nodeTemplateStateRepository - .findByParticipantId(participantId.toString())); + .findByParticipantId(participantId.toString(), pageable)); } /** diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionElementRepository.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionElementRepository.java index e375e1f34..2eb18afe7 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionElementRepository.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionElementRepository.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2025 Nordix Foundation. + * Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,9 +22,10 @@ package org.onap.policy.clamp.models.acm.persistence.repository; import java.util.List; import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionElement; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; public interface AutomationCompositionElementRepository extends JpaRepository { - List findByParticipantId(String participantId); + List findByParticipantId(String participantId, Pageable pageable); } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/NodeTemplateStateRepository.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/NodeTemplateStateRepository.java index 3a879a78b..342334178 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/NodeTemplateStateRepository.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/NodeTemplateStateRepository.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation. + * Copyright (C) 2023,2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,13 +22,13 @@ package org.onap.policy.clamp.models.acm.persistence.repository; import java.util.List; import org.onap.policy.clamp.models.acm.persistence.concepts.JpaNodeTemplateState; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.repository.query.QueryByExampleExecutor; -public interface NodeTemplateStateRepository extends - JpaRepository, - QueryByExampleExecutor { +public interface NodeTemplateStateRepository extends JpaRepository { List findByParticipantId(String participantId); + + List findByParticipantId(String participantId, Pageable pageable); } diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProviderTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProviderTest.java index ac3aa87c5..a3d7b7927 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProviderTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProviderTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation. + * Copyright (C) 2021-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,6 +54,8 @@ import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.resources.ResourceUtils; import org.onap.policy.models.base.PfModelRuntimeException; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; class ParticipantProviderTest { @@ -182,10 +184,11 @@ class ParticipantProviderTest { var acElementList = inputAutomationCompositionsJpa.get(0).getElements(); var participantId = UUID.randomUUID(); - when(automationCompositionElementRepository.findByParticipantId(participantId.toString())) - .thenReturn(acElementList); + var pageable = PageRequest.of(0, 5); + when(automationCompositionElementRepository.findByParticipantId(participantId.toString(), pageable)) + .thenReturn(acElementList); - var listOfAcElements = participantProvider.getAutomationCompositionElements(participantId); + var listOfAcElements = participantProvider.getAutomationCompositionElements(participantId, pageable); assertThat(listOfAcElements).hasSameSizeAs(acElementList); assertEquals(UUID.fromString(acElementList.get(0).getElementId()), listOfAcElements.get(0).getId()); @@ -197,13 +200,16 @@ class ParticipantProviderTest { var automationCompositionElementRepository = mock(AutomationCompositionElementRepository.class); var nodeTemplateStateRepository = mock(NodeTemplateStateRepository.class); var participantId = jpaParticipantList.get(0).getParticipantId(); - when(nodeTemplateStateRepository.findByParticipantId(participantId)).thenReturn(jpaNodeTemplateStateList); + var pageable = PageRequest.of(0, 5); + when(nodeTemplateStateRepository + .findByParticipantId(participantId, pageable)).thenReturn(jpaNodeTemplateStateList); var participantProvider = new ParticipantProvider(participantRepository, automationCompositionElementRepository, nodeTemplateStateRepository, mock(ParticipantReplicaRepository.class)); - var listOfNodeTemplateState = participantProvider.getAcNodeTemplateStates(UUID.fromString(participantId)); + var listOfNodeTemplateState = + participantProvider.getAcNodeTemplateStates(UUID.fromString(participantId), pageable); assertEquals(listOfNodeTemplateState, nodeTemplateStateList); } @@ -222,11 +228,26 @@ class ParticipantProviderTest { assertThrows(NullPointerException.class, () -> participantProvider.findParticipant(null)); assertThrows(NullPointerException.class, () -> participantProvider.saveParticipant(null)); assertThrows(NullPointerException.class, () -> participantProvider.deleteParticipant(null)); - assertThrows(NullPointerException.class, () -> participantProvider.getAutomationCompositionElements(null)); - assertThrows(NullPointerException.class, () -> participantProvider.getAcNodeTemplateStates(null)); + + var pageable = Pageable.unpaged(); + assertThrows(NullPointerException.class, () -> + participantProvider.getAutomationCompositionElements(null, pageable)); + var participantId = UUID.randomUUID(); + assertThrows(NullPointerException.class, () -> + participantProvider.getAutomationCompositionElements(participantId, null)); + assertThrows(NullPointerException.class, () -> + participantProvider.getAcNodeTemplateStates(null, pageable)); + assertThrows(NullPointerException.class, () -> + participantProvider.getAcNodeTemplateStates(participantId, null)); + assertThrows(NullPointerException.class, () -> participantProvider.findParticipantReplica(null)); assertThrows(NullPointerException.class, () -> participantProvider.saveParticipantReplica(null)); assertThrows(NullPointerException.class, () -> participantProvider.deleteParticipantReplica(null)); + assertThrows(NullPointerException.class, () -> + participantProvider.getAutomationCompositionElements(null, pageable)); + assertThrows(NullPointerException.class, () -> + participantProvider.getAutomationCompositionElements(participantId, null)); + assertThrows(NullPointerException.class, () -> participantProvider.getAcNodeTemplateStates(null, null)); } @Test diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/CommissioningController.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/CommissioningController.java index 56f3179c2..26fb5f195 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/CommissioningController.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/CommissioningController.java @@ -32,8 +32,6 @@ import org.onap.policy.clamp.models.acm.messages.rest.commissioning.Commissionin import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplates; import org.springframework.context.annotation.Profile; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; @@ -90,7 +88,7 @@ public class CommissioningController extends AbstractRestController implements A @Override public ResponseEntity queryCompositionDefinitions(String name, String version, Integer page, Integer size, UUID requestId) { - var pageable = page != null && size != null ? PageRequest.of(page, size) : Pageable.unpaged(); + var pageable = getPageable(page, size); return ResponseEntity.ok().body(provider.getAutomationCompositionDefinitions(name, version, pageable)); } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/InstantiationController.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/InstantiationController.java index 2a45c5498..386241d02 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/InstantiationController.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/InstantiationController.java @@ -32,8 +32,6 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AcInstanceStateUpdate; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse; import org.springframework.context.annotation.Profile; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; @@ -96,7 +94,7 @@ public class InstantiationController extends AbstractRestController implements A @Override public ResponseEntity queryCompositionInstances(UUID compositionId, String name, String version, Integer page, Integer size, UUID requestId) { - var pageable = page != null && size != null ? PageRequest.of(page, size) : Pageable.unpaged(); + var pageable = getPageable(page, size); return ResponseEntity.ok().body(provider.getAutomationCompositions(compositionId, name, version, pageable)); } 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 index 1136dcb16..51b3baa00 100644 --- 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 @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation. + * Copyright (C) 2023-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,8 +40,10 @@ public class ParticipantController extends AbstractRestController implements Par private final AcmParticipantProvider acmParticipantProvider; @Override - public ResponseEntity getParticipant(UUID participantId, UUID requestId) { - var participantInformation = acmParticipantProvider.getParticipantById(participantId); + public ResponseEntity getParticipant(UUID participantId, Integer page, Integer size, + UUID requestId) { + var pageable = getPageable(page, size); + var participantInformation = acmParticipantProvider.getParticipantById(participantId, pageable); return ResponseEntity.ok().body(participantInformation); } @@ -59,8 +61,9 @@ public class ParticipantController extends AbstractRestController implements Par @Override public ResponseEntity> queryParticipants(String name, String version, - UUID requestId) { - var participantInformationList = acmParticipantProvider.getAllParticipants(); + Integer page, Integer size, UUID requestId) { + var pageable = getPageable(page, size); + var participantInformationList = acmParticipantProvider.getAllParticipants(pageable); return ResponseEntity.ok().body(participantInformationList); } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/stub/ParticipantControllerStub.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/stub/ParticipantControllerStub.java index 78c566ce4..583f043a5 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/stub/ParticipantControllerStub.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/stub/ParticipantControllerStub.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation. + * Copyright (C) 2023,2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,7 +46,8 @@ public class ParticipantControllerStub extends AbstractRestController implements private String pathToParticipantList; @Override - public ResponseEntity getParticipant(UUID participantId, UUID xonaprequestid) { + public ResponseEntity getParticipant(UUID participantId, Integer page, Integer size, + UUID xonaprequestid) { return stubUtils.getResponse(pathToSingleParticipant, ParticipantInformation.class); } @@ -62,7 +63,7 @@ public class ParticipantControllerStub extends AbstractRestController implements @Override public ResponseEntity> queryParticipants(String name, String version, - UUID xonaprequestid) { + Integer page, Integer size, UUID xonaprequestid) { List participantInformationList = new ArrayList<>(); return (ResponseEntity>) stubUtils .getResponse(pathToParticipantList, participantInformationList.getClass()); diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/web/AbstractRestController.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/web/AbstractRestController.java index a1830125f..636f486d5 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/web/AbstractRestController.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/web/AbstractRestController.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2022 Nordix Foundation. + * Copyright (C) 2021-2022,2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,8 @@ import jakarta.ws.rs.core.Response; import java.net.URI; import java.net.URISyntaxException; import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.web.bind.annotation.RequestMapping; /** @@ -48,4 +50,8 @@ public abstract class AbstractRestController { throw new AutomationCompositionRuntimeException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()); } } + + protected Pageable getPageable(Integer page, Integer size) { + return page != null && size != null ? PageRequest.of(page, size) : Pageable.unpaged(); + } } 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 index 62ba7b017..a2e35d788 100644 --- 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 @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation. + * Copyright (C) 2023-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,20 +20,21 @@ package org.onap.policy.clamp.acm.runtime.participants; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.function.Function; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; -import org.apache.commons.collections4.MapUtils; import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantStatusReqPublisher; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; import org.onap.policy.clamp.models.acm.concepts.NodeTemplateState; +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.provider.ParticipantProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -49,39 +50,34 @@ public class AcmParticipantProvider { /** * Get all participants. * + * @param pageable the Pageable * @return A list of available participants */ - public List getAllParticipants() { + public List getAllParticipants(final Pageable pageable) { var participants = this.participantProvider.getParticipants(); + return participants.stream().map(participant -> createParticipantInformation(participant, pageable)).toList(); + } - List participantInformationList = new ArrayList<>(); - participants.forEach(participant -> { - ParticipantInformation participantInformation = new ParticipantInformation(); - participantInformation.setParticipant(participant); - participantInformation.setAcElementInstanceMap(getAutomationCompositionElementsForParticipant(participant - .getParticipantId())); - participantInformation.setAcNodeTemplateStateDefinitionMap(getNodeTemplateStatesForParticipant(participant - .getParticipantId())); - participantInformationList.add(participantInformation); - }); - return participantInformationList; + private ParticipantInformation createParticipantInformation(Participant participant, Pageable pageable) { + var participantInformation = new ParticipantInformation(); + participantInformation.setParticipant(participant); + participantInformation.setAcElementInstanceMap( + getAcElementsForParticipant(participant.getParticipantId(), pageable)); + participantInformation.setAcNodeTemplateStateDefinitionMap( + getNodeTemplateStatesForParticipant(participant.getParticipantId(), pageable)); + return participantInformation; } /** * Get a participant. * * @param participantId The UUID of the participant to get + * @param pageable the Pageable * @return The participant */ - public ParticipantInformation getParticipantById(UUID participantId) { + public ParticipantInformation getParticipantById(final UUID participantId, final Pageable pageable) { var participant = this.participantProvider.getParticipantById(participantId); - var participantInformation = new ParticipantInformation(); - participantInformation.setParticipant(participant); - - participantInformation.setAcElementInstanceMap(getAutomationCompositionElementsForParticipant(participantId)); - participantInformation.setAcNodeTemplateStateDefinitionMap(getNodeTemplateStatesForParticipant(participantId)); - - return participantInformation; + return createParticipantInformation(participant, pageable); } /** @@ -105,20 +101,16 @@ public class AcmParticipantProvider { this.participantStatusReqPublisher.send((UUID) null); } - private Map getAutomationCompositionElementsForParticipant(UUID participantId) { - var automationCompositionElements = participantProvider - .getAutomationCompositionElements(participantId); - Map map = new HashMap<>(); - MapUtils.populateMap(map, automationCompositionElements, AutomationCompositionElement::getId); - - return map; + private Map getAcElementsForParticipant(UUID participantId, Pageable pageable) { + var automationCompositionElements = + participantProvider.getAutomationCompositionElements(participantId, pageable); + return automationCompositionElements + .stream().collect(Collectors.toMap(AutomationCompositionElement::getId, Function.identity())); } - private Map getNodeTemplateStatesForParticipant(UUID participantId) { - var acNodeTemplateStates = participantProvider.getAcNodeTemplateStates(participantId); - Map map = new HashMap<>(); - MapUtils.populateMap(map, acNodeTemplateStates, NodeTemplateState::getNodeTemplateStateId); - - return map; + private Map getNodeTemplateStatesForParticipant(UUID participantId, Pageable pageable) { + var acNodeTemplateStates = participantProvider.getAcNodeTemplateStates(participantId, pageable); + return acNodeTemplateStates + .stream().collect(Collectors.toMap(NodeTemplateState::getNodeTemplateStateId, Function.identity())); } } diff --git a/runtime-acm/src/main/resources/openapi/openapi.yaml b/runtime-acm/src/main/resources/openapi/openapi.yaml index 7a5f04d09..fa8e8b2a1 100644 --- a/runtime-acm/src/main/resources/openapi/openapi.yaml +++ b/runtime-acm/src/main/resources/openapi/openapi.yaml @@ -62,6 +62,18 @@ paths: parameter is not specified, all automation composition definitions that match the "name" filter are are returned. schema: type: string + - name: page + in: query + required: false + description: Zero-based page number, must not be negative. + schema: + type: integer + - name: size + in: query + required: false + description: The size of the page to be returned, must be greater than 0. + schema: + type: integer - name: X-onap-RequestId in: header description: RequestID for http transaction @@ -233,6 +245,18 @@ paths: schema: type: string format: uuid + - name: page + in: query + required: false + description: Zero-based page number, must not be negative. + schema: + type: integer + - name: size + in: query + required: false + description: The size of the page to be returned, must be greater than 0. + schema: + type: integer - name: X-onap-RequestId in: header description: RequestID for http transaction 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 index ca3b9bfab..08f1ab891 100644 --- 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 @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation. + * Copyright (C) 2023-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ 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 static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVICE_TEMPLATE_YAML; import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.core.GenericType; @@ -36,15 +37,22 @@ 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.instantiation.AutomationCompositionInstantiationProvider; +import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils; import org.onap.policy.clamp.acm.runtime.main.rest.ParticipantController; +import org.onap.policy.clamp.acm.runtime.util.CommonTestData; import org.onap.policy.clamp.acm.runtime.util.rest.CommonRestController; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; +import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.Participant; import org.onap.policy.clamp.models.acm.concepts.ParticipantInformation; +import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; 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.tosca.authorative.concepts.ToscaServiceTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; @@ -61,6 +69,13 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; @ActiveProfiles({ "test", "default" }) class ParticipantControllerTest extends CommonRestController { private static final String PARTICIPANTS_ENDPOINT = "participants"; + private static final int NUMBER_RECORDS = 10; + + @Autowired + private AcDefinitionProvider acDefinitionProvider; + + @Autowired + private AutomationCompositionInstantiationProvider instantiationProvider; @LocalServerPort private int randomServerPort; @@ -68,7 +83,10 @@ class ParticipantControllerTest extends CommonRestController { 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 AC_INSTANTIATION_CREATE_JSON = "src/test/resources/rest/acm/AutomationComposition.json"; + private static final String NODE_TYPE = "org.onap.policy.clamp.acm.AutomationComposition"; + private static ToscaServiceTemplate serviceTemplate = new ToscaServiceTemplate(); + private static AutomationComposition automationComposition = new AutomationComposition(); private static final List inputParticipants = new ArrayList<>(); private static final String ORIGINAL_JSON = ResourceUtils.getResourceAsString(PARTICIPANT_JSON); private static final String ORIGINAL_JSON2 = ResourceUtils.getResourceAsString(PARTICIPANT_JSON2); @@ -83,6 +101,9 @@ class ParticipantControllerTest extends CommonRestController { public static void setUpBeforeClass() throws CoderException { inputParticipants.add(CODER.decode(ORIGINAL_JSON, Participant.class)); inputParticipants.add(CODER.decode(ORIGINAL_JSON2, Participant.class)); + serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); + automationComposition = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Query"); } @BeforeEach @@ -102,13 +123,42 @@ class ParticipantControllerTest extends CommonRestController { @Test void testQueryParticipant() { - participantProvider.saveParticipant(inputParticipants.get(0)); - var participantId = participantProvider.getParticipants().get(0).getParticipantId(); - var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT + "/" + participantId); + var participant = CommonTestData.createParticipant(CommonTestData.getParticipantId()); + var replica = CommonTestData.createParticipantReplica(CommonTestData.getParticipantId()); + participant.getReplicas().put(replica.getReplicaId(), replica); + participantProvider.saveParticipant(participant); + for (var i = 0; i < NUMBER_RECORDS; i++) { + createAcDefinitionInDB("QueryParticipant" + i); + } + // valid pagination + validateParticipantPageable("?page=1&size=4", 4); + + // not valid pagination + validateParticipantNotPageable("?page=0", NUMBER_RECORDS); + validateParticipantNotPageable("?size=5", NUMBER_RECORDS); + validateParticipantNotPageable("", NUMBER_RECORDS); + } + + private void validateParticipantPageable(String url, int size) { + var participantInfo = getParticipantInformation(url); + assertThat(participantInfo.getAcNodeTemplateStateDefinitionMap()).hasSize(size); + assertThat(participantInfo.getAcElementInstanceMap()).hasSize(size); + } + + private void validateParticipantNotPageable(String url, int size) { + var participantInfo = getParticipantInformation(url); + assertThat(participantInfo.getAcNodeTemplateStateDefinitionMap()).hasSizeGreaterThanOrEqualTo(size); + assertThat(participantInfo.getAcElementInstanceMap()).hasSizeGreaterThanOrEqualTo(size); + } + + private ParticipantInformation getParticipantInformation(String url) { + var invocationBuilder = super.sendRequest( + PARTICIPANTS_ENDPOINT + "/" + CommonTestData.getParticipantId() + url); try (var response = invocationBuilder.buildGet().invoke()) { assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); - var entityList = response.readEntity(ParticipantInformation.class); - assertNotNull(entityList); + var participantInfo = response.readEntity(ParticipantInformation.class); + assertNotNull(participantInfo); + return participantInfo; } } @@ -123,17 +173,75 @@ class ParticipantControllerTest extends CommonRestController { @Test void getAllParticipants() { - inputParticipants.forEach(p -> participantProvider.saveParticipant(p)); + inputParticipants.forEach(participantProvider::saveParticipant); var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT); try (var response = invocationBuilder.buildGet().invoke()) { assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); - List entityList = response.readEntity(new GenericType<>() {}); + List entityList = response.readEntity(new GenericType<>() { + }); assertThat(entityList).isNotEmpty(); var participantIds = entityList.stream().map(ParticipantInformation::getParticipant).map(Participant::getParticipantId) .collect(Collectors.toSet()); inputParticipants.forEach(p -> assertThat(participantIds).contains(p.getParticipantId())); } + var participant = CommonTestData.createParticipant(CommonTestData.getParticipantId()); + var replica = CommonTestData.createParticipantReplica(CommonTestData.getParticipantId()); + participant.getReplicas().put(replica.getReplicaId(), replica); + participantProvider.saveParticipant(participant); + for (var i = 0; i < NUMBER_RECORDS; i++) { + createAcDefinitionInDB("AllParticipants" + i); + } + // valid pagination + validateAllParticipantsPageable("?page=1&size=4", 4); + + // not valid pagination + validateAllParticipantsNotPageable("?page=0", NUMBER_RECORDS); + validateAllParticipantsNotPageable("?size=5", NUMBER_RECORDS); + validateAllParticipantsNotPageable("", NUMBER_RECORDS); + } + + private void validateAllParticipantsNotPageable(String url, int size) { + var participantInfo = getFirstParticipantInformation(url); + assertThat(participantInfo.getAcNodeTemplateStateDefinitionMap()).hasSizeGreaterThanOrEqualTo(size); + assertThat(participantInfo.getAcElementInstanceMap()).hasSizeGreaterThanOrEqualTo(size); + } + + private void validateAllParticipantsPageable(String url, int size) { + var participantInfo = getFirstParticipantInformation(url); + assertThat(participantInfo.getAcNodeTemplateStateDefinitionMap()).hasSize(size); + assertThat(participantInfo.getAcElementInstanceMap()).hasSize(size); + } + + private ParticipantInformation getFirstParticipantInformation(String url) { + var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT + url); + try (var response = invocationBuilder.buildGet().invoke()) { + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + List entityList = response.readEntity(new GenericType<>() {}); + var participantInfoOpt = entityList.stream() + .filter(p -> CommonTestData.getParticipantId().equals(p.getParticipant().getParticipantId())) + .findFirst(); + assertThat(participantInfoOpt).isPresent(); + return participantInfoOpt.get(); + } + } + + private void createAcDefinitionInDB(String name) { + var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate); + serviceTemplateCreate.setName(name); + var acmDefinition = CommonTestData.createAcDefinition(serviceTemplateCreate, AcTypeState.PRIMED); + acDefinitionProvider.updateAcDefinition(acmDefinition, NODE_TYPE); + var automationCompositionCreate = new AutomationComposition(automationComposition); + automationCompositionCreate.setCompositionId(acmDefinition.getCompositionId()); + automationCompositionCreate.setName(acmDefinition.getServiceTemplate().getName()); + var elements = new ArrayList<>(automationCompositionCreate.getElements().values()); + automationCompositionCreate.getElements().clear(); + for (var element : elements) { + element.setId(UUID.randomUUID()); + automationCompositionCreate.getElements().put(element.getId(), element); + } + instantiationProvider + .createAutomationComposition(acmDefinition.getCompositionId(), automationCompositionCreate); } @Test @@ -144,7 +252,7 @@ class ParticipantControllerTest extends CommonRestController { + "/" + participantId); try (var response = invocationBuilder.header("Content-Length", 0) - .put(Entity.entity("", MediaType.APPLICATION_JSON))) { + .put(Entity.entity("", MediaType.APPLICATION_JSON))) { assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatus()); } } @@ -155,19 +263,17 @@ class ParticipantControllerTest extends CommonRestController { + "/" + UUID.randomUUID()); try (var response = invocationBuilder.header("Content-Length", 0) - .put(Entity.entity("", MediaType.APPLICATION_JSON))) { + .put(Entity.entity("", MediaType.APPLICATION_JSON))) { assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus()); } } @Test void testOrderAllParticipantReport() { - inputParticipants.forEach(p -> { - participantProvider.saveParticipant(p); - }); + inputParticipants.forEach(participantProvider::saveParticipant); var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT); try (var response = invocationBuilder.header("Content-Length", 0) - .put(Entity.entity("", MediaType.APPLICATION_JSON))) { + .put(Entity.entity("", MediaType.APPLICATION_JSON))) { assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatus()); } } -- 2.16.6