Skip to content

Commit efa4ef1

Browse files
authored
Merge branch 'main' into Fix_NullPointerException_ModificationByAssignment
2 parents 49c2b5f + 1642d36 commit efa4ef1

File tree

7 files changed

+472
-22
lines changed

7 files changed

+472
-22
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
<groupId>org.gridsuite</groupId>
2121
<artifactId>gridsuite-network-modification</artifactId>
22-
<version>0.65.0-SNAPSHOT</version>
22+
<version>0.66.0-SNAPSHOT</version>
2323

2424
<packaging>jar</packaging>
2525
<name>Network modification library</name>

src/main/java/org/gridsuite/modification/modifications/AbstractBranchModification.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,8 @@ public ReportNode updateMeasurements(Branch<?> branch, BranchModificationInfos b
211211
return estimSubReportNode;
212212
}
213213

214-
private void upsertMeasurement(Measurements<?> measurements, Measurement.Type type, ThreeSides side, Double value, Boolean validity, List<ReportNode> reports) {
215-
if (value == null && validity == null) {
214+
private void upsertMeasurement(Measurements<?> measurements, Measurement.Type type, ThreeSides side, Double value, Boolean requestedValidity, List<ReportNode> reports) {
215+
if (value == null && requestedValidity == null) {
216216
return;
217217
}
218218
String measurementType = (type == Measurement.Type.ACTIVE_POWER ? "Active power" : "Reactive power") + " measurement ";
@@ -223,20 +223,21 @@ private void upsertMeasurement(Measurements<?> measurements, Measurement.Type ty
223223
m.setValue(value);
224224
reports.add(ModificationUtils.buildModificationReport(oldValue, value, measurementType + VALUE, TypedValue.INFO_SEVERITY));
225225
}
226-
if (validity != null) {
226+
if (requestedValidity != null) {
227227
boolean oldValidity = m.isValid();
228-
m.setValid(validity);
229-
reports.add(ModificationUtils.buildModificationReport(oldValidity, validity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));
228+
229+
ModificationUtils.updateMeasurementValidity(m, requestedValidity);
230+
reports.add(ModificationUtils.buildModificationReport(oldValidity, requestedValidity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));
230231
}
231232
} else { // add new measurement
232233
var mAdder = measurements.newMeasurement().setId(UUID.randomUUID().toString()).setType(type).setSide(side);
233234
if (value != null) {
234235
mAdder.setValue(value);
235236
reports.add(ModificationUtils.buildModificationReport(null, value, measurementType + VALUE, TypedValue.INFO_SEVERITY));
236237
}
237-
if (validity != null) {
238-
mAdder.setValid(validity);
239-
reports.add(ModificationUtils.buildModificationReport(null, validity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));
238+
if (requestedValidity != null) {
239+
mAdder.setValid(requestedValidity);
240+
reports.add(ModificationUtils.buildModificationReport(null, requestedValidity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));
240241
}
241242
mAdder.add();
242243
}

src/main/java/org/gridsuite/modification/modifications/AbstractInjectionModification.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ protected ReportNode updateMeasurements(Injection<?> injection, InjectionModific
6060
return estimSubReportNode;
6161
}
6262

63-
private void upsertMeasurement(Measurements<?> measurements, Measurement.Type type, Double value, Boolean validity, List<ReportNode> reports) {
64-
if (value == null && validity == null) {
63+
private void upsertMeasurement(Measurements<?> measurements, Measurement.Type type, Double value, Boolean requestedValidity, List<ReportNode> reports) {
64+
if (value == null && requestedValidity == null) {
6565
return;
6666
}
6767
String measurementType = (type == Measurement.Type.ACTIVE_POWER ? "Active power" : "Reactive power") + " measurement ";
@@ -72,20 +72,21 @@ private void upsertMeasurement(Measurements<?> measurements, Measurement.Type ty
7272
measurement.setValue(value);
7373
reports.add(ModificationUtils.buildModificationReport(oldValue, value, measurementType + VALUE, TypedValue.INFO_SEVERITY));
7474
}
75-
if (validity != null) {
75+
if (requestedValidity != null) {
7676
boolean oldValidity = measurement.isValid();
77-
measurement.setValid(validity);
78-
reports.add(ModificationUtils.buildModificationReport(oldValidity, validity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));
77+
78+
ModificationUtils.updateMeasurementValidity(measurement, requestedValidity);
79+
reports.add(ModificationUtils.buildModificationReport(oldValidity, requestedValidity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));
7980
}
8081
} else {
8182
var measurementAdder = measurements.newMeasurement().setId(UUID.randomUUID().toString()).setType(type);
8283
if (value != null) {
8384
measurementAdder.setValue(value);
8485
reports.add(ModificationUtils.buildModificationReport(null, value, measurementType + VALUE, TypedValue.INFO_SEVERITY));
8586
}
86-
if (validity != null) {
87-
measurementAdder.setValid(validity);
88-
reports.add(ModificationUtils.buildModificationReport(null, validity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));
87+
if (requestedValidity != null) {
88+
measurementAdder.setValid(requestedValidity);
89+
reports.add(ModificationUtils.buildModificationReport(null, requestedValidity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));
8990
}
9091
measurementAdder.add();
9192
}

src/main/java/org/gridsuite/modification/utils/ModificationUtils.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public final class ModificationUtils {
7272
private static final String COULD_NOT_ACTION_EQUIPMENT_ON_SIDE = COULD_NOT_ACTION_EQUIPMENT + " on side %s";
7373
public static final String CONNECT = "connect";
7474
public static final String DISCONNECT = "disconnect";
75+
private static final String MEASUREMENT_VALIDITY_PROPERTY = "validity";
7576
public static final String FIELD_MAX_ACTIVE_POWER = "Maximum active power";
7677
public static final String FIELD_MIN_ACTIVE_POWER = "Minimum active power";
7778
public static final String FIELD_PLANNED_ACTIVE_POWER_SET_POINT = "Planned active power set point";
@@ -2193,5 +2194,27 @@ public void createNewActivePowerControlForInjectionCreation(ActivePowerControlAd
21932194
}
21942195

21952196
}
2196-
}
21972197

2198+
public static void updateMeasurementValidity(Measurement measurement, boolean requestedValidity) {
2199+
measurement.setValid(requestedValidity);
2200+
if (measurement.getProperty(MEASUREMENT_VALIDITY_PROPERTY) != null) {
2201+
if (requestedValidity) {
2202+
switch (measurement.getProperty(MEASUREMENT_VALIDITY_PROPERTY)) {
2203+
//validity = 1 → TM non valid & not masked
2204+
//validity = 3 → TM non valid & masked
2205+
case "1": measurement.putProperty(MEASUREMENT_VALIDITY_PROPERTY, "0"); break;
2206+
case "3": measurement.putProperty(MEASUREMENT_VALIDITY_PROPERTY, "2"); break;
2207+
default: break;
2208+
}
2209+
} else {
2210+
switch (measurement.getProperty(MEASUREMENT_VALIDITY_PROPERTY)) {
2211+
//validity = 0 → TM valid & not masked
2212+
//validity = 2 → TM valid & masked
2213+
case "0": measurement.putProperty(MEASUREMENT_VALIDITY_PROPERTY, "1"); break;
2214+
case "2": measurement.putProperty(MEASUREMENT_VALIDITY_PROPERTY, "3"); break;
2215+
default: break;
2216+
}
2217+
}
2218+
}
2219+
}
2220+
}

src/test/java/org/gridsuite/modification/modifications/LineModificationTest.java

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,4 +591,208 @@ void testLimitsPropertiesModificationSameOperationalLimitsReplace() {
591591
assertEquals(OLG_PROP3_VALUE, repLimitsGroup2.getProperty(OLG_PROP3_NAME));
592592
}
593593

594+
@Test
595+
void testMeasurementValidityPropertyForLine() {
596+
Line line = getNetwork().getLine("line1");
597+
Measurements<?> measurements = (Measurements<?>) line.getExtension(Measurements.class);
598+
assertNotNull(measurements);
599+
Measurement activePowerMeasurement = measurements.getMeasurements(Measurement.Type.ACTIVE_POWER).stream()
600+
.filter(m -> m.getSide() == ThreeSides.ONE)
601+
.findFirst()
602+
.orElseThrow();
603+
604+
LineModificationInfos addSide1ActiveByValue = LineModificationInfos.builder()
605+
.equipmentId("line1")
606+
.p1MeasurementValue(new AttributeModification<>(79.0, OperationType.SET))
607+
.build();
608+
addSide1ActiveByValue.toModification().apply(getNetwork());
609+
assertEquals(79.0, activePowerMeasurement.getValue());
610+
611+
activePowerMeasurement.putProperty("validity", "1");
612+
LineModificationInfos modificationInfosTrueFromOne = LineModificationInfos.builder()
613+
.equipmentId("line1")
614+
.p1MeasurementValidity(new AttributeModification<>(true, OperationType.SET))
615+
.build();
616+
modificationInfosTrueFromOne.toModification().apply(getNetwork());
617+
assertEquals("0", activePowerMeasurement.getProperty("validity"));
618+
619+
activePowerMeasurement.putProperty("validity", "3");
620+
LineModificationInfos modificationInfosTrueFromThree = LineModificationInfos.builder()
621+
.equipmentId("line1")
622+
.p1MeasurementValidity(new AttributeModification<>(true, OperationType.SET))
623+
.build();
624+
modificationInfosTrueFromThree.toModification().apply(getNetwork());
625+
assertEquals("2", activePowerMeasurement.getProperty("validity"));
626+
627+
Measurement reactivePowerMeasurement = measurements.getMeasurements(Measurement.Type.REACTIVE_POWER).stream()
628+
.filter(m -> m.getSide() == ThreeSides.ONE)
629+
.findFirst()
630+
.orElseThrow();
631+
reactivePowerMeasurement.putProperty("validity", "2");
632+
LineModificationInfos modificationInfosFalseFromTwo = LineModificationInfos.builder()
633+
.equipmentId("line1")
634+
.q1MeasurementValidity(new AttributeModification<>(false, OperationType.SET))
635+
.build();
636+
modificationInfosFalseFromTwo.toModification().apply(getNetwork());
637+
assertEquals("3", reactivePowerMeasurement.getProperty("validity"));
638+
639+
reactivePowerMeasurement.putProperty("validity", "0");
640+
LineModificationInfos modificationInfosFalseFromZero = LineModificationInfos.builder()
641+
.equipmentId("line1")
642+
.q1MeasurementValidity(new AttributeModification<>(false, OperationType.SET))
643+
.build();
644+
modificationInfosFalseFromZero.toModification().apply(getNetwork());
645+
assertEquals("1", reactivePowerMeasurement.getProperty("validity"));
646+
647+
// update validity on existing measurement without legacy property
648+
reactivePowerMeasurement.removeProperty("validity");
649+
LineModificationInfos modificationInfosTrueWithoutProperty = LineModificationInfos.builder()
650+
.equipmentId("line1")
651+
.q1MeasurementValidity(new AttributeModification<>(true, OperationType.SET))
652+
.build();
653+
modificationInfosTrueWithoutProperty.toModification().apply(getNetwork());
654+
assertTrue(reactivePowerMeasurement.isValid());
655+
assertNull(reactivePowerMeasurement.getProperty("validity"));
656+
657+
// add side 2 (new) measurement by value only
658+
assertTrue(measurements.getMeasurements(Measurement.Type.ACTIVE_POWER).stream().noneMatch(m -> m.getSide() == ThreeSides.TWO));
659+
LineModificationInfos addSide2ActiveByValue = LineModificationInfos.builder()
660+
.equipmentId("line1")
661+
.p2MeasurementValue(new AttributeModification<>(42.0, OperationType.SET))
662+
.build();
663+
addSide2ActiveByValue.toModification().apply(getNetwork());
664+
Measurement addedActiveSide2 = measurements.getMeasurements(Measurement.Type.ACTIVE_POWER).stream()
665+
.filter(m -> m.getSide() == ThreeSides.TWO)
666+
.findFirst()
667+
.orElseThrow();
668+
assertEquals(42.0, addedActiveSide2.getValue());
669+
670+
// add side 2 reactive measurement by validity only then update it
671+
assertTrue(measurements.getMeasurements(Measurement.Type.REACTIVE_POWER).stream().noneMatch(m -> m.getSide() == ThreeSides.TWO));
672+
LineModificationInfos addSide2ReactiveByValidity = LineModificationInfos.builder()
673+
.equipmentId("line1")
674+
.q2MeasurementValue(new AttributeModification<>(MEASUREMENT_Q_VALUE, OperationType.SET))
675+
.q2MeasurementValidity(new AttributeModification<>(false, OperationType.SET))
676+
.build();
677+
addSide2ReactiveByValidity.toModification().apply(getNetwork());
678+
679+
Measurement addedReactiveSide2 = measurements.getMeasurements(Measurement.Type.REACTIVE_POWER).stream()
680+
.filter(m -> m.getSide() == ThreeSides.TWO)
681+
.findFirst()
682+
.orElseThrow();
683+
assertFalse(addedReactiveSide2.isValid());
684+
685+
LineModificationInfos updateSide2ReactiveValidity = LineModificationInfos.builder()
686+
.equipmentId("line1")
687+
.q2MeasurementValue(new AttributeModification<>(MEASUREMENT_Q_VALUE, OperationType.SET))
688+
.q2MeasurementValidity(new AttributeModification<>(true, OperationType.SET))
689+
.build();
690+
updateSide2ReactiveValidity.toModification().apply(getNetwork());
691+
assertTrue(addedReactiveSide2.isValid());
692+
}
693+
694+
@Test
695+
void testCreateMeasurementsExtensionWhenMissing() {
696+
Line line = getNetwork().getLine("line2");
697+
assertNull(line.getExtension(Measurements.class));
698+
699+
LineModificationInfos lineModificationInfos = LineModificationInfos.builder()
700+
.equipmentId("line2")
701+
.p1MeasurementValidity(new AttributeModification<>(true, OperationType.SET))
702+
.p1MeasurementValue(new AttributeModification<>(MEASUREMENT_P_VALUE, OperationType.SET))
703+
.q1MeasurementValidity(new AttributeModification<>(false, OperationType.SET))
704+
.q1MeasurementValue(new AttributeModification<>(MEASUREMENT_Q_VALUE, OperationType.SET))
705+
.build();
706+
lineModificationInfos.toModification().apply(getNetwork());
707+
708+
Measurements<?> measurements = (Measurements<?>) line.getExtension(Measurements.class);
709+
assertNotNull(measurements);
710+
711+
Measurement p1Measurement = measurements.getMeasurements(Measurement.Type.ACTIVE_POWER).stream()
712+
.filter(m -> m.getSide() == ThreeSides.ONE)
713+
.findFirst()
714+
.orElseThrow();
715+
assertEquals(10.0, p1Measurement.getValue());
716+
assertTrue(p1Measurement.isValid());
717+
718+
Measurement q1Measurement = measurements.getMeasurements(Measurement.Type.REACTIVE_POWER).stream()
719+
.filter(m -> m.getSide() == ThreeSides.ONE)
720+
.findFirst()
721+
.orElseThrow();
722+
assertEquals(-10.0, q1Measurement.getValue());
723+
assertFalse(q1Measurement.isValid());
724+
}
725+
726+
@Test
727+
void testCreateMeasurementsExtensionWhenMissingOnlyWithValue() {
728+
Line line = getNetwork().getLine("line2");
729+
assertNull(line.getExtension(Measurements.class));
730+
731+
LineModificationInfos lineModificationInfos = LineModificationInfos.builder()
732+
.equipmentId("line2")
733+
.p1MeasurementValue(new AttributeModification<>(MEASUREMENT_P_VALUE, OperationType.SET))
734+
.q1MeasurementValue(new AttributeModification<>(MEASUREMENT_Q_VALUE, OperationType.SET))
735+
.build();
736+
lineModificationInfos.toModification().apply(getNetwork());
737+
738+
Measurements<?> measurements = (Measurements<?>) line.getExtension(Measurements.class);
739+
assertNotNull(measurements);
740+
741+
Measurement p1Measurement = measurements.getMeasurements(Measurement.Type.ACTIVE_POWER).stream()
742+
.filter(m -> m.getSide() == ThreeSides.ONE)
743+
.findFirst()
744+
.orElseThrow();
745+
assertEquals(10.0, p1Measurement.getValue());
746+
assertTrue(p1Measurement.isValid()); // a Measurement is valid by default
747+
748+
Measurement q1Measurement = measurements.getMeasurements(Measurement.Type.REACTIVE_POWER).stream()
749+
.filter(m -> m.getSide() == ThreeSides.ONE)
750+
.findFirst()
751+
.orElseThrow();
752+
assertEquals(-10.0, q1Measurement.getValue());
753+
assertTrue(q1Measurement.isValid());
754+
}
755+
756+
@Test
757+
void testCreateMeasurementsExtensionWhenMissingOnlyWithFalseValidity() {
758+
Line line = getNetwork().getLine("line2");
759+
assertNull(line.getExtension(Measurements.class));
760+
761+
LineModificationInfos lineModificationInfos = LineModificationInfos.builder()
762+
.equipmentId("line2")
763+
.p1MeasurementValidity(new AttributeModification<>(false, OperationType.SET))
764+
.q1MeasurementValidity(new AttributeModification<>(false, OperationType.SET))
765+
.build();
766+
lineModificationInfos.toModification().apply(getNetwork());
767+
768+
Measurements<?> measurements = (Measurements<?>) line.getExtension(Measurements.class);
769+
assertNotNull(measurements);
770+
771+
Measurement p1Measurement = measurements.getMeasurements(Measurement.Type.ACTIVE_POWER).stream()
772+
.filter(m -> m.getSide() == ThreeSides.ONE)
773+
.findFirst()
774+
.orElseThrow();
775+
assertTrue(Double.isNaN(p1Measurement.getValue()));
776+
assertFalse(p1Measurement.isValid());
777+
778+
Measurement q1Measurement = measurements.getMeasurements(Measurement.Type.REACTIVE_POWER).stream()
779+
.filter(m -> m.getSide() == ThreeSides.ONE)
780+
.findFirst()
781+
.orElseThrow();
782+
assertTrue(Double.isNaN(q1Measurement.getValue()));
783+
assertFalse(q1Measurement.isValid());
784+
}
785+
786+
@Test
787+
void testCannotCreateMeasurementsExtensionWhenMissingWithOnlyTrueValidity() {
788+
Line line = getNetwork().getLine("line2");
789+
assertNull(line.getExtension(Measurements.class));
790+
791+
LineModificationInfos lineModificationInfos = LineModificationInfos.builder()
792+
.equipmentId("line2")
793+
.p1MeasurementValidity(new AttributeModification<>(true, OperationType.SET)) // not allowed by powsybl on extension creation
794+
.build();
795+
PowsyblException e = assertThrows(PowsyblException.class, () -> lineModificationInfos.toModification().apply(getNetwork()));
796+
assertEquals("Valid measurement cannot have an undefined value", e.getMessage());
797+
}
594798
}

0 commit comments

Comments
 (0)