Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@
/**
* This function removes all the temporary limits of the 'currentLimits' concerned and recreates them (except in case of deletion)
*/
protected void modifyTemporaryLimits(CurrentLimitsAdder limitsAdder, CurrentLimits currentLimits, OperationalLimitsGroupInfos.Applicability applicability) {

Check failure on line 397 in src/main/java/org/gridsuite/modification/modifications/olg/OperationalLimitsGroupModification.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 16 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=org.gridsuite%3Anetwork-modification&issues=AZ5QkIQ9pIqP4gyJNm1e&open=AZ5QkIQ9pIqP4gyJNm1e&pullRequest=191
CurrentLimitsModificationInfos currentLimitsInfos = olgModifInfos.getCurrentLimits();

// we create a mutable list of temporary limits to be able to remove the limits that are modified in this current modification
Expand All @@ -415,9 +415,13 @@
}
}

// tracks whether at least one input actually applied a change (created / modified /
// deleted a temporary limit); limits ignored by validation (missing fields, duplicates,
// no match...) do not count
boolean atLeastOneLimitApplied = false;
if (currentLimitsInfos != null && currentLimitsInfos.getTemporaryLimits() != null) {
for (CurrentTemporaryLimitModificationInfos limit : currentLimitsInfos.getTemporaryLimits()) {
applyTemporaryLimitModification(
atLeastOneLimitApplied |= applyTemporaryLimitModification(
limitsAdder,
currentLimits,
limit,
Expand All @@ -429,7 +433,7 @@
}

if (!unmodifiedTemporaryLimits.isEmpty()) {
if (areLimitsReplaced) {
if (areLimitsReplaced && atLeastOneLimitApplied) {
// this needs to be logged only if there are unmodifiedTemporaryLimits left.
// which means that they are going to be removed by the REPLACE mode
addToLogsOnSide(ReportNode.newRootReportNode()
Expand Down Expand Up @@ -492,6 +496,28 @@
return true;
}

/**
* A MODIFY row can only update an existing temporary limit, it cannot create one. Reject the row
* when no existing temporary limit matches its acceptable duration.
* @return true if the row must be skipped because it targets no existing temporary limit; false otherwise.
*/
private boolean isModifyWithoutMatch(
CurrentTemporaryLimitModificationInfos limit,
LoadingLimits.TemporaryLimit limitToModify,
OperationalLimitsGroupInfos.Applicability applicability) {
if (limit.getModificationType() != TemporaryLimitModificationType.MODIFY || limitToModify != null) {
return false;
}
addToLogsOnSide(ReportNode.newRootReportNode()
.withResourceBundles(NetworkModificationReportResourceBundle.BASE_NAME)
.withMessageTemplate("network.modification.temporaryLimitsNoMatch")
.withUntypedValue(LIMIT_ACCEPTABLE_DURATION, limit.getAcceptableDuration().getValue())
.withSeverity(TypedValue.WARN_SEVERITY)
.build(),
applicability);
return true;
}

/**
* For ADD / MODIFY / MODIFY_OR_ADD, refuse to introduce a duplicate name or duration in the limit set.
* Conflicting limits being deleted in the same batch are not considered duplicates.
Expand Down Expand Up @@ -556,7 +582,7 @@
* @param limit modification to be applied to the limit
* @param unmodifiedTemporaryLimits list of all the unmodified limits that will be added at the end of the network modification
*/
private void applyTemporaryLimitModification(
private boolean applyTemporaryLimitModification(
CurrentLimitsAdder limitsAdder,
CurrentLimits networkCurrentLimits,
CurrentTemporaryLimitModificationInfos limit,
Expand All @@ -565,24 +591,29 @@
OperationalLimitsGroupInfos.Applicability applicability) {
CurrentLimitsModificationInfos currentLimitsInfos = olgModifInfos.getCurrentLimits();
if (!preModificationCheck(limit, applicability)) {
return;
return false;
}
LoadingLimits.TemporaryLimit limitToModify = networkCurrentLimits != null
? getTemporaryLimitToModify(networkCurrentLimits, limit, currentLimitsInfos)
: null;
if (isModifyWithoutMatch(limit, limitToModify, applicability)) {
return false;
}
if (wouldCreateDuplicate(workingTemporaryLimits, limit, applicability)) {
return;
return false;
}
int limitAcceptableDuration = limit.getAcceptableDuration().getValue();
double limitValue = hasValue(limit.getValue()) ? limit.getValue().getValue() : Double.MAX_VALUE;
String limitDurationToReport = String.valueOf(limitAcceptableDuration);
String limitValueToReport = limitValue == Double.MAX_VALUE ? NO_VALUE : String.valueOf(limitValue);
LoadingLimits.TemporaryLimit limitToModify = null;
if (networkCurrentLimits != null) {
limitToModify = getTemporaryLimitToModify(networkCurrentLimits, limit, currentLimitsInfos);
// this limit is modified by the network modification so we remove it from the list of unmodified temporary limits
unmodifiedTemporaryLimits.removeIf(temporaryLimit -> temporaryLimit.getAcceptableDuration() == limitAcceptableDuration);
}
if (limitToModify == null && mayCreateLimit(limit.getModificationType())) {
createTemporaryLimit(limitsAdder, limit, limitDurationToReport, limitValueToReport, limitValue, limitAcceptableDuration, applicability);
workingTemporaryLimits.put(limitAcceptableDuration, limit.getName().getValue());
return true;
} else if (limitToModify != null) {
// the limit already exists
if (limit.getModificationType() == TemporaryLimitModificationType.DELETE) {
Expand All @@ -600,16 +631,9 @@
modifyTemporaryLimit(limitsAdder, limit, limitToModify, limitValue, limitDurationToReport, limitAcceptableDuration, applicability);
workingTemporaryLimits.put(limitAcceptableDuration, limit.getName().getValue());
}
} else if (limit.getModificationType() == TemporaryLimitModificationType.MODIFY) {
// invalid modification
addToLogsOnSide(ReportNode.newRootReportNode()
.withResourceBundles(NetworkModificationReportResourceBundle.BASE_NAME)
.withMessageTemplate("network.modification.temporaryLimitsNoMatch")
.withUntypedValue(LIMIT_ACCEPTABLE_DURATION, limitAcceptableDuration)
.withSeverity(TypedValue.WARN_SEVERITY)
.build(),
applicability);
return true;
}
return false;
}

/**
Expand Down Expand Up @@ -668,10 +692,10 @@
// Check if there are any actual changes
boolean nameChanged = !limitToModify.getName().equals(finalName);
boolean valueChanged = Double.compare(limitToModify.getValue(), finalValue) != 0;
String finalValueToReport = finalValue == Double.MAX_VALUE ? NO_VALUE : String.valueOf(finalValue);

if (valueChanged && !nameChanged) {
// only the value changes
String finalValueToReport = finalValue == Double.MAX_VALUE ? NO_VALUE : String.valueOf(finalValue);
addToLogsOnSide(ReportNode.newRootReportNode()
.withResourceBundles(NetworkModificationReportResourceBundle.BASE_NAME)
.withMessageTemplate("network.modification.temporaryLimitValueModified.name")
Expand All @@ -684,13 +708,13 @@
.withSeverity(TypedValue.DETAIL_SEVERITY)
.build(),
applicability);
} else if (nameChanged || valueChanged) {

Check warning on line 711 in src/main/java/org/gridsuite/modification/modifications/olg/OperationalLimitsGroupModification.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this expression which always evaluates to "false"

See more on https://sonarcloud.io/project/issues?id=org.gridsuite%3Anetwork-modification&issues=AZ5QkIQ9pIqP4gyJNm1d&open=AZ5QkIQ9pIqP4gyJNm1d&pullRequest=191
// log only if there is at least one actual modification
addToLogsOnSide(ReportNode.newRootReportNode()
.withResourceBundles(NetworkModificationReportResourceBundle.BASE_NAME)
.withMessageTemplate("network.modification.temporaryLimitModified.name")
.withUntypedValue(NAME, finalName)
.withUntypedValue(VALUE, finalValue)
.withUntypedValue(VALUE, finalValueToReport)
.withUntypedValue(DURATION, limitAcceptableDuration)
.withSeverity(TypedValue.DETAIL_SEVERITY)
.build(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ network.modification.temporaryLimitsReplaced = Previous temporary limits were re
network.modification.temporaryLimitsMissingInfo = Missing info (name or duration) to find temporary limit to ${modificationType}: ignored
network.modification.temporaryLimitsMissingModificationType = Missing modification type for temporary limit: ignored
network.modification.temporaryLimitsDuplicate = Duplicate name or duration for temporary limit ${name} (duration: ${duration}) to ${modificationType}: ignored
network.modification.temporaryLimitsNoMatch = No existing temporary limit found with acceptableDuration = ${limitAcceptableDuration} matching is based on acceptableDuration if that helps
network.modification.temporaryLimitsNoMatch = No existing temporary limit found with acceptableDuration=${limitAcceptableDuration}: ignored
network.modification.temporaryLimitsWrongModification = Temporary limit modification type can only be ADD when limit group modification type is not MODIFY: switched from ${modificationType} to ADD
network.modification.terminal1Disconnected = Equipment with id=${id} disconnected on side 1
network.modification.terminal2Disconnected = Equipment with id=${id} disconnected on side 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,8 +437,7 @@ private enum MissingField { NAME, DURATION }
/**
* Verify that a temporary limit modification with either {@code name} or {@code acceptableDuration}
* missing is skipped and emits a {@code temporaryLimitsMissingInfo} log, for every supported
* {@link TemporaryLimitModificationType}. When the temporary-limit-level type is REPLACE, pre-existing
* limits are dropped by REPLACE semantics; otherwise they remain untouched.
* {@link TemporaryLimitModificationType}.
*/
@ParameterizedTest(name = "[{index}] {0} with missing {1} should log temporaryLimitsMissingInfo and skip the change")
@MethodSource("missingTemporaryLimitFieldCases")
Expand All @@ -454,8 +453,9 @@ void testTemporaryLimitMissingFieldIsSkipped(TemporaryLimitModificationType op,
.getOperationalLimitsGroup1("DEFAULT").orElse(null))
.getCurrentLimits().orElse(null);
assertNotNull(limits);
int expectedSize = (op == TemporaryLimitModificationType.REPLACE) ? 0 : 2;
assertEquals(expectedSize, limits.getTemporaryLimits().size());
// the only input is invalid, so nothing is applied and the existing temporary limits
// are kept, including in REPLACE mode
assertEquals(2, limits.getTemporaryLimits().size());
assertLogMessageWithoutRank(
"Missing info (name or duration) to find temporary limit to " + op + ": ignored",
"network.modification.temporaryLimitsMissingInfo", reportNode);
Expand Down Expand Up @@ -1105,7 +1105,7 @@ private void assertAfterNetworkModificationApplication(ReportNode reportNode) {
assertLogMessageWithoutRank("Limit set DEFAULT has been modified on side 1", "network.modification.operationalLimitsGroupModified", reportNode);
assertLogMessageWithoutRank("Previous temporary limits were removed", "network.modification.temporaryLimitsReplaced", reportNode);
assertLogMessageWithoutRank("Cannot add DEFAULT operational limit group, one with the given name already exists", "network.modification.tabular.modification.exception", reportNode);
assertLogMessageWithoutRank("No existing temporary limit found with acceptableDuration = 3 matching is based on acceptableDuration if that helps", "network.modification.temporaryLimitsNoMatch", reportNode);
assertLogMessageWithoutRank("No existing temporary limit found with acceptableDuration=3: ignored", "network.modification.temporaryLimitsNoMatch", reportNode);
assertLogMessageWithoutRank("limit set selected on side 2 : group0", "network.modification.limitSetSelectedOnSide2", reportNode);
assertLogMessageWithoutRank("Limit set group0 has replaced the existing limit sets on side 2", "network.modification.operationalLimitsGroupReplaced", reportNode);
assertLogMessageWithoutRank("Limit set DEFAULT added on side 1", "network.modification.operationalLimitsGroupAdded", reportNode);
Expand Down
Loading