diff --git a/monitor-server/src/main/java/org/gridsuite/monitor/server/controllers/ProcessConfigController.java b/monitor-server/src/main/java/org/gridsuite/monitor/server/controllers/ProcessConfigController.java index 2236c41..d6af176 100644 --- a/monitor-server/src/main/java/org/gridsuite/monitor/server/controllers/ProcessConfigController.java +++ b/monitor-server/src/main/java/org/gridsuite/monitor/server/controllers/ProcessConfigController.java @@ -11,6 +11,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import org.gridsuite.monitor.server.dto.processconfig.MetadataInfos; import org.gridsuite.monitor.server.dto.processconfig.PersistedProcessConfig; import org.gridsuite.monitor.commons.types.processconfig.ProcessConfig; import org.gridsuite.monitor.commons.types.processexecution.ProcessType; @@ -67,6 +68,15 @@ public ResponseEntity getProcessConfig( return processConfig.map(config -> ResponseEntity.ok().body(config)).orElseGet(() -> ResponseEntity.notFound().build()); } + @GetMapping(value = "/metadata", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Get process configs metadata") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "process configs metadata were returned")}) + public ResponseEntity> getProcessConfigsMetadata(@RequestParam("ids") List processConfigIds) { + List processConfigs = processConfigService.getProcessConfigsMetadata(processConfigIds); + return ResponseEntity.ok().body(processConfigs); + } + @PutMapping(value = "/{uuid}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Update process config") @ApiResponses(value = { @@ -80,6 +90,19 @@ public ResponseEntity updateProcessConfig( ResponseEntity.notFound().build(); } + @PostMapping(value = "/duplication", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Duplicate a process config") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "process config was duplicated"), + @ApiResponse(responseCode = "404", description = "process config to duplicate was not found")}) + public ResponseEntity duplicateProcessConfig( + @Parameter(description = "UUID of the process config to duplicate") @RequestParam("duplicateFrom") UUID sourceProcessConfigUuid) { + Optional newProcessConfigUuid = processConfigService.duplicateProcessConfig(sourceProcessConfigUuid); + return newProcessConfigUuid + .map(configUuid -> ResponseEntity.ok().body(configUuid)) + .orElseGet(() -> ResponseEntity.notFound().build()); + } + @DeleteMapping(value = "/{uuid}", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Delete process config") @ApiResponses(value = { diff --git a/monitor-server/src/main/java/org/gridsuite/monitor/server/dto/processconfig/MetadataInfos.java b/monitor-server/src/main/java/org/gridsuite/monitor/server/dto/processconfig/MetadataInfos.java new file mode 100644 index 0000000..c3ff986 --- /dev/null +++ b/monitor-server/src/main/java/org/gridsuite/monitor/server/dto/processconfig/MetadataInfos.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2026, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.monitor.server.dto.processconfig; + +import org.gridsuite.monitor.commons.types.processexecution.ProcessType; + +import java.util.UUID; + +/** + * @author Caroline Jeandat {@literal } + */ +public record MetadataInfos( + UUID id, + ProcessType type +) { +} diff --git a/monitor-server/src/main/java/org/gridsuite/monitor/server/services/processconfig/ProcessConfigService.java b/monitor-server/src/main/java/org/gridsuite/monitor/server/services/processconfig/ProcessConfigService.java index ff4608b..1f43a16 100644 --- a/monitor-server/src/main/java/org/gridsuite/monitor/server/services/processconfig/ProcessConfigService.java +++ b/monitor-server/src/main/java/org/gridsuite/monitor/server/services/processconfig/ProcessConfigService.java @@ -9,6 +9,7 @@ import org.gridsuite.monitor.commons.types.processconfig.ProcessConfig; import org.gridsuite.monitor.commons.types.processconfig.SecurityAnalysisConfig; import org.gridsuite.monitor.commons.types.processexecution.ProcessType; +import org.gridsuite.monitor.server.dto.processconfig.MetadataInfos; import org.gridsuite.monitor.server.dto.processconfig.ProcessConfigComparison; import org.gridsuite.monitor.server.dto.processconfig.ProcessConfigFieldComparison; import org.gridsuite.monitor.server.dto.processconfig.PersistedProcessConfig; @@ -36,6 +37,10 @@ public ProcessConfigService(ProcessConfigRepository processConfigRepository, Sec @Transactional public UUID createProcessConfig(ProcessConfig processConfig) { + return doCreateProcessConfig(processConfig); + } + + private UUID doCreateProcessConfig(ProcessConfig processConfig) { switch (processConfig) { case SecurityAnalysisConfig sac -> { return processConfigRepository.save(securityAnalysisConfigMapper.toEntity(sac)).getId(); @@ -49,6 +54,13 @@ public Optional getProcessConfig(UUID processConfigUuid) return processConfigRepository.findById(processConfigUuid).map(this::toPersistedProcessConfig); } + @Transactional(readOnly = true) + public List getProcessConfigsMetadata(List processConfigUuids) { + return processConfigRepository.findAllById(processConfigUuids).stream() + .map(entity -> new MetadataInfos(entity.getId(), entity.getProcessType())) + .toList(); + } + @Transactional public boolean updateProcessConfig(UUID processConfigUuid, ProcessConfig processConfig) { return processConfigRepository.findById(processConfigUuid) @@ -66,6 +78,12 @@ public boolean updateProcessConfig(UUID processConfigUuid, ProcessConfig process .orElse(false); } + @Transactional + public Optional duplicateProcessConfig(UUID sourceProcessConfigUuid) { + return processConfigRepository.findById(sourceProcessConfigUuid) + .map(sourceEntity -> doCreateProcessConfig(toProcessConfig(sourceEntity))); + } + @Transactional public boolean deleteProcessConfig(UUID processConfigUuid) { if (processConfigRepository.existsById(processConfigUuid)) { diff --git a/monitor-server/src/test/java/org/gridsuite/monitor/server/controllers/ProcessConfigControllerTest.java b/monitor-server/src/test/java/org/gridsuite/monitor/server/controllers/ProcessConfigControllerTest.java index 2d5e0f0..f33196e 100644 --- a/monitor-server/src/test/java/org/gridsuite/monitor/server/controllers/ProcessConfigControllerTest.java +++ b/monitor-server/src/test/java/org/gridsuite/monitor/server/controllers/ProcessConfigControllerTest.java @@ -7,6 +7,7 @@ package org.gridsuite.monitor.server.controllers; import com.fasterxml.jackson.databind.ObjectMapper; +import org.gridsuite.monitor.server.dto.processconfig.MetadataInfos; import org.gridsuite.monitor.server.dto.processconfig.PersistedProcessConfig; import org.gridsuite.monitor.commons.types.processconfig.ProcessConfig; import org.gridsuite.monitor.commons.types.processconfig.SecurityAnalysisConfig; @@ -110,6 +111,28 @@ void getSecurityAnalysisConfigNotFound() throws Exception { verify(processConfigService).getProcessConfig(any(UUID.class)); } + @Test + void getSecurityAnalysisConfigsMetadata() throws Exception { + UUID processConfigId1 = UUID.randomUUID(); + UUID processConfigId2 = UUID.randomUUID(); + + List expectedMetadata = List.of( + new MetadataInfos(processConfigId1, ProcessType.SECURITY_ANALYSIS), + new MetadataInfos(processConfigId2, ProcessType.SECURITY_ANALYSIS) + ); + + when(processConfigService.getProcessConfigsMetadata(List.of(processConfigId1, processConfigId2))) + .thenReturn(expectedMetadata); + + mockMvc.perform(get("/v1/process-configs/metadata") + .param("ids", processConfigId1.toString(), processConfigId2.toString())) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(content().json(objectMapper.writeValueAsString(expectedMetadata))); + + verify(processConfigService).getProcessConfigsMetadata(List.of(processConfigId1, processConfigId2)); + } + @Test void updateSecurityAnalysisConfig() throws Exception { UUID processConfigId = UUID.randomUUID(); @@ -150,6 +173,35 @@ void updateSecurityAnalysisConfigNotFound() throws Exception { verify(processConfigService).updateProcessConfig(any(UUID.class), any(ProcessConfig.class)); } + @Test + void duplicateProcessConfig() throws Exception { + UUID processConfigId = UUID.randomUUID(); + UUID newProcessConfigId = UUID.randomUUID(); + + when(processConfigService.duplicateProcessConfig(processConfigId)) + .thenReturn(Optional.of(newProcessConfigId)); + + mockMvc.perform(post("/v1/process-configs/duplication?duplicateFrom={uuid}", processConfigId)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(jsonPath("$").value(newProcessConfigId.toString())); + + verify(processConfigService).duplicateProcessConfig(processConfigId); + } + + @Test + void duplicateProcessConfigNotFound() throws Exception { + UUID processConfigId = UUID.randomUUID(); + + when(processConfigService.duplicateProcessConfig(processConfigId)) + .thenReturn(Optional.empty()); + + mockMvc.perform(post("/v1/process-configs/duplication?duplicateFrom={uuid}", processConfigId)) + .andExpect(status().isNotFound()); + + verify(processConfigService).duplicateProcessConfig(processConfigId); + } + @Test void deleteSecurityAnalysisConfig() throws Exception { UUID processConfigId = UUID.randomUUID(); diff --git a/monitor-server/src/test/java/org/gridsuite/monitor/server/services/processconfig/ProcessConfigServiceTest.java b/monitor-server/src/test/java/org/gridsuite/monitor/server/services/processconfig/ProcessConfigServiceTest.java index 1ce851b..cf6ac9d 100644 --- a/monitor-server/src/test/java/org/gridsuite/monitor/server/services/processconfig/ProcessConfigServiceTest.java +++ b/monitor-server/src/test/java/org/gridsuite/monitor/server/services/processconfig/ProcessConfigServiceTest.java @@ -6,6 +6,7 @@ */ package org.gridsuite.monitor.server.services.processconfig; +import org.gridsuite.monitor.server.dto.processconfig.MetadataInfos; import org.gridsuite.monitor.server.dto.processconfig.PersistedProcessConfig; import org.gridsuite.monitor.commons.types.processconfig.SecurityAnalysisConfig; import org.gridsuite.monitor.commons.types.processexecution.ProcessType; @@ -104,6 +105,28 @@ void getSecurityAnalysisConfigNotFound() { assertThat(processConfig).isEmpty(); } + @Test + void getProcessConfigsMetadata() { + UUID processConfigId1 = UUID.randomUUID(); + UUID processConfigId2 = UUID.randomUUID(); + + SecurityAnalysisConfigEntity entity1 = securityAnalysisConfigMapper.toEntity(securityAnalysisConfig); + entity1.setId(processConfigId1); + SecurityAnalysisConfigEntity entity2 = securityAnalysisConfigMapper.toEntity(securityAnalysisConfig); + entity2.setId(processConfigId2); + + when(processConfigRepository.findAllById(List.of(processConfigId1, processConfigId2))) + .thenReturn(List.of(entity1, entity2)); + + List metadataInfos = processConfigService.getProcessConfigsMetadata(List.of(processConfigId1, processConfigId2)); + + verify(processConfigRepository).findAllById(List.of(processConfigId1, processConfigId2)); + assertThat(metadataInfos).isEqualTo(List.of( + new MetadataInfos(processConfigId1, ProcessType.SECURITY_ANALYSIS), + new MetadataInfos(processConfigId2, ProcessType.SECURITY_ANALYSIS) + )); + } + @Test void updateSecurityAnalysisConfig() { UUID processConfigId = UUID.randomUUID(); @@ -144,6 +167,41 @@ void updateSecurityAnalysisConfigNotFound() { verify(processConfigRepository).findById(processConfigId); } + @Test + void duplicateSecurityAnalysisConfig() { + UUID processConfigId = UUID.randomUUID(); + UUID expectedNewProcessConfigId = UUID.randomUUID(); + + when(processConfigRepository.findById(processConfigId)) + .thenReturn(Optional.of(mock(SecurityAnalysisConfigEntity.class))); + when(processConfigRepository.save(any(SecurityAnalysisConfigEntity.class))) + .thenAnswer(invocation -> { + SecurityAnalysisConfigEntity entity = invocation.getArgument(0); + entity.setId(expectedNewProcessConfigId); + return entity; + }); + + Optional newProcessConfigId = processConfigService.duplicateProcessConfig(processConfigId); + + assertThat(newProcessConfigId).isPresent(); + assertThat(newProcessConfigId.get()).isEqualTo(expectedNewProcessConfigId); + + verify(processConfigRepository).findById(processConfigId); + ArgumentCaptor captor = ArgumentCaptor.forClass(SecurityAnalysisConfigEntity.class); + verify(processConfigRepository).save(captor.capture()); + } + + @Test + void duplicateSecurityAnalysisConfigNotFound() { + UUID processConfigId = UUID.randomUUID(); + + when(processConfigRepository.findById(processConfigId)).thenReturn(Optional.empty()); + + Optional newProcessConfigId = processConfigService.duplicateProcessConfig(processConfigId); + assertThat(newProcessConfigId).isEmpty(); + verify(processConfigRepository).findById(processConfigId); + } + @Test void deleteSecurityAnalysisConfig() { UUID processConfigId = UUID.randomUUID();