Skip to content

Specific composite handling#965

Open
Mathieu-Deharbe wants to merge 14 commits intomainfrom
specific-composite-handling
Open

Specific composite handling#965
Mathieu-Deharbe wants to merge 14 commits intomainfrom
specific-composite-handling

Conversation

@Mathieu-Deharbe
Copy link
Contributor

Separates composite handling from regular network modification handling

Mathieu-Deharbe and others added 9 commits March 12, 2026 11:30
Signed-off-by: Mathieu DEHARBE <mathieu.deharbe@rte-france.com>
Signed-off-by: Mathieu DEHARBE <mathieu.deharbe@rte-france.com>
Signed-off-by: Mathieu DEHARBE <mathieu.deharbe@rte-france.com>
Signed-off-by: Mathieu DEHARBE <mathieu.deharbe@rte-france.com>
Signed-off-by: Mathieu DEHARBE <mathieu.deharbe@rte-france.com>
Signed-off-by: Mathieu DEHARBE <mathieu.deharbe@rte-france.com>
Signed-off-by: Mathieu DEHARBE <mathieu.deharbe@rte-france.com>
@Mathieu-Deharbe Mathieu-Deharbe self-assigned this Mar 17, 2026
Signed-off-by: Mathieu DEHARBE <mathieu.deharbe@rte-france.com>
Signed-off-by: Mathieu DEHARBE <mathieu.deharbe@rte-france.com>
@sonarqubecloud
Copy link

Signed-off-by: Mathieu DEHARBE <mathieu.deharbe@rte-france.com>
Copy link
Contributor

@Meklo Meklo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a test for composite splitting would be interesting or it follows the exact same path as composite insertion in study server ?

studyService.invalidateNodeTreeWithLF(targetStudyUuid, targetNodeUuid);
try {
studyService.duplicateOrInsertNetworkModifications(targetStudyUuid, targetNodeUuid, originStudyUuid, originNodeUuid, modificationsToCopy, userId, action);
studyService.duplicateNetworkModifications(targetStudyUuid, targetNodeUuid, originStudyUuid, modificationsToCopyUuidList, userId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be missing something but in duplicateNetworkModifications, originStudyUuid has been removed as a parameter yet it is still being fed here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right I mixed up originStudyUuid and originNodeUuid ! Thanks a lot. Corrected here : d1ad47b

Comment on lines -2422 to +2426
copyModificationsToExclude(originNodeUuid, targetNodeUuid, modifications, networkModificationResults);
copyModificationsToExclude(originNodeUuid, targetNodeUuid, modificationsUuids, networkModificationResults);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed this function is called from duplicateNetworkModifications but not insertCompositeNetworkModifications, I don't know much about this exclusion system so is this intentional ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intentional : this function excludes modification copy according to gridstudy tags (it is not clear though, a comment would help).
For now tags don't appear in gridexplore's composite so this doesn't apply. It probably will change later, but the function will have to be changed to use something else than node's uuids.

Signed-off-by: Mathieu DEHARBE <mathieu.deharbe@rte-france.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 20, 2026

📝 Walkthrough

Walkthrough

This PR refactors network modification handling by introducing a dedicated enum type for composite modification actions, removing the ModificationsToCopyInfos DTO, and simplifying service APIs to work directly with UUID lists. A new endpoint is added for composite modifications, with corresponding updates across controller, service, and test layers.

Changes

Cohort / File(s) Summary
Enum Type Reorganization
src/main/java/org/gridsuite/study/server/StudyConstants.java
Removed SPLIT_COMPOSITE and INSERT_COMPOSITE from ModificationsActionType; introduced new CompositeModificationsActionType enum with SPLIT and INSERT constants.
API Layer Updates
src/main/java/org/gridsuite/study/server/controller/StudyController.java
Modified moveOrCopyModifications(...) to accept List<UUID> instead of List<ModificationsToCopyInfos>; removed composite action handling. Added new insertCompositeModifications(...) endpoint for PUT /studies/{studyUuid}/nodes/{nodeUuid}/composite-modifications.
DTO Removal
src/main/java/org/gridsuite/study/server/dto/ModificationsToCopyInfos.java
Deleted entire DTO class, removing uuid and compositeName fields and all Lombok-generated constructors/builders.
Service Layer Refactoring
src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java, src/main/java/org/gridsuite/study/server/service/StudyService.java
Updated moveModifications(...) and related methods to use List<UUID> instead of List<ModificationsToCopyInfos>. Replaced duplicateOrInsertModifications(...) with dedicated duplicateModifications(...). Added insertCompositeModifications(...). Extracted shared impact-notification logic into helper method.
Test Updates
src/test/java/org/gridsuite/study/server/NetworkModificationTest.java, src/test/java/org/gridsuite/study/server/rootnetworks/ModificationToExcludeTest.java, src/test/java/org/gridsuite/study/server/studycontroller/StudyControllerRebuildNodeTest.java
Updated test payloads and mocks to use List<UUID> directly. Added test for new composite modification insertion endpoint. Simplified UUID mapping logic and removed ModificationsToCopyInfos references.
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Specific composite handling' accurately reflects the main change: separating composite modification handling from regular network modification handling by introducing CompositeModificationsActionType and a dedicated endpoint.
Description check ✅ Passed The description 'Separates composite handling from regular network modification handling' directly relates to the changeset and captures the core objective of the pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

📝 Coding Plan
  • Generate coding plan for human review comments

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.41.1)
src/main/java/org/gridsuite/study/server/controller/StudyController.java
src/main/java/org/gridsuite/study/server/service/StudyService.java
src/test/java/org/gridsuite/study/server/NetworkModificationTest.java

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can customize the high-level summary generated by CodeRabbit.

Configure the reviews.high_level_summary_instructions setting to provide custom instructions for generating the high-level summary.

@Mathieu-Deharbe
Copy link
Contributor Author

Mathieu-Deharbe commented Mar 20, 2026

Adding a test for composite splitting would be interesting or it follows the exact same path as composite insertion in study server ?

They follow exactly the same path so I don't think a specific test would bring anything. Actually CompositeModificationsActionType could arguably be removed from study-server.

@Mathieu-Deharbe Mathieu-Deharbe requested a review from Meklo March 20, 2026 11:12
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java (1)

260-277: ⚠️ Potential issue | 🔴 Critical

Fail fast when the remote mutation response is empty.

These methods all return exchange(...).getBody() directly, but the new callers immediately consume duplicated UUIDs and impact results from that body. A successful PUT with no payload will now surface later as a local NPE/IOOBE after the remote write already happened.

Suggested guard at the client boundary
-        return restTemplate.exchange(
+        NetworkModificationsResult result = restTemplate.exchange(
                 getNetworkModificationServerURI(false) + path.buildAndExpand(targetGroupUuid).toUriString(),
                 HttpMethod.PUT,
                 httpEntity,
-                NetworkModificationsResult.class).getBody();
+                NetworkModificationsResult.class).getBody();
+        return Objects.requireNonNull(result, "Expected NetworkModificationsResult body");

Apply the same pattern to the other changed methods that currently return getBody() directly.

Also applies to: 280-300, 303-321, 344-345

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java`
around lines 260 - 277, The REST client call in moveModifications currently
returns restTemplate.exchange(...).getBody() directly which can be null and
cause NPE/IOOBE downstream; update moveModifications (and the other similar
methods that call restTemplate.exchange(...).getBody()) to capture the
ResponseEntity<NetworkModificationsResult>, check responseEntity.getBody() for
null, and if null throw a clear, fast-fail exception (e.g.,
IllegalStateException or a custom exception) with a descriptive message
indicating the remote PUT returned an empty body for the MOVE action and include
context (originGroupUuid, targetGroupUuid); ensure you reference the
restTemplate.exchange call and NetworkModificationsResult so the guard is added
at the client boundary for all analogous methods.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/java/org/gridsuite/study/server/controller/StudyController.java`:
- Around line 689-692: The endpoint StudyController.insertCompositeModifications
currently accepts a RequestBody List of org.springframework.data.util.Pair which
Jackson cannot deserialize; create a dedicated DTO (e.g.,
CompositeModificationInfo with fields uuid and name) and replace the parameter
type modificationsToInsert from List<Pair<UUID,String>> to
List<CompositeModificationInfo>, update any imports/usages and OpenAPI
annotations accordingly, and ensure the new DTO is a public record or class with
JVM-accessible properties so Jackson can serialize/deserialize it without custom
deserializers.

In `@src/main/java/org/gridsuite/study/server/service/StudyService.java`:
- Around line 2424-2426: The call to
networkModificationService.duplicateModifications(...) assumes the response has
one duplicated UUID per requested source and then blindly calls
copyModificationsToExclude; update the code around duplicateModifications and
copyModificationsToExclude to first validate that NetworkModificationsResult (or
its duplicates list/map) contains exactly the same number of entries as
modificationsUuids (and that each source UUID maps to a duplicate UUID), and if
the sizes/mapping do not match, fail fast (throw an exception or return an
error) or log and skip to avoid misapplying exclusion tags; apply the same
validation to the other block referenced (around the 2476-2485 area) so you
always map source->duplicate deterministically rather than assuming order.

---

Outside diff comments:
In
`@src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java`:
- Around line 260-277: The REST client call in moveModifications currently
returns restTemplate.exchange(...).getBody() directly which can be null and
cause NPE/IOOBE downstream; update moveModifications (and the other similar
methods that call restTemplate.exchange(...).getBody()) to capture the
ResponseEntity<NetworkModificationsResult>, check responseEntity.getBody() for
null, and if null throw a clear, fast-fail exception (e.g.,
IllegalStateException or a custom exception) with a descriptive message
indicating the remote PUT returned an empty body for the MOVE action and include
context (originGroupUuid, targetGroupUuid); ensure you reference the
restTemplate.exchange call and NetworkModificationsResult so the guard is added
at the client boundary for all analogous methods.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 996d639b-b58b-4954-a7a4-c2d5a565cee2

📥 Commits

Reviewing files that changed from the base of the PR and between b41b0b8 and d1ad47b.

📒 Files selected for processing (8)
  • src/main/java/org/gridsuite/study/server/StudyConstants.java
  • src/main/java/org/gridsuite/study/server/controller/StudyController.java
  • src/main/java/org/gridsuite/study/server/dto/ModificationsToCopyInfos.java
  • src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java
  • src/main/java/org/gridsuite/study/server/service/StudyService.java
  • src/test/java/org/gridsuite/study/server/NetworkModificationTest.java
  • src/test/java/org/gridsuite/study/server/rootnetworks/ModificationToExcludeTest.java
  • src/test/java/org/gridsuite/study/server/studycontroller/StudyControllerRebuildNodeTest.java
💤 Files with no reviewable changes (1)
  • src/main/java/org/gridsuite/study/server/dto/ModificationsToCopyInfos.java

Comment on lines +689 to +692
public ResponseEntity<Void> insertCompositeModifications(@PathVariable("studyUuid") UUID studyUuid,
@PathVariable("nodeUuid") UUID nodeUuid,
@RequestParam("action") CompositeModificationsActionType action,
@RequestBody List<Pair<UUID, String>> modificationsToInsert,
Copy link

@coderabbitai coderabbitai bot Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Spring Data Pair JSON deserialization Jackson

💡 Result:

Spring Data's org.springframework.data.util.Pair does not have built-in Jackson JSON serialization/deserialization support. The Pair class is a final immutable tuple without a default constructor or @JsonCreator, so Jackson cannot deserialize it by default. To enable JSON deserialization of Pair (e.g., List<Pair<A, B>>), implement a custom JsonDeserializer and register it with the ObjectMapper via a Jackson SimpleModule. Spring Boot auto-detects @JacksonComponent-annotated serializers/deserializers or Jackson Modules as Spring beans. Example custom deserializer for Pair<MyClassA, MyClassB> (from StackOverflow solution): java import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.data.util.Pair; import java.io.IOException; public class MyPairDeserializer extends JsonDeserializer<Pair<MyClassA, MyClassB>> { private static ObjectMapper objectMapper; @Override public Pair<MyClassA, MyClassB> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { if (objectMapper == null) { objectMapper = new ObjectMapper; objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } JsonNode treeNode = jsonParser.getCodec.readTree(jsonParser); MyClassA first = objectMapper.treeToValue(treeNode.get("first"), MyClassA.class); MyClassB second = objectMapper.treeToValue(treeNode.get("second"), MyClassB.class); return Pair.of(first, second); } } Register the module (e.g., as a @Bean): java @Configuration public class JacksonConfig { @Bean public Module pairModule { SimpleModule module = new SimpleModule; module.addDeserializer(Pair.class, new MyPairDeserializer); // Note: generics handling may need JavaType return module; } } Expected JSON format: {"first": {...}, "second": {...}} For generic handling across Pair<S, T>, use JsonDeserializer<Pair> with type resolution or parameterize appropriately. A matching serializer may be needed for full round-trip. Spring Data provides Jackson modules for geo types and others, but not Pair (confirmed by absence in official docs). In Spring Data REST, custom modules are auto-registered for domain serialization.

Citations:


🏁 Script executed:

cat -n src/main/java/org/gridsuite/study/server/controller/StudyController.java | sed -n '685,700p'

Repository: gridsuite/study-server

Length of output: 1628


🏁 Script executed:

# Search for custom Pair deserializers or Jackson configurations
rg -i "pairdeserializer|pair.*deserializ|jacksonconfig|JsonDeserializer.*Pair" --type java

Repository: gridsuite/study-server

Length of output: 48


🏁 Script executed:

# Search for Jackson module configuration or SimpleModule registration
rg -i "simplemodule|jacksonmodule|@.*Component.*jackson" --type java -A 3

Repository: gridsuite/study-server

Length of output: 48


🏁 Script executed:

# Search for any Jackson ObjectMapper bean configuration
rg -i "objectmapper|jackson.*bean|@bean.*jackson" --type java -B 2 -A 4

Repository: gridsuite/study-server

Length of output: 50379


🏁 Script executed:

# Search for Spring `@Configuration` classes
rg "@Configuration" --type java -A 5 | head -50

Repository: gridsuite/study-server

Length of output: 3041


🏁 Script executed:

# Check if Pair is imported from Spring Data and if it's used elsewhere
rg "import.*Pair|org\.springframework\.data\.util\.Pair" --type java

Repository: gridsuite/study-server

Length of output: 1243


🏁 Script executed:

# Search for Pair usage in test files to see if the endpoint is tested
rg "insertCompositeModifications" --type java -B 2 -A 5

Repository: gridsuite/study-server

Length of output: 3721


🏁 Script executed:

# Check pom.xml or gradle files for Jackson dependencies
find . -name "pom.xml" -o -name "build.gradle" | head -5

Repository: gridsuite/study-server

Length of output: 75


🏁 Script executed:

cat pom.xml | grep -A 5 -B 5 "spring-boot\|jackson\|spring-data" | head -60

Repository: gridsuite/study-server

Length of output: 2181


🏁 Script executed:

# Search for any custom Jackson deserializers or Jackson bean definitions in the codebase
rg "JsonDeserializer|@JsonDeserialize|ObjectMapper.*bean|addDeserializer" --type java

Repository: gridsuite/study-server

Length of output: 48


🏁 Script executed:

# Search for test classes that test the insertCompositeModifications endpoint
rg "mockMvc.*insertCompositeModifications|post.*composite-modifications" --type java -B 2 -A 5

Repository: gridsuite/study-server

Length of output: 48


🏁 Script executed:

# Check if there are any integration tests for the StudyController
rg "class.*StudyControllerTest|class.*StudyTest.*Test" --type java | head -10

Repository: gridsuite/study-server

Length of output: 177


🏁 Script executed:

# Search for actual calls to insertCompositeModifications in tests
rg "insertCompositeModifications" --type java -C 3

Repository: gridsuite/study-server

Length of output: 3562


The endpoint cannot be invoked via HTTP as currently written — use a dedicated DTO for the request body.

org.springframework.data.util.Pair lacks native Jackson deserialization support and requires a custom JsonDeserializer to deserialize from JSON. Without one, any HTTP call to this endpoint will fail at the deserialization stage. A custom record or class like CompositeModificationInfo(UUID uuid, String name) is not just clearer for API contracts and OpenAPI documentation — it's required for the endpoint to function.

♻️ Example DTO approach
// Create a new record/class
public record CompositeModificationInfo(UUID uuid, String name) {}

// Update the endpoint signature
`@RequestBody` List<CompositeModificationInfo> modificationsToInsert,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/org/gridsuite/study/server/controller/StudyController.java`
around lines 689 - 692, The endpoint
StudyController.insertCompositeModifications currently accepts a RequestBody
List of org.springframework.data.util.Pair which Jackson cannot deserialize;
create a dedicated DTO (e.g., CompositeModificationInfo with fields uuid and
name) and replace the parameter type modificationsToInsert from
List<Pair<UUID,String>> to List<CompositeModificationInfo>, update any
imports/usages and OpenAPI annotations accordingly, and ensure the new DTO is a
public record or class with JVM-accessible properties so Jackson can
serialize/deserialize it without custom deserializers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting : it wants me to go back to the dto that I just removed.

And it is wrong : this Pair system works fine (it doesn't mean that this is the best way of course, but it does work).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Mathieu-Deharbe, you're right — I apologize for the incorrect analysis. Spring Boot auto-configures Jackson support for org.springframework.data.util.Pair via spring-data-commons (through SpringDataWebAutoConfiguration), so deserialization works without any custom deserializer. My comment was wrong on both counts: the Pair serialization works fine, and the suggested fix would have essentially re-introduced the ModificationsToCopyInfos DTO you deliberately removed.


✏️ Learnings added
Learnt from: Mathieu-Deharbe
Repo: gridsuite/study-server PR: 965
File: src/main/java/org/gridsuite/study/server/controller/StudyController.java:689-692
Timestamp: 2026-03-20T11:42:11.589Z
Learning: In the gridsuite/study-server project (Java/Spring Boot), `org.springframework.data.util.Pair` can be used as a `RequestBody` type (e.g., `List<Pair<UUID, String>>`) in Spring MVC controllers without a custom Jackson deserializer. Spring Boot auto-configures Jackson support for `Pair` via `spring-data-commons` (`SpringDataWebAutoConfiguration`), so no custom `JsonDeserializer` is needed.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment on lines +2424 to +2426
NetworkModificationsResult networkModificationResults = networkModificationService.duplicateModifications(groupUuid, Pair.of(modificationsUuids, modificationApplicationContexts));

copyModificationsToExclude(originNodeUuid, targetNodeUuid, modifications, networkModificationResults);
copyModificationsToExclude(originNodeUuid, targetNodeUuid, modificationsUuids, networkModificationResults);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate the duplicate response size before copying exclusion tags.

Lines 2426 and 2481-2482 assume the server returns exactly one duplicated UUID per requested source UUID. If one item is missing, this throws; if the contract ever drifts, exclusion tags can be copied onto the wrong duplicate.

Suggested guard
 private void copyModificationsToExclude(UUID originNodeUuid,
                                         UUID targetNodeUuid,
                                         List<UUID> modificationsUuids,
                                         NetworkModificationsResult networkModificationResults) {
+    List<UUID> duplicatedModificationUuids = networkModificationResults.modificationUuids();
+    if (duplicatedModificationUuids.size() != modificationsUuids.size()) {
+        throw new IllegalStateException("Duplicate response size mismatch");
+    }
     Map<UUID, UUID> mappingModificationsUuids = new HashMap<>();
     for (int i = 0; i < modificationsUuids.size(); i++) {
-        mappingModificationsUuids.put(modificationsUuids.get(i), networkModificationResults.modificationUuids().get(i));
+        mappingModificationsUuids.put(modificationsUuids.get(i), duplicatedModificationUuids.get(i));
     }
 
     rootNetworkNodeInfoService.copyModificationsToExcludeFromTags(originNodeUuid, targetNodeUuid, mappingModificationsUuids);
 }

Also applies to: 2476-2485

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/org/gridsuite/study/server/service/StudyService.java` around
lines 2424 - 2426, The call to
networkModificationService.duplicateModifications(...) assumes the response has
one duplicated UUID per requested source and then blindly calls
copyModificationsToExclude; update the code around duplicateModifications and
copyModificationsToExclude to first validate that NetworkModificationsResult (or
its duplicates list/map) contains exactly the same number of entries as
modificationsUuids (and that each source UUID maps to a duplicate UUID), and if
the sizes/mapping do not match, fail fast (throw an exception or return an
error) or log and skip to avoid misapplying exclusion tags; apply the same
validation to the other block referenced (around the 2476-2485 area) so you
always map source->duplicate deterministically rather than assuming order.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR separates composite modification handling from regular network modification operations by introducing a dedicated composite endpoint and simplifying regular copy/move payloads to UUID lists.

Changes:

  • Replace ModificationsToCopyInfos payloads with List<UUID> for regular move/copy/duplicate flows and update impacted services/tests.
  • Introduce a dedicated /composite-modifications endpoint and service path to handle composite-specific insert/split actions.
  • Remove the ModificationsToCopyInfos DTO and split action enums into ModificationsActionType vs CompositeModificationsActionType.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/test/java/org/gridsuite/study/server/studycontroller/StudyControllerRebuildNodeTest.java Updates controller test to pass UUID lists instead of DTOs.
src/test/java/org/gridsuite/study/server/rootnetworks/ModificationToExcludeTest.java Updates duplication tests to new APIs (duplicateNetworkModifications, duplicateModifications).
src/test/java/org/gridsuite/study/server/NetworkModificationTest.java Adapts move/duplicate tests to UUID list payloads and adds composite insertion test coverage.
src/main/java/org/gridsuite/study/server/service/StudyService.java Refactors duplication flow, adds composite insert/split flow, and centralizes impact notification emission.
src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java Updates REST payload types to UUID lists and adds composite modifications REST call.
src/main/java/org/gridsuite/study/server/dto/ModificationsToCopyInfos.java Removes obsolete DTO.
src/main/java/org/gridsuite/study/server/controller/StudyController.java Updates move/copy endpoint payload type and adds composite-modifications endpoint.
src/main/java/org/gridsuite/study/server/StudyConstants.java Splits action enums for regular vs composite modifications.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +689 to +693
public ResponseEntity<Void> insertCompositeModifications(@PathVariable("studyUuid") UUID studyUuid,
@PathVariable("nodeUuid") UUID nodeUuid,
@RequestParam("action") CompositeModificationsActionType action,
@RequestBody List<Pair<UUID, String>> modificationsToInsert,
@RequestHeader(HEADER_USER_ID) String userId) {
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using List<Pair<UUID, String>> as a request body couples the public API schema to org.springframework.data.util.Pair (with first/second fields) and makes the contract unclear for API consumers. Consider introducing a dedicated DTO (e.g., { uuid, name }) for composite modifications instead of Pair to produce a stable, self-describing OpenAPI schema and JSON representation.

Copilot uses AI. Check for mistakes.
Comment on lines +2449 to +2454
public void insertCompositeNetworkModifications(
UUID targetStudyUuid,
UUID targetNodeUuid,
List<Pair<UUID, String>> modifications,
String userId,
StudyConstants.CompositeModificationsActionType action) {
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

insertCompositeNetworkModifications takes an action that can be SPLIT as well as INSERT, so the method name is misleading (it may not actually insert composites). Renaming it (and corresponding controller helper) to something action-neutral (e.g., applyCompositeNetworkModifications) would make call sites clearer and reduce the risk of misuse.

Copilot uses AI. Check for mistakes.
Comment on lines +687 to +688
@Operation(summary = "For a list of composite network modifications passed in body, insert them into the target node")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The composite modification list has been inserted.")})
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new /composite-modifications endpoint accepts an action that can be SPLIT or INSERT, but the OpenAPI summary/response description only describes insertion. This is misleading for SPLIT; please update the summary/ApiResponse text (or split into two endpoints) so behavior matches the documented contract.

Suggested change
@Operation(summary = "For a list of composite network modifications passed in body, insert them into the target node")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The composite modification list has been inserted.")})
@Operation(summary = "For a list of composite network modifications passed in body, apply the requested action (insert or split) into the target node")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The composite modification list has been updated according to the requested action.")})

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants