Skip to content

Commit 97311f5

Browse files
authored
Feat: Manage Map Card save in layout (#816)
* feat(DiagramGridLayout): Manage Map Card save in layout and add a control over the number of Map Card in the grid Signed-off-by: sBouzols <[email protected]>
1 parent e559467 commit 97311f5

File tree

6 files changed

+108
-5
lines changed

6 files changed

+108
-5
lines changed

src/main/java/org/gridsuite/study/server/RestResponseEntityExceptionHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ protected ResponseEntity<Object> handleStudyException(StudyException exception)
7070
ROOT_NETWORK_DELETE_FORBIDDEN,
7171
MAXIMUM_ROOT_NETWORK_BY_STUDY_REACHED,
7272
MAXIMUM_TAG_LENGTH_EXCEEDED,
73-
TOO_MANY_NAD_CONFIGS
73+
TOO_MANY_NAD_CONFIGS,
74+
TOO_MANY_MAP_CARDS
7475
-> ResponseEntity.status(HttpStatus.FORBIDDEN).body(exception.getMessage());
7576
case CANT_DELETE_ROOT_NODE -> ResponseEntity.status(HttpStatus.FORBIDDEN).body(NOT_ALLOWED);
7677
case CREATE_NETWORK_MODIFICATION_FAILED,

src/main/java/org/gridsuite/study/server/StudyException.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ public enum Type {
156156
UPDATE_SPREADSHEET_CONFIG_FAILED,
157157
NETWORK_EXPORT_FAILED,
158158
GET_LOADFLOW_PROVIDER_FAILED,
159-
TOO_MANY_NAD_CONFIGS
159+
TOO_MANY_NAD_CONFIGS,
160+
TOO_MANY_MAP_CARDS
160161
}
161162

162163
private final Type type;

src/main/java/org/gridsuite/study/server/dto/diagramgridlayout/diagramlayout/AbstractDiagramLayoutJsonMapper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
@JsonSubTypes.Type(value = NetworkAreaDiagramLayout.class, name = "network-area-diagram"),
2222
@JsonSubTypes.Type(value = SubstationDiagramLayout.class, name = "substation"),
2323
@JsonSubTypes.Type(value = VoltageLevelDiagramLayout.class, name = "voltage-level"),
24+
@JsonSubTypes.Type(value = MapLayout.class, name = "map"),
2425
})
2526
public interface AbstractDiagramLayoutJsonMapper {
2627
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout;
8+
9+
import lombok.Getter;
10+
import lombok.NoArgsConstructor;
11+
import lombok.Setter;
12+
import lombok.experimental.SuperBuilder;
13+
14+
@SuperBuilder
15+
@NoArgsConstructor
16+
@Setter
17+
@Getter
18+
public class MapLayout extends AbstractDiagramLayout {
19+
}

src/main/java/org/gridsuite/study/server/service/DiagramGridLayoutService.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.gridsuite.study.server.StudyException;
1111
import org.gridsuite.study.server.dto.diagramgridlayout.DiagramGridLayout;
1212
import org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout.AbstractDiagramLayout;
13+
import org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout.MapLayout;
1314
import org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout.NetworkAreaDiagramLayout;
1415
import org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout.NetworkAreaDiagramLayoutDetails;
1516
import org.gridsuite.study.server.dto.diagramgridlayout.nad.NadConfigInfos;
@@ -30,7 +31,8 @@
3031
public class DiagramGridLayoutService {
3132

3233
private static final Logger LOGGER = LoggerFactory.getLogger(DiagramGridLayoutService.class);
33-
private static final int MAX_NAD_CONFIGS_ALLOWED = 3;
34+
public static final int MAX_NAD_CONFIGS_ALLOWED = 3;
35+
public static final int MAX_MAP_CARDS_ALLOWED = 1;
3436

3537
private final StudyConfigService studyConfigService;
3638
private final SingleLineDiagramService singleLineDiagramService;
@@ -47,6 +49,9 @@ public UUID createDiagramGridLayout(DiagramGridLayout diagramGridLayout) {
4749
// Validate NAD config count before processing
4850
validateNadConfigCount(diagramGridLayout);
4951

52+
// Validate map card count
53+
validateMapCardCount(diagramGridLayout);
54+
5055
// Process diagram layout and handle NAD layout details
5156
DiagramGridLayout processedDiagramLayout = processNADLayoutDetails(diagramGridLayout);
5257
return studyConfigService.saveDiagramGridLayout(processedDiagramLayout);
@@ -59,6 +64,9 @@ public UUID updateDiagramGridLayout(UUID existingDiagramGridLayoutUuid, DiagramG
5964
// Validate NAD config count before processing
6065
validateNadConfigCount(diagramGridLayout);
6166

67+
// Validate map card count
68+
validateMapCardCount(diagramGridLayout);
69+
6270
List<UUID> oldNadConfigUuidsToDelete = collectOldNadConfigUuids(existingDiagramGridLayoutUuid);
6371

6472
// Process diagram layout and handle NAD layout details
@@ -134,6 +142,22 @@ private void cleanupOldNadConfigs(List<UUID> oldNadConfigUuidsToDelete) {
134142
}
135143
}
136144

145+
/**
146+
* Validates that the diagram grid layout does not contain more than one map card.
147+
*/
148+
private void validateMapCardCount(DiagramGridLayout diagramGridLayout) {
149+
if (diagramGridLayout != null && diagramGridLayout.getDiagramLayouts() != null) {
150+
long mapCardsCount = diagramGridLayout.getDiagramLayouts().stream()
151+
.filter(MapLayout.class::isInstance)
152+
.count();
153+
154+
if (mapCardsCount > MAX_MAP_CARDS_ALLOWED) {
155+
throw new StudyException(StudyException.Type.TOO_MANY_MAP_CARDS,
156+
"Maximum " + MAX_MAP_CARDS_ALLOWED + " map card allowed, but " + mapCardsCount + " provided");
157+
}
158+
}
159+
}
160+
137161
/**
138162
* Validates that the diagram grid layout does not exceed the maximum allowed NAD configurations.
139163
*/

src/test/java/org/gridsuite/study/server/DiagramGridLayoutTest.java

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
import org.junit.jupiter.api.BeforeEach;
1212
import org.junit.jupiter.api.Test;
1313
import org.gridsuite.study.server.dto.diagramgridlayout.DiagramGridLayout;
14+
import org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout.AbstractDiagramLayout;
1415
import org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout.DiagramPosition;
16+
import org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout.MapLayout;
1517
import org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout.NadVoltageLevelPositionInfos;
1618
import org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout.NetworkAreaDiagramLayoutDetails;
1719
import org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout.NetworkAreaDiagramLayout;
@@ -592,9 +594,9 @@ void testUpdateDiagramGridLayoutWithTooManyNads() throws Exception {
592594
UUID existingDiagramGridLayoutUuid = UUID.randomUUID();
593595
studyRepository.save(StudyEntity.builder().id(studyUuid).diagramGridLayoutUuid(existingDiagramGridLayoutUuid).build());
594596

595-
// Create 4 NAD layout details (exceeds the limit of 3)
597+
// Create more than MAX_NAD_CONFIGS_ALLOWED NAD layout details
596598
List<NetworkAreaDiagramLayoutDetails> nadLayouts = new ArrayList<>();
597-
for (int i = 0; i < 4; i++) {
599+
for (int i = 0; i < DiagramGridLayoutService.MAX_NAD_CONFIGS_ALLOWED + 1; i++) {
598600
nadLayouts.add(NetworkAreaDiagramLayoutDetails.builder()
599601
.diagramUuid(UUID.randomUUID())
600602
.voltageLevelIds(Set.of("VL" + i))
@@ -626,4 +628,59 @@ void testUpdateDiagramGridLayoutWithTooManyNads() throws Exception {
626628
wireMockServer.verify(0, WireMock.putRequestedFor(WireMock.urlMatching(".*")));
627629
}
628630

631+
@Test
632+
void testCreateDiagramGridLayoutWithTooManyMapCards() throws Exception {
633+
UUID studyUuid = UUID.randomUUID();
634+
studyRepository.save(StudyEntity.builder().id(studyUuid).build());
635+
636+
// Create more than MAX_MAP_CARDS_ALLOWED Map Cards
637+
List<AbstractDiagramLayout> mapLayouts = new ArrayList<>();
638+
for (int i = 0; i < DiagramGridLayoutService.MAX_MAP_CARDS_ALLOWED + 1; i++) {
639+
mapLayouts.add(MapLayout.builder().diagramUuid(UUID.randomUUID()).build());
640+
}
641+
642+
DiagramGridLayout diagramGridLayoutWithTooMuchMapCards = DiagramGridLayout.builder().diagramLayouts(mapLayouts).build();
643+
644+
String payload = objectMapper.writeValueAsString(diagramGridLayoutWithTooMuchMapCards);
645+
646+
// Should return forbidden due to too many Map Cards
647+
mockMvc.perform(post("/v1/studies/{studyUuid}/diagram-grid-layout", studyUuid)
648+
.contentType(MediaType.APPLICATION_JSON)
649+
.content(payload))
650+
.andExpect(status().isForbidden());
651+
652+
// Verify no external services were called since validation failed early
653+
wireMockServer.verify(0, WireMock.postRequestedFor(WireMock.urlMatching(".*")));
654+
}
655+
656+
@Test
657+
void testUpdateDiagramGridLayoutWithTooManyMapCards() throws Exception {
658+
UUID studyUuid = UUID.randomUUID();
659+
UUID existingDiagramGridLayoutUuid = UUID.randomUUID();
660+
studyRepository.save(StudyEntity.builder().id(studyUuid).diagramGridLayoutUuid(existingDiagramGridLayoutUuid).build());
661+
662+
// Create more than MAX_MAP_CARDS_ALLOWED Map Cards
663+
List<AbstractDiagramLayout> mapLayouts = new ArrayList<>();
664+
for (int i = 0; i < DiagramGridLayoutService.MAX_MAP_CARDS_ALLOWED + 1; i++) {
665+
mapLayouts.add(MapLayout.builder().diagramUuid(UUID.randomUUID()).build());
666+
}
667+
668+
DiagramGridLayout updatePayload = DiagramGridLayout.builder()
669+
.diagramLayouts(new ArrayList<>(mapLayouts))
670+
.build();
671+
672+
String payload = objectMapper.writeValueAsString(updatePayload);
673+
674+
// Should return forbidden due to too many Map Cards
675+
mockMvc.perform(post("/v1/studies/{studyUuid}/diagram-grid-layout", studyUuid)
676+
.contentType(MediaType.APPLICATION_JSON)
677+
.content(payload))
678+
.andExpect(status().isForbidden());
679+
680+
// Verify no external services were called since validation failed early
681+
wireMockServer.verify(0, WireMock.getRequestedFor(WireMock.urlMatching(".*")));
682+
wireMockServer.verify(0, WireMock.postRequestedFor(WireMock.urlMatching(".*")));
683+
wireMockServer.verify(0, WireMock.putRequestedFor(WireMock.urlMatching(".*")));
684+
}
685+
629686
}

0 commit comments

Comments
 (0)