@@ -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