Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions monitor-commons/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,15 @@
<version>2.2.22</version>
<scope>provided</scope>
</dependency>
<dependency>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

?

<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.gridsuite.monitor.commons.types.processexecution.ProcessType;

import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
Expand All @@ -25,4 +26,17 @@ public record LoadFlowConfig(
public ProcessType processType() {
return ProcessType.LOADFLOW;
}

@Override
public List<ProcessConfigFieldComparison> compareWith(ProcessConfig other) {
LoadFlowConfig o = (LoadFlowConfig) other;
return List.of(
new ProcessConfigFieldComparison("modifications",
Objects.equals(this.modificationUuids, o.modificationUuids),
this.modificationUuids, o.modificationUuids),
new ProcessConfigFieldComparison("loadflowParameters",
Objects.equals(this.loadflowParametersUuid, o.loadflowParametersUuid),
this.loadflowParametersUuid, o.loadflowParametersUuid)
);
}
Comment on lines +31 to +41
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@ public interface ProcessConfig {
ProcessType processType();

List<UUID> modificationUuids();

List<ProcessConfigFieldComparison> compareWith(ProcessConfig other);
Comment on lines +32 to +33

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Make the compareWith contract explicitly non-null.

Both current implementations dereference other.processType() on the type-mismatch path, so compareWith(null) fails with an unexpected NPE instead of a controlled exception. Tighten the interface contract or fail fast before implementations reach that branch.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@monitor-commons/src/main/java/org/gridsuite/monitor/commons/types/processconfig/ProcessConfig.java`
around lines 32 - 33, The compareWith contract in ProcessConfig is currently
ambiguous about null, and the implementations can hit an unexpected NPE when
other is null. Make the parameter explicitly non-null in the ProcessConfig
interface and update the compareWith implementations to fail fast with a
controlled exception before any access to other.processType(), keeping the
contract consistent across all implementations.

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/**
/*
* 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;
package org.gridsuite.monitor.commons.types.processconfig;

import io.swagger.v3.oas.annotations.media.Schema;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.gridsuite.monitor.commons.types.processexecution.ProcessType;

import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
Expand All @@ -27,4 +28,20 @@ public record SecurityAnalysisConfig(
public ProcessType processType() {
return ProcessType.SECURITY_ANALYSIS;
}

@Override
public List<ProcessConfigFieldComparison> compareWith(ProcessConfig other) {
SecurityAnalysisConfig o = (SecurityAnalysisConfig) other;
return List.of(
new ProcessConfigFieldComparison("modifications",
Objects.equals(this.modificationUuids, o.modificationUuids),
this.modificationUuids, o.modificationUuids),
new ProcessConfigFieldComparison("securityAnalysisParameters",
Objects.equals(this.securityAnalysisParametersUuid, o.securityAnalysisParametersUuid),
this.securityAnalysisParametersUuid, o.securityAnalysisParametersUuid),
new ProcessConfigFieldComparison("loadflowParameters",
Objects.equals(this.loadflowParametersUuid, o.loadflowParametersUuid),
this.loadflowParametersUuid, o.loadflowParametersUuid)
);
}
Comment on lines +33 to +46
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* 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.commons.types.processconfig;

import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

/**
* @author Caroline Jeandat {@literal <caroline.jeandat at rte-france.com>}
*/
class LoadFlowConfigTest {
@Test
void compareWithShouldReturnNoDifferenceWhenConfigsAreEqual() {
LoadFlowConfig processConfig = new LoadFlowConfig(UUID.randomUUID(), List.of(UUID.randomUUID()));

List<ProcessConfigFieldComparison> result = processConfig.compareWith(processConfig);

assertThat(result)
.hasSize(2)
.allMatch(ProcessConfigFieldComparison::identical)
.allMatch(fieldComparison -> fieldComparison.value1().equals(fieldComparison.value2()));
}

@Test
void compareWithShouldReturnDifferentModificationsWhenModificationsAreDifferent() {
UUID loadflowParametersUuid = UUID.randomUUID();
List<UUID> modificationUuids1 = List.of(UUID.randomUUID(), UUID.randomUUID());
List<UUID> modificationUuids2 = List.of(UUID.randomUUID(), UUID.randomUUID());

LoadFlowConfig processConfig1 = new LoadFlowConfig(loadflowParametersUuid, modificationUuids1);
LoadFlowConfig processConfig2 = new LoadFlowConfig(loadflowParametersUuid, modificationUuids2);

List<ProcessConfigFieldComparison> result = processConfig1.compareWith(processConfig2);

assertThat(result).hasSize(2);
ProcessConfigFieldComparison comparison = result.stream()
.filter(d -> "modifications".equals(d.field()))
.findFirst()
.orElseThrow();
assertThat(comparison.identical()).isFalse();
assertThat(comparison.value1()).isEqualTo(modificationUuids1);
assertThat(comparison.value2()).isEqualTo(modificationUuids2);
}

@Test
void compareWithShouldDetectOrderDifferenceInModifications() {
UUID loadflowParametersUuid = UUID.randomUUID();
UUID mod1 = UUID.randomUUID();
UUID mod2 = UUID.randomUUID();
List<UUID> modificationUuids1 = List.of(mod1, mod2);
List<UUID> modificationUuids2 = List.of(mod2, mod1); // Different order

LoadFlowConfig processConfig1 = new LoadFlowConfig(loadflowParametersUuid, modificationUuids1);
LoadFlowConfig processConfig2 = new LoadFlowConfig(loadflowParametersUuid, modificationUuids2);

List<ProcessConfigFieldComparison> result = processConfig1.compareWith(processConfig2);

assertThat(result).hasSize(2);
ProcessConfigFieldComparison comparison = result.stream()
.filter(d -> "modifications".equals(d.field()))
.findFirst()
.orElseThrow();
assertThat(comparison.identical()).isFalse();
assertThat(comparison.value1()).isEqualTo(modificationUuids1);
assertThat(comparison.value2()).isEqualTo(modificationUuids2);
}

@Test
void compareWithShouldReturnDifferencesWhenParametersAreDifferent() {
UUID loadflowParametersUuid1 = UUID.randomUUID();
UUID loadflowParametersUuid2 = UUID.randomUUID();
List<UUID> modificationUuids = List.of(UUID.randomUUID(), UUID.randomUUID());

LoadFlowConfig processConfig1 = new LoadFlowConfig(loadflowParametersUuid1, modificationUuids);
LoadFlowConfig processConfig2 = new LoadFlowConfig(loadflowParametersUuid2, modificationUuids);

List<ProcessConfigFieldComparison> result = processConfig1.compareWith(processConfig2);

assertThat(result).hasSize(2);
ProcessConfigFieldComparison comparison = result.stream()
.filter(d -> "loadflowParameters".equals(d.field()))
.findFirst()
.orElseThrow();
assertThat(comparison.identical()).isFalse();
assertThat(comparison.value1()).isEqualTo(loadflowParametersUuid1);
assertThat(comparison.value2()).isEqualTo(loadflowParametersUuid2);
}

@Test
void compareWithShouldThrowWhenProcessTypesAreDifferent() {
LoadFlowConfig loadFlowConfig = new LoadFlowConfig(UUID.randomUUID(), List.of(UUID.randomUUID()));
SecurityAnalysisConfig securityAnalysisConfig = new SecurityAnalysisConfig(UUID.randomUUID(), List.of(UUID.randomUUID()), UUID.randomUUID());

assertThatThrownBy(() -> loadFlowConfig.compareWith(securityAnalysisConfig)).isInstanceOf(ClassCastException.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* 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.commons.types.processconfig;

import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

/**
* @author Caroline Jeandat {@literal <caroline.jeandat at rte-france.com>}
*/
class SecurityAnalysisConfigTest {
@Test
void compareWithShouldReturnNoDifferenceWhenConfigsAreEqual() {
SecurityAnalysisConfig securityAnalysisConfig = new SecurityAnalysisConfig(UUID.randomUUID(), List.of(UUID.randomUUID()), UUID.randomUUID());

List<ProcessConfigFieldComparison> result = securityAnalysisConfig.compareWith(securityAnalysisConfig);

assertThat(result)
.hasSize(3)
.allMatch(ProcessConfigFieldComparison::identical)
.allMatch(fieldComparison -> fieldComparison.value1().equals(fieldComparison.value2()));
}

@Test
void compareWithShouldReturnDifferentModificationsWhenModificationsAreDifferent() {
UUID securityAnalysisParametersUuid = UUID.randomUUID();
List<UUID> modificationUuids1 = List.of(UUID.randomUUID(), UUID.randomUUID());
List<UUID> modificationUuids2 = List.of(UUID.randomUUID(), UUID.randomUUID());
UUID loadflowParametersUuid = UUID.randomUUID();

SecurityAnalysisConfig processConfig1 = new SecurityAnalysisConfig(securityAnalysisParametersUuid, modificationUuids1, loadflowParametersUuid);
SecurityAnalysisConfig processConfig2 = new SecurityAnalysisConfig(securityAnalysisParametersUuid, modificationUuids2, loadflowParametersUuid);

List<ProcessConfigFieldComparison> result = processConfig1.compareWith(processConfig2);

assertThat(result).hasSize(3);
ProcessConfigFieldComparison comparison = result.stream()
.filter(d -> "modifications".equals(d.field()))
.findFirst()
.orElseThrow();
assertThat(comparison.identical()).isFalse();
assertThat(comparison.value1()).isEqualTo(modificationUuids1);
assertThat(comparison.value2()).isEqualTo(modificationUuids2);
}

@Test
void compareWithShouldDetectOrderDifferenceInModifications() {
UUID securityAnalysisParametersUuid = UUID.randomUUID();
UUID mod1 = UUID.randomUUID();
UUID mod2 = UUID.randomUUID();
List<UUID> modificationUuids1 = List.of(mod1, mod2);
List<UUID> modificationUuids2 = List.of(mod2, mod1); // Different order
UUID loadflowParametersUuid = UUID.randomUUID();

SecurityAnalysisConfig processConfig1 = new SecurityAnalysisConfig(securityAnalysisParametersUuid, modificationUuids1, loadflowParametersUuid);
SecurityAnalysisConfig processConfig2 = new SecurityAnalysisConfig(securityAnalysisParametersUuid, modificationUuids2, loadflowParametersUuid);

List<ProcessConfigFieldComparison> result = processConfig1.compareWith(processConfig2);

assertThat(result).hasSize(3);
ProcessConfigFieldComparison comparison = result.stream()
.filter(d -> "modifications".equals(d.field()))
.findFirst()
.orElseThrow();
assertThat(comparison.identical()).isFalse();
assertThat(comparison.value1()).isEqualTo(modificationUuids1);
assertThat(comparison.value2()).isEqualTo(modificationUuids2);
}

@Test
void compareWithShouldReturnDifferencesWhenSecurityAnalysisParametersAreDifferent() {
UUID securityAnalysisParametersUuid1 = UUID.randomUUID();
UUID securityAnalysisParametersUuid2 = UUID.randomUUID();
List<UUID> modificationUuids = List.of(UUID.randomUUID(), UUID.randomUUID());
UUID loadflowParametersUuid = UUID.randomUUID();

SecurityAnalysisConfig processConfig1 = new SecurityAnalysisConfig(securityAnalysisParametersUuid1, modificationUuids, loadflowParametersUuid);
SecurityAnalysisConfig processConfig2 = new SecurityAnalysisConfig(securityAnalysisParametersUuid2, modificationUuids, loadflowParametersUuid);

List<ProcessConfigFieldComparison> result = processConfig1.compareWith(processConfig2);

assertThat(result).hasSize(3);
ProcessConfigFieldComparison comparison = result.stream()
.filter(d -> "securityAnalysisParameters".equals(d.field()))
.findFirst()
.orElseThrow();
assertThat(comparison.identical()).isFalse();
assertThat(comparison.value1()).isEqualTo(securityAnalysisParametersUuid1);
assertThat(comparison.value2()).isEqualTo(securityAnalysisParametersUuid2);
}

@Test
void compareWithShouldReturnDifferencesWhenLoadflowParametersAreDifferent() {
UUID securityAnalysisParametersUuid = UUID.randomUUID();
List<UUID> modificationUuids = List.of(UUID.randomUUID(), UUID.randomUUID());
UUID loadflowParametersUuid1 = UUID.randomUUID();
UUID loadflowParametersUuid2 = UUID.randomUUID();

SecurityAnalysisConfig processConfig1 = new SecurityAnalysisConfig(securityAnalysisParametersUuid, modificationUuids, loadflowParametersUuid1);
SecurityAnalysisConfig processConfig2 = new SecurityAnalysisConfig(securityAnalysisParametersUuid, modificationUuids, loadflowParametersUuid2);

List<ProcessConfigFieldComparison> result = processConfig1.compareWith(processConfig2);

assertThat(result).hasSize(3);
ProcessConfigFieldComparison comparison = result.stream()
.filter(d -> "loadflowParameters".equals(d.field()))
.findFirst()
.orElseThrow();
assertThat(comparison.identical()).isFalse();
assertThat(comparison.value1()).isEqualTo(loadflowParametersUuid1);
assertThat(comparison.value2()).isEqualTo(loadflowParametersUuid2);
}

@Test
void compareWithShouldThrowWhenProcessTypesAreDifferent() {
SecurityAnalysisConfig securityAnalysisConfig = new SecurityAnalysisConfig(UUID.randomUUID(), List.of(UUID.randomUUID()), UUID.randomUUID());
LoadFlowConfig loadFlowConfig = new LoadFlowConfig(UUID.randomUUID(), List.of(UUID.randomUUID()));

assertThatThrownBy(() -> securityAnalysisConfig.compareWith(loadFlowConfig)).isInstanceOf(ClassCastException.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,11 @@ public ResponseEntity<ProcessConfigComparison> compareProcessConfigs(
@Parameter(description = "First process config UUID") @RequestParam("uuid1") UUID uuid1,
@Parameter(description = "Second process config UUID") @RequestParam("uuid2") UUID uuid2) {

Optional<ProcessConfigComparison> comparison = processConfigService.compareProcessConfigs(uuid1, uuid2);
return comparison.map(c -> ResponseEntity.status(HttpStatus.OK).body(c)).orElseGet(() -> ResponseEntity.status(HttpStatus.NOT_FOUND).build());
try {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

keep exisitig

Optional<ProcessConfigComparison> comparison = processConfigService.compareProcessConfigs(uuid1, uuid2);
return comparison.map(c -> ResponseEntity.status(HttpStatus.OK).body(c)).orElseGet(() -> ResponseEntity.status(HttpStatus.NOT_FOUND).build());
} catch (ClassCastException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
Comment on lines +137 to +142
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package org.gridsuite.monitor.server.dto.processconfig;

import io.swagger.v3.oas.annotations.media.Schema;
import org.gridsuite.monitor.commons.types.processconfig.ProcessConfigFieldComparison;

import java.util.List;
import java.util.UUID;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/*
* 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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/*
* 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* @author Franck Lecuyer <franck.lecuyer at rte-france.com>
*/
@Mapper(componentModel = "spring")
public interface LoadFlowConfigMapper {
public interface LoadFlowConfigMapper extends ProcessConfigMapper<LoadFlowConfig, LoadFlowConfigEntity> {
@Mapping(target = "processType", expression = "java(dto.processType())")
LoadFlowConfigEntity toEntity(LoadFlowConfig dto);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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.mappers.processconfig;

import org.gridsuite.monitor.commons.types.processconfig.ProcessConfig;
import org.gridsuite.monitor.server.entities.processconfig.ProcessConfigEntity;

/**
* @author Caroline Jeandat {@literal <caroline.jeandat at rte-france.com>}
*/
public interface ProcessConfigMapper<C extends ProcessConfig, E extends ProcessConfigEntity> {
E toEntity(C dto);

C toDto(E entity);

void updateEntityFromDto(C dto, E entity);
}
Loading
Loading