Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
a2ba643
Use the modification applicability per root network tag
flomillot Aug 7, 2026
0d58468
Merge remote-tracking branch 'origin/main' into florent/GRD-4941-modi…
flomillot Aug 10, 2026
44a8817
Rename the root network applicability query parameter to applicable
flomillot Aug 10, 2026
a5e1c49
Rename the root network applicability parameter to applicable
flomillot Aug 11, 2026
62e3fe0
Merge remote-tracking branch 'origin/main' into florent/GRD-4941-modi…
flomillot Aug 12, 2026
ed85ed2
Clear the sonar smells on the root network applicability test
flomillot Aug 13, 2026
731e38c
Drop the network modification applicability endpoint
flomillot Aug 21, 2026
7bf6e62
Merge remote-tracking branch 'origin/main' into florent/GRD-4941-modi…
flomillot Aug 21, 2026
f4ccd09
Stop returning the duplicated modifications mapping
flomillot Aug 21, 2026
8d03932
Keep the applicabilities when a root network tag changes
flomillot Aug 25, 2026
86d0396
Merge branch 'main' into florent/GRD-4941-modification-applicability
flomillot Aug 25, 2026
05694ef
Build again after the merge of main
flomillot Aug 25, 2026
382a118
Merge remote-tracking branch 'origin/main' into florent/GRD-4941-modi…
flomillot Aug 27, 2026
db0c6fa
Merge remote-tracking branch 'origin/main' into florent/GRD-4941-modi…
flomillot Aug 27, 2026
77724c7
refactor: remove unused getAllWithRootNetworkByNodeInfoId method
flomillot Aug 28, 2026
0d5c480
Cover the root network tag calls and the rights check on a shared mod…
flomillot Sep 2, 2026
275c91b
Merge remote-tracking branch 'origin/main' into florent/GRD-4941-modi…
flomillot Sep 2, 2026
16cf002
Merge remote-tracking branch 'origin/main' into florent/GRD-4941-modi…
flomillot Sep 3, 2026
129768a
Clear the sonar remarks the applicability changes raised
flomillot Sep 4, 2026
8c12afd
Merge remote-tracking branch 'origin/main' into florent/GRD-4941-modi…
flomillot Sep 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ private StudyConstants() {
public static final String HEADER_ERROR_MESSAGE = "x-exception-message";
public static final String QUERY_PARAM_ONLY_STASHED = "onlyStashed";
public static final String QUERY_PARAM_STASHED = "stashed";
public static final String QUERY_PARAM_ACTIVATED = "activated";
public static final String QUERY_PARAM_APPLICABLE = "applicable";
public static final String QUERY_PARAM_DESCRIPTION = "description";
public static final String PATH_PARAM_PARAMETERS = "parameters";
public static final String DYNA_FLOW_PROVIDER = "DynaFlow";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ public ResponseEntity<Void> moveOrCopyModifications(@PathVariable("studyUuid") U
List<UUID> modificationsToCopyUuidList = modificationInfos.stream().map(ModificationMoveOrCopyInfos::modificationUuid).toList();
switch (action) {
case COPY:
handleDuplicateNetworkModifications(studyUuid, nodeUuid, originNodeUuid, modificationsToCopyUuidList, userId);
handleDuplicateNetworkModifications(studyUuid, nodeUuid, modificationsToCopyUuidList, userId);
break;
case MOVE:
// we don't cut - paste modifications from different studies
Expand Down Expand Up @@ -746,9 +746,9 @@ private void handleInsertCompositeNetworkModifications(
() -> studyService.insertCompositeNetworkModifications(targetStudyUuid, targetNodeUuid, compositeInfos, userId, action));
}

private void handleDuplicateNetworkModifications(UUID targetStudyUuid, UUID targetNodeUuid, UUID originNodeUuid, List<UUID> modificationsToCopyUuidList, String userId) {
private void handleDuplicateNetworkModifications(UUID targetStudyUuid, UUID targetNodeUuid, List<UUID> modificationsToCopyUuidList, String userId) {
nodeActivityRunnerService.runWith(EDIT_MODIFICATIONS, targetStudyUuid, List.of(targetNodeUuid),
() -> studyService.duplicateNetworkModifications(targetStudyUuid, targetNodeUuid, originNodeUuid, modificationsToCopyUuidList, userId));
() -> studyService.duplicateNetworkModifications(targetStudyUuid, targetNodeUuid, modificationsToCopyUuidList, userId));
}

@GetMapping(value = "/export-network-formats")
Expand Down Expand Up @@ -979,17 +979,6 @@ public ResponseEntity<String> getExportedNetworkModifications(@Parameter(descrip
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(studyService.getExportedNetworkModifications(studyUuid, nodeUuid));
}

@GetMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/excluded-network-modifications", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Get excluded network modifications from a node")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The excluded network modifications were returned"), @ApiResponse(responseCode = "404",
description = "The study/node is not found")})
public ResponseEntity<List<ExcludedNetworkModifications>> getNetworkModificationsToExclude(@Parameter(description = "Study UUID") @PathVariable("studyUuid") UUID studyUuid,
@Parameter(description = "Node UUID") @PathVariable("nodeUuid") UUID nodeUuid) {

studyService.assertIsStudyAndNodeExist(studyUuid, nodeUuid);
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(networkModificationTreeService.getModificationsToExclude(nodeUuid));
}

@PostMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/network-modifications")
@Operation(summary = "Create a network modification for a node")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The network modification was created"), @ApiResponse(responseCode = "404", description = "The study/node is not found")})
Expand Down Expand Up @@ -1060,18 +1049,18 @@ public ResponseEntity<Void> updateNetworkModificationsMetadata(@Parameter(descri
return ResponseEntity.ok().build();
}

@PutMapping(value = "/studies/{studyUuid}/root-networks/{rootNetworkUuid}/nodes/{nodeUuid}/network-modifications", params = "activated")
@Operation(summary = "Update 'activated' value for a network modifications for a node in a specific root network")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Update the activation status for network modifications on a node in a specific root network"),
@PutMapping(value = "/studies/{studyUuid}/root-networks/{rootNetworkUuid}/nodes/{nodeUuid}/network-modifications", params = "applicable")
@Operation(summary = "Update the applicability of network modifications for a node on a specific root network")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Update the applicability of network modifications on a node in a specific root network"),
@ApiResponse(responseCode = "404", description = "The study/root network/node is not found")})
public ResponseEntity<Void> updateNetworkModificationsActivation(@Parameter(description = "Study UUID") @PathVariable("studyUuid") UUID studyUuid,
public ResponseEntity<Void> updateNetworkModificationsApplicability(@Parameter(description = "Study UUID") @PathVariable("studyUuid") UUID studyUuid,
@Parameter(description = "Root network UUID") @PathVariable("rootNetworkUuid") UUID rootNetworkUuid,
@Parameter(description = "Node UUID") @PathVariable("nodeUuid") UUID nodeUuid,
@Parameter(description = "Network modification UUIDs") @RequestParam("uuids") Set<UUID> networkModificationUuids,
@Parameter(description = "New activated value") @RequestParam(name = "activated") Boolean activated,
@Parameter(description = "New applicability value") @RequestParam(name = "applicable") Boolean applicable,
@RequestHeader(HEADER_USER_ID) String userId) {
studyService.assertIsNodeNotReadOnly(nodeUuid);
rebuildNodeService.updateNetworkModificationsActivation(studyUuid, nodeUuid, rootNetworkUuid, networkModificationUuids, userId, activated);
rebuildNodeService.updateNetworkModificationsApplicability(studyUuid, nodeUuid, rootNetworkUuid, networkModificationUuids, userId, applicable);
return ResponseEntity.ok().build();
}

Expand Down
9 changes: 3 additions & 6 deletions src/main/java/org/gridsuite/study/server/dto/BuildInfos.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public class BuildInfos {

private List<UUID> modificationGroupUuids = new ArrayList<>();

// map with modification groups as key, modification to excludes as value
private Map<UUID, Set<UUID>> modificationUuidsToExclude = new HashMap<>();
// tag of the root network being built, used to resolve the applicability of each modification
private String rootNetworkTag;

/**
* Reports generated during this build operation.
Expand All @@ -43,10 +43,7 @@ public class BuildInfos {
*/
private List<ReportInfos> inheritedReportsInfos = new ArrayList<>();

public void insertModificationInfos(UUID modificationGroupUuid, Set<UUID> modificationUuidsToExclude, ReportInfos reportInfos) {
if (modificationUuidsToExclude != null && !modificationUuidsToExclude.isEmpty()) {
this.modificationUuidsToExclude.put(modificationGroupUuid, modificationUuidsToExclude);
}
public void insertModificationInfos(UUID modificationGroupUuid, ReportInfos reportInfos) {
modificationGroupUuids.add(0, modificationGroupUuid);
reportsInfos.add(0, reportInfos);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/
package org.gridsuite.study.server.dto.modification;

import java.util.Set;
import java.util.UUID;

public record ModificationApplicationContext(UUID networkUuid, String variantId, UUID reportUuid, UUID reporterId, Set<UUID> excludedModifications) { }
public record ModificationApplicationContext(UUID networkUuid, String variantId, UUID reportUuid, UUID reporterId, String rootNetworkTag) { }

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
import org.gridsuite.study.server.dto.RootNetworkNodeInfo;
import org.gridsuite.study.server.repository.rootnetwork.RootNetworkEntity;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

/**
Expand Down Expand Up @@ -115,13 +113,6 @@ public class RootNetworkNodeInfoEntity {
})
private NodeBuildStatusEmbeddable nodeBuildStatus;

@ElementCollection
@CollectionTable(name = "RootNetworkNodeInfoModificationsToExclude",
joinColumns = @JoinColumn(name = "root_network_node_info_id"),
indexes = {@Index(name = "root_network_node_info_entity_modificationsUuidsToExclude_idx1", columnList = "root_network_node_info_id")},
foreignKey = @ForeignKey(name = "root_network_node_info_entity_modificationsUuidsToExclude_fk1"))
private Set<UUID> modificationsUuidsToExclude = new HashSet<>();

public RootNetworkNodeInfo toDto() {
return RootNetworkNodeInfo.builder()
.id(id)
Expand All @@ -144,12 +135,4 @@ public RootNetworkNodeInfo toDto() {
.variantId(variantId)
.build();
}

public void addModificationsToExclude(Set<UUID> uuids) {
modificationsUuidsToExclude.addAll(uuids);
}

public void removeModificationsFromExclude(Set<UUID> uuids) {
modificationsUuidsToExclude.removeAll(uuids);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ public interface RootNetworkNodeInfoRepository extends JpaRepository<RootNetwork

Optional<RootNetworkNodeInfoEntity> findByNodeInfoIdAndRootNetworkId(UUID nodeInfoId, UUID rootNetworkUuid);

@EntityGraph(attributePaths = {"modificationsUuidsToExclude"}, type = EntityGraph.EntityGraphType.LOAD)
Optional<RootNetworkNodeInfoEntity> findWithModificationsToExcludeByNodeInfoIdAndRootNetworkId(UUID nodeInfoId, UUID rootNetworkUuid);
@EntityGraph(attributePaths = {"rootNetwork"}, type = EntityGraph.EntityGraphType.LOAD)
Optional<RootNetworkNodeInfoEntity> findWithRootNetworkByNodeInfoIdAndRootNetworkId(UUID nodeInfoId, UUID rootNetworkUuid);

List<RootNetworkNodeInfoEntity> findAllByRootNetworkStudyId(UUID studyUuid);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.NonNull;
import org.apache.commons.collections4.CollectionUtils;
import org.gridsuite.study.server.RemoteServicesProperties;
import org.gridsuite.study.server.StudyConstants;
import org.gridsuite.study.server.dto.BuildInfos;
Expand Down Expand Up @@ -52,6 +53,10 @@ public class NetworkModificationService {
private static final String QUERY_PARAM_ACTION = "action";
private static final String QUERY_PARAM_NAME = "name";
private static final String QUERY_PARAM_GROUP_UUID = "groupUuid";
private static final String QUERY_PARAM_ROOT_NETWORK_TAG = "rootNetworkTag";
private static final String QUERY_PARAM_GROUP_UUIDS = "groupUuids";
private static final String QUERY_PARAM_ROOT_NETWORK_TAGS = "rootNetworkTags";
private static final String ROOT_NETWORK_TAG_PATH = "root-network-tag";
private static final String PARAM_USER_INPUT = "userInput";

private final RestTemplate restTemplate;
Expand Down Expand Up @@ -352,6 +357,66 @@ public List<ReferenceData> getReferencesFromGroup(UUID groupUuid) {
).getBody();
}

public void updateRootNetworkApplicability(List<UUID> modificationsUuids, String rootNetworkTag, boolean applicable) {
Objects.requireNonNull(modificationsUuids);
Objects.requireNonNull(rootNetworkTag);
var path = UriComponentsBuilder
.fromUriString(getNetworkModificationServerURI(false) + NETWORK_MODIFICATIONS_PATH + DELIMITER + "root-network-applicability")
.queryParam(UUIDS, modificationsUuids)
.queryParam(QUERY_PARAM_ROOT_NETWORK_TAG, rootNetworkTag)
.queryParam(QUERY_PARAM_APPLICABLE, applicable)
.buildAndExpand()
.toUriString();

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

restTemplate.exchange(path, HttpMethod.PUT, new HttpEntity<>(headers), Void.class);
}

/**
* Renames a root network tag in the applicabilities held by the modifications of the given groups.
*/
public void renameRootNetworkTag(List<UUID> groupUuids, String oldTag, String newTag) {
Objects.requireNonNull(oldTag);
Objects.requireNonNull(newTag);
if (CollectionUtils.isEmpty(groupUuids)) {
return;
}
var path = UriComponentsBuilder
.fromUriString(getNetworkModificationServerURI(false) + NETWORK_MODIFICATIONS_PATH + DELIMITER + ROOT_NETWORK_TAG_PATH)
.queryParam(QUERY_PARAM_GROUP_UUIDS, groupUuids)
.queryParam("oldTag", oldTag)
.queryParam("newTag", newTag)
.buildAndExpand()
.toUriString();

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

restTemplate.exchange(path, HttpMethod.PUT, new HttpEntity<>(headers), Void.class);
}

/**
* Drops root network tags from the applicabilities held by the modifications of the given groups.
*/
public void deleteRootNetworkTags(List<UUID> groupUuids, List<String> rootNetworkTags) {
if (CollectionUtils.isEmpty(groupUuids) || CollectionUtils.isEmpty(rootNetworkTags)) {
return;
}
var path = UriComponentsBuilder
.fromUriString(getNetworkModificationServerURI(false) + NETWORK_MODIFICATIONS_PATH + DELIMITER + ROOT_NETWORK_TAG_PATH)
.queryParam(QUERY_PARAM_GROUP_UUIDS, groupUuids)
.queryParam(QUERY_PARAM_ROOT_NETWORK_TAGS, rootNetworkTags)
.buildAndExpand()
.toUriString();

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

restTemplate.exchange(path, HttpMethod.DELETE, new HttpEntity<>(headers), Void.class);
}

public void buildNode(@NonNull UUID nodeUuid, @NonNull UUID rootNetworkUuid, @NonNull BuildInfos buildInfos, AbstractWorkflowInfos workflowInfos) {
UUID networkUuid = rootNetworkService.getNetworkUuid(rootNetworkUuid);
String receiver = buildReceiver(nodeUuid, rootNetworkUuid);
Expand Down Expand Up @@ -495,7 +560,7 @@ private NetworkModificationsResult handleModifications(UUID groupUuid, UUID orig
).getBody();
}

public Map<UUID, UUID> duplicateModificationsGroup(UUID sourceGroupUuid, UUID groupUuid) {
public void duplicateModificationsGroup(UUID sourceGroupUuid, UUID groupUuid) {
Objects.requireNonNull(groupUuid);
Objects.requireNonNull(sourceGroupUuid);
var path = UriComponentsBuilder.fromPath("groups/{uuid}/duplicate")
Expand All @@ -506,12 +571,12 @@ public Map<UUID, UUID> duplicateModificationsGroup(UUID sourceGroupUuid, UUID gr
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

return restTemplate.exchange(
restTemplate.exchange(
getNetworkModificationServerURI(false) + path,
HttpMethod.POST,
new HttpEntity<>(headers),
new ParameterizedTypeReference<Map<UUID, UUID>>() { }
).getBody();
Void.class
);
}

public NetworkModificationsResult duplicateModificationsFromGroup(UUID groupUuid, UUID originGroupUuid, Pair<List<UUID>, List<ModificationApplicationContext>> modificationContextInfos) {
Expand Down Expand Up @@ -559,7 +624,7 @@ public void deleteIndexedModifications(List<UUID> groupUuids, UUID networkUuid)

String path = UriComponentsBuilder.fromPath(NETWORK_MODIFICATIONS_PATH + DELIMITER + "index")
.queryParam("networkUuid", networkUuid)
.queryParam("groupUuids", groupUuids)
.queryParam(QUERY_PARAM_GROUP_UUIDS, groupUuids)
.toUriString();

restTemplate.exchange(getNetworkModificationServerURI(false) + path, HttpMethod.DELETE, null, Void.class);
Expand Down
Loading
Loading