Skip to content

feat(ByFilterAssignment): add reactive power measurement attributes for static var compensator#198

Open
dbraquart wants to merge 8 commits into
mainfrom
dbraquart/add-measurement-for-cspr
Open

feat(ByFilterAssignment): add reactive power measurement attributes for static var compensator#198
dbraquart wants to merge 8 commits into
mainfrom
dbraquart/add-measurement-for-cspr

Conversation

@dbraquart

@dbraquart dbraquart commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

PR Summary

Because there is currently no static var compensator modification in GridSuite, we add the possibility to change the reactive power measurement value/validity with the "Modification by filter" exisiting modification.

To update a reactive power measurement, we just call existing function used in InjectionModification class.

In this PR we also refacto a little bit to regroup all "measurement" util functions in a new file, and we now use a single "upsertMeasurement" function for all cases (injections, branches, voltage level, by-filter assignement)

Signed-off-by: David BRAQUART <[email protected]>
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds read/write support for reactive power measurement value and validity on StaticVarCompensator via a new field handler, centralizes measurement upsert logic in MeasurementUtils, updates modification classes to use the utility, wires FieldUtils dispatcher, and adds an integration test.

Changes

Static Var Compensator Reactive Power Measurement Support

Layer / File(s) Summary
Static Var Compensator reactive power measurement field handler
src/main/java/org/gridsuite/modification/dto/byfilter/equipmentfield/StaticVarCompensatorField.java
New StaticVarCompensatorField enum with getReferenceValue and setNewValue to read/write reactive power measurement value and validity on a StaticVarCompensator, creating the Measurements extension when absent.
Measurement utilities
src/main/java/org/gridsuite/modification/utils/MeasurementUtils.java
New MeasurementUtils provides getExistingMeasurement(...), getExistingSideMeasurement(...), side-aware upsertSideMeasurement(...), and updateMeasurementValidity(...) to centralize measurement lookup/upsert and validity property mapping.
AbstractInjectionModification measurement refactor
src/main/java/org/gridsuite/modification/modifications/AbstractInjectionModification.java
Delegates measurement upserts to MeasurementUtils.upsertMeasurement, removes private helper methods, and updates imports.
AbstractBranchModification measurement refactor
src/main/java/org/gridsuite/modification/modifications/AbstractBranchModification.java
Replaces local per-side upsert logic with MeasurementUtils.upsertSideMeasurement and removes related helpers and constants.
VoltageLevelModification measurement wiring
src/main/java/org/gridsuite/modification/modifications/VoltageLevelModification.java
Uses shared upsertMeasurement for BusbarSection voltage measurements and removes local helper.
FieldUtils dispatcher integration
src/main/java/org/gridsuite/modification/dto/byfilter/equipmentfield/FieldUtils.java
getFieldValue and setFieldValue now route STATIC_VAR_COMPENSATOR equipment type to StaticVarCompensatorField methods.
Integration test for static var compensator by-assignment modifications
src/test/java/org/gridsuite/modification/modifications/byfilter/assignment/StaticVarCompensatorModificationByAssignmentTest.java
New test creates two compensators, applies assignments that set reactive power measurement value on one and validity on the other, and asserts measurements were created/updated accordingly.
ModificationUtils cleanup
src/main/java/org/gridsuite/modification/utils/ModificationUtils.java
Removed the old measurement validity constant and the updateMeasurementValidity(...) method; validity handling moved to MeasurementUtils.

Suggested reviewers

  • achour94
  • antoinebhs
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding reactive power measurement attributes for static var compensators in the ByFilterAssignment modification mechanism.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description accurately describes the main changes: adding static var compensator reactive power measurement support via ByFilterAssignment and refactoring measurement utility functions.

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


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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/main/java/org/gridsuite/modification/modifications/AbstractInjectionModification.java (1)

63-101: 🏗️ Heavy lift

Refactor upsertMeasurement to reduce branching complexity.

Line 63 introduces a method that now mixes selection, update/create branching, and reporting, which is why complexity remains high. Please split into small helpers (e.g., updateMeasurement, createMeasurement, appendReportIfNeeded) to bring it under the quality threshold while keeping behavior identical.

🤖 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
`@src/main/java/org/gridsuite/modification/modifications/AbstractInjectionModification.java`
around lines 63 - 101, The upsertMeasurement method mixes selection,
update/create branching, and reporting; split it into small helpers to reduce
complexity while preserving behavior: extract an updateMeasurement(Measurement
measurement, Double value, Boolean requestedValidity, List<ReportNode> reports)
that handles the value change (uses measurement.getValue(),
measurement.setValue()) and validity change (uses measurement.isValid() and
ModificationUtils.updateMeasurementValidity()), a
createMeasurement(Measurements<?> measurements, Measurement.Type type, Double
value, Boolean requestedValidity, List<ReportNode> reports) that builds the new
measurement via
measurements.newMeasurement().setId(...).setType(...).setValue(...).setValid(...).add(),
and an appendReportIfNeeded(Object oldVal, Object newVal, String label,
List<ReportNode> reports) that wraps
ModificationUtils.buildModificationReport(..., TypedValue.INFO_SEVERITY) and
adds to reports when non-null; then make upsertMeasurement call
getExistingMeasurement(...) and delegate to updateMeasurement or
createMeasurement so all report creation and branching logic is localized to the
new helpers and existing public behavior/labels (measurementType + VALUE /
VALIDITY) is preserved.

Source: Linters/SAST tools

src/test/java/org/gridsuite/modification/modifications/byfilter/assignment/StaticVarCompensatorModificationByAssignmentTest.java (1)

78-78: ⚡ Quick win

Remove unnecessary casts to Measurements<?>.

The getExtension(Measurements.class) method returns the correct type without requiring an explicit cast (same issue as in StaticVarCompensatorField).

♻️ Proposed fix
-        Measurements<?> ms1 = (Measurements<?>) svc1.getExtension(Measurements.class);
+        Measurements<?> ms1 = svc1.getExtension(Measurements.class);

Apply the same change on line 82 for ms2.

Also applies to: 82-82

🤖 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
`@src/test/java/org/gridsuite/modification/modifications/byfilter/assignment/StaticVarCompensatorModificationByAssignmentTest.java`
at line 78, In StaticVarCompensatorModificationByAssignmentTest remove the
unnecessary explicit casts to Measurements<?>: change the assignments where ms1
and ms2 are obtained from svc1.getExtension(Measurements.class) and
svc2.getExtension(Measurements.class) to rely on the method's generic return
type (i.e., assign directly to Measurements<?> ms1 and Measurements<?> ms2
without the (Measurements<?>) cast) so the variables use the correct inferred
type.
src/main/java/org/gridsuite/modification/dto/byfilter/equipmentfield/StaticVarCompensatorField.java (1)

28-28: ⚡ Quick win

Remove unnecessary casts to Measurements<?>.

The getExtension(Class) method already returns the extension type matching the class parameter, making the explicit cast redundant.

♻️ Proposed fix
-        Measurements<?> measurements = (Measurements<?>) svc.getExtension(Measurements.class);
+        Measurements<?> measurements = svc.getExtension(Measurements.class);

Apply the same change on line 44.

Also applies to: 44-44

🤖 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
`@src/main/java/org/gridsuite/modification/dto/byfilter/equipmentfield/StaticVarCompensatorField.java`
at line 28, Remove the redundant explicit cast to Measurements<?> when calling
svc.getExtension(Measurements.class) in StaticVarCompensatorField; update the
expressions using svc.getExtension(Measurements.class) to rely on the method's
generic return type (i.e., drop the "(Measurements<?>)" cast) and do the same
for the other identical occurrence in this class (the second
svc.getExtension(Measurements.class) usage).

Source: Linters/SAST tools

🤖 Prompt for all review comments with 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.

Inline comments:
In
`@src/main/java/org/gridsuite/modification/dto/byfilter/equipmentfield/StaticVarCompensatorField.java`:
- Line 51: In StaticVarCompensatorField where
REACTIVE_POWER_MEASUREMENT_VALIDITY calls upsertMeasurement(...,
Measurement.Type.REACTIVE_POWER, null, Boolean.parseBoolean(newValue), null),
replace the silent Boolean.parseBoolean behavior with explicit validation: check
newValue for a case-insensitive exact "true" or "false" (e.g., equalsIgnoreCase)
and only pass the corresponding boolean to upsertMeasurement; for any other
value, throw an IllegalArgumentException (or return/report an error) so invalid
inputs are rejected rather than being treated as false. Ensure the validation is
applied at the same call site in StaticVarCompensatorField and keep the
upsertMeasurement invocation signature unchanged.

---

Nitpick comments:
In
`@src/main/java/org/gridsuite/modification/dto/byfilter/equipmentfield/StaticVarCompensatorField.java`:
- Line 28: Remove the redundant explicit cast to Measurements<?> when calling
svc.getExtension(Measurements.class) in StaticVarCompensatorField; update the
expressions using svc.getExtension(Measurements.class) to rely on the method's
generic return type (i.e., drop the "(Measurements<?>)" cast) and do the same
for the other identical occurrence in this class (the second
svc.getExtension(Measurements.class) usage).

In
`@src/main/java/org/gridsuite/modification/modifications/AbstractInjectionModification.java`:
- Around line 63-101: The upsertMeasurement method mixes selection,
update/create branching, and reporting; split it into small helpers to reduce
complexity while preserving behavior: extract an updateMeasurement(Measurement
measurement, Double value, Boolean requestedValidity, List<ReportNode> reports)
that handles the value change (uses measurement.getValue(),
measurement.setValue()) and validity change (uses measurement.isValid() and
ModificationUtils.updateMeasurementValidity()), a
createMeasurement(Measurements<?> measurements, Measurement.Type type, Double
value, Boolean requestedValidity, List<ReportNode> reports) that builds the new
measurement via
measurements.newMeasurement().setId(...).setType(...).setValue(...).setValid(...).add(),
and an appendReportIfNeeded(Object oldVal, Object newVal, String label,
List<ReportNode> reports) that wraps
ModificationUtils.buildModificationReport(..., TypedValue.INFO_SEVERITY) and
adds to reports when non-null; then make upsertMeasurement call
getExistingMeasurement(...) and delegate to updateMeasurement or
createMeasurement so all report creation and branching logic is localized to the
new helpers and existing public behavior/labels (measurementType + VALUE /
VALIDITY) is preserved.

In
`@src/test/java/org/gridsuite/modification/modifications/byfilter/assignment/StaticVarCompensatorModificationByAssignmentTest.java`:
- Line 78: In StaticVarCompensatorModificationByAssignmentTest remove the
unnecessary explicit casts to Measurements<?>: change the assignments where ms1
and ms2 are obtained from svc1.getExtension(Measurements.class) and
svc2.getExtension(Measurements.class) to rely on the method's generic return
type (i.e., assign directly to Measurements<?> ms1 and Measurements<?> ms2
without the (Measurements<?>) cast) so the variables use the correct inferred
type.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 09ab7277-abc3-4616-afdc-2638392d5f6a

📥 Commits

Reviewing files that changed from the base of the PR and between 6e97880 and ac9905b.

📒 Files selected for processing (4)
  • src/main/java/org/gridsuite/modification/dto/byfilter/equipmentfield/FieldUtils.java
  • src/main/java/org/gridsuite/modification/dto/byfilter/equipmentfield/StaticVarCompensatorField.java
  • src/main/java/org/gridsuite/modification/modifications/AbstractInjectionModification.java
  • src/test/java/org/gridsuite/modification/modifications/byfilter/assignment/StaticVarCompensatorModificationByAssignmentTest.java


assertThat(svc1Measurement.getValue()).isEqualTo(REACTIVE_POWER_MEASUREMENT_VALUE_FOR_SVC1);
assertThat(svc2Measurement.isValid()).isEqualTo(REACTIVE_POWER_MEASUREMENT_VALIDITY_FOR_SVC2);
}

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.

assert all 4 combinations

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes, I realize that the test updates both SVCs in the same way

@dbraquart dbraquart force-pushed the dbraquart/add-measurement-for-cspr branch from a27b0d7 to 94dad9c Compare June 12, 2026 13:52

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/main/java/org/gridsuite/modification/utils/MeasurementUtils.java (1)

81-98: Handle validity-only upsert explicitly (NaN value vs invalid/valid constraints)

In MeasurementUtils.upsertSideMeasurement, when adding a new measurement with requestedValue == null and requestedValidity != null, setValue() is not called; the resulting measurement value is expected to be NaN (e.g., LineModificationTest asserts Double.isNaN(...getValue()) for validity-only updates).

powsybl also rejects the case where requestedValidity == true while the value is undefined on extension creation (see testCannotCreateMeasurementsExtensionWhenMissingWithOnlyTrueValidity, message: "Valid measurement cannot have an undefined value"), so this behavior depends on requestedValidity:

  • false validity: allowed with NaN value
  • true validity: fails unless a value is provided

Recommendation: document this contract in the method (and/or add a small guard/message when creating new measurements with requestedValidity == true but requestedValue == null) to avoid surprise failures.

🤖 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 `@src/main/java/org/gridsuite/modification/utils/MeasurementUtils.java` around
lines 81 - 98, In MeasurementUtils.upsertSideMeasurement the new-measurement
path must explicitly handle the case where requestedValue == null but
requestedValidity != null: if requestedValidity is false, call
measurementAdder.setValue(Double.NaN) and add the corresponding
ModificationUtils.buildModificationReport for the VALUE (same
severity/logFieldPrefix usage) so the system records the NaN value; if
requestedValidity is true, fail fast by throwing an IllegalArgumentException (or
return an error/report) with a clear message ("Valid measurement cannot have an
undefined value") instead of creating an invalid measurement; update the method
comment to document this contract; use the existing symbols measurementAdder,
requestedValue, requestedValidity, ModificationUtils.buildModificationReport and
logFieldPrefix to locate changes.
🤖 Prompt for all review comments with 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.

Nitpick comments:
In `@src/main/java/org/gridsuite/modification/utils/MeasurementUtils.java`:
- Around line 81-98: In MeasurementUtils.upsertSideMeasurement the
new-measurement path must explicitly handle the case where requestedValue ==
null but requestedValidity != null: if requestedValidity is false, call
measurementAdder.setValue(Double.NaN) and add the corresponding
ModificationUtils.buildModificationReport for the VALUE (same
severity/logFieldPrefix usage) so the system records the NaN value; if
requestedValidity is true, fail fast by throwing an IllegalArgumentException (or
return an error/report) with a clear message ("Valid measurement cannot have an
undefined value") instead of creating an invalid measurement; update the method
comment to document this contract; use the existing symbols measurementAdder,
requestedValue, requestedValidity, ModificationUtils.buildModificationReport and
logFieldPrefix to locate changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: be5d3c0b-4c84-4cd1-b186-95c982589ee3

📥 Commits

Reviewing files that changed from the base of the PR and between 94dad9c and 1d1916f.

📒 Files selected for processing (4)
  • src/main/java/org/gridsuite/modification/modifications/AbstractBranchModification.java
  • src/main/java/org/gridsuite/modification/modifications/VoltageLevelModification.java
  • src/main/java/org/gridsuite/modification/utils/MeasurementUtils.java
  • src/main/java/org/gridsuite/modification/utils/ModificationUtils.java
💤 Files with no reviewable changes (1)
  • src/main/java/org/gridsuite/modification/utils/ModificationUtils.java

@sonarqubecloud

Copy link
Copy Markdown

@dbraquart dbraquart requested a review from benrejebmoh June 12, 2026 15:33
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.

2 participants