|
15 | 15 | import org.gridsuite.modification.NetworkModificationException; |
16 | 16 | import org.gridsuite.modification.dto.*; |
17 | 17 | import org.gridsuite.modification.utils.ModificationUtils; |
| 18 | +import org.springframework.util.CollectionUtils; |
18 | 19 | import org.springframework.util.StringUtils; |
19 | 20 |
|
20 | 21 | import java.util.*; |
@@ -65,20 +66,24 @@ protected void modifyBranch(Branch<?> branch, BranchModificationInfos branchModi |
65 | 66 | } |
66 | 67 |
|
67 | 68 | List<ReportNode> activeOLGReports = new ArrayList<>(); |
68 | | - List<ReportNode> olgReports = new ArrayList<>(); |
69 | 69 |
|
| 70 | + ReportNode limitsReportNode = null; |
70 | 71 | boolean modifyOLG = branchModificationInfos.getEnableOLGModification() == null |
71 | | - || branchModificationInfos.getEnableOLGModification(); |
72 | | - if (modifyOLG && branchModificationInfos.getOperationalLimitsGroups() != null) { |
73 | | - modifyOperationalLimitsGroups(branch, branchModificationInfos.getOperationalLimitsGroups(), olgReports); |
| 72 | + || branchModificationInfos.getEnableOLGModification(); |
| 73 | + |
| 74 | + if (modifyOLG && !CollectionUtils.isEmpty(branchModificationInfos.getOperationalLimitsGroups())) { |
| 75 | + limitsReportNode = subReportNode.newReportNode().withMessageTemplate("network.modification.limits").add(); |
| 76 | + ReportNode limitSetsReportNode = limitsReportNode.newReportNode().withMessageTemplate("network.modification.limitsSets").add(); |
| 77 | + modifyOperationalLimitsGroups(branch, branchModificationInfos.getOperationalLimitsGroups(), limitSetsReportNode); |
74 | 78 | } |
75 | 79 |
|
76 | 80 | applySelectedOLGs(branch, activeOLGReports); |
77 | 81 |
|
78 | | - if (!activeOLGReports.isEmpty() || !olgReports.isEmpty()) { |
79 | | - ReportNode limitsReportNode = subReportNode.newReportNode().withMessageTemplate("network.modification.limits").add(); |
| 82 | + if (!activeOLGReports.isEmpty()) { |
| 83 | + if (limitsReportNode == null) { |
| 84 | + limitsReportNode = subReportNode.newReportNode().withMessageTemplate("network.modification.limits").add(); |
| 85 | + } |
80 | 86 | ModificationUtils.getInstance().reportModifications(limitsReportNode, activeOLGReports, "network.modification.activeLimitsSets"); |
81 | | - ModificationUtils.getInstance().reportModifications(limitsReportNode, olgReports, "network.modification.limitsSets"); |
82 | 87 | } |
83 | 88 | updateConnections(branch, branchModificationInfos); |
84 | 89 | } |
@@ -190,26 +195,33 @@ private void detectApplicabilityChange(Branch<?> branch, List<OperationalLimitsG |
190 | 195 | } |
191 | 196 | } |
192 | 197 |
|
193 | | - private void modifyOperationalLimitsGroups(Branch<?> branch, List<OperationalLimitsGroupModificationInfos> operationalLimitsInfos, List<ReportNode> olgReports) { |
| 198 | + private void modifyOperationalLimitsGroups(Branch<?> branch, |
| 199 | + List<OperationalLimitsGroupModificationInfos> operationalLimitsInfos, |
| 200 | + ReportNode limitSetsReportNode) { |
| 201 | + |
194 | 202 | for (OperationalLimitsGroupModificationInfos opLGModifInfos : operationalLimitsInfos) { |
195 | 203 | if (opLGModifInfos.getModificationType() == null) { |
196 | 204 | continue; |
197 | 205 | } |
| 206 | + |
| 207 | + ArrayList<ReportNode> olgSetReports = new ArrayList<>(); |
| 208 | + |
198 | 209 | OperationalLimitsGroupInfos.Applicability applicability = opLGModifInfos.getApplicability(); |
199 | 210 | // here the modifications on an applicability EQUIPMENT are separated into two separate applications of both sides |
200 | 211 | // because iidm has two separated sets of opLGs on the network object (and for better logs) |
201 | 212 |
|
202 | | - detectApplicabilityChange(branch, operationalLimitsInfos, opLGModifInfos, olgReports); |
203 | | - |
| 213 | + detectApplicabilityChange(branch, operationalLimitsInfos, opLGModifInfos, olgSetReports); |
204 | 214 | if (applicability == SIDE1 |
205 | | - || applicability == EQUIPMENT) { |
| 215 | + || applicability == EQUIPMENT) { |
206 | 216 | OperationalLimitsGroup operationalLimitsGroup1 = branch.getOperationalLimitsGroup1(opLGModifInfos.getId()).orElse(null); |
207 | | - applyModificationToOperationalLimitsGroup(branch::newOperationalLimitsGroup1, opLGModifInfos, operationalLimitsGroup1, olgReports, SIDE1); |
| 217 | + applyModificationToOperationalLimitsGroup(branch::newOperationalLimitsGroup1, opLGModifInfos, operationalLimitsGroup1, |
| 218 | + SIDE1, limitSetsReportNode); |
208 | 219 | } |
209 | 220 | if (applicability == SIDE2 |
210 | | - || applicability == EQUIPMENT) { |
| 221 | + || applicability == EQUIPMENT) { |
211 | 222 | OperationalLimitsGroup operationalLimitsGroup2 = branch.getOperationalLimitsGroup2(opLGModifInfos.getId()).orElse(null); |
212 | | - applyModificationToOperationalLimitsGroup(branch::newOperationalLimitsGroup2, opLGModifInfos, operationalLimitsGroup2, olgReports, SIDE2); |
| 223 | + applyModificationToOperationalLimitsGroup(branch::newOperationalLimitsGroup2, opLGModifInfos, operationalLimitsGroup2, |
| 224 | + SIDE2, limitSetsReportNode); |
213 | 225 | } |
214 | 226 | } |
215 | 227 | } |
@@ -411,82 +423,200 @@ protected void applyModificationToOperationalLimitsGroup( |
411 | 423 | Function<String, OperationalLimitsGroup> groupFactory, |
412 | 424 | OperationalLimitsGroupModificationInfos opLGModificationInfos, |
413 | 425 | OperationalLimitsGroup modifiedOperationalLimitsGroup, |
414 | | - List<ReportNode> operationalLimitsGroupReports, |
415 | | - OperationalLimitsGroupInfos.Applicability applicability |
| 426 | + OperationalLimitsGroupInfos.Applicability applicability, |
| 427 | + ReportNode limitsSetsReportNode |
416 | 428 | ) { |
417 | 429 | switch (opLGModificationInfos.getModificationType()) { |
418 | 430 | case OperationalLimitsGroupModificationType.MODIFY_OR_ADD: { |
419 | 431 | if (modifiedOperationalLimitsGroup == null) { |
420 | | - addOpLG(groupFactory, opLGModificationInfos, modifiedOperationalLimitsGroup, operationalLimitsGroupReports, applicability); |
| 432 | + addOpLG(groupFactory, opLGModificationInfos, modifiedOperationalLimitsGroup, applicability, limitsSetsReportNode); |
421 | 433 | } else { |
422 | | - modifyOLG(opLGModificationInfos, modifiedOperationalLimitsGroup, operationalLimitsGroupReports, applicability); |
| 434 | + modifyOLG(opLGModificationInfos, modifiedOperationalLimitsGroup, applicability, limitsSetsReportNode); |
423 | 435 | } |
424 | 436 | } break; |
425 | 437 | case OperationalLimitsGroupModificationType.MODIFY: { |
426 | 438 | if (modifiedOperationalLimitsGroup == null) { |
427 | 439 | throw new PowsyblException("Cannot modify operational limit group " + opLGModificationInfos.getId() + " which has not been found in equipment given side"); |
428 | 440 | } |
429 | | - modifyOLG(opLGModificationInfos, modifiedOperationalLimitsGroup, operationalLimitsGroupReports, applicability); |
| 441 | + modifyOLG(opLGModificationInfos, modifiedOperationalLimitsGroup, applicability, limitsSetsReportNode); |
430 | 442 | } break; |
431 | 443 | case OperationalLimitsGroupModificationType.ADD: { |
432 | | - addOpLG(groupFactory, opLGModificationInfos, modifiedOperationalLimitsGroup, operationalLimitsGroupReports, applicability); |
| 444 | + addOpLG(groupFactory, opLGModificationInfos, modifiedOperationalLimitsGroup, applicability, limitsSetsReportNode); |
433 | 445 | } break; |
434 | 446 | case OperationalLimitsGroupModificationType.REPLACE: { |
435 | | - replaceOpLG(groupFactory, opLGModificationInfos, modifiedOperationalLimitsGroup, operationalLimitsGroupReports, applicability); |
| 447 | + replaceOpLG(groupFactory, opLGModificationInfos, modifiedOperationalLimitsGroup, applicability, limitsSetsReportNode); |
436 | 448 | } break; |
| 449 | + default: break; |
437 | 450 | } |
438 | 451 | } |
439 | 452 |
|
440 | | - private void replaceOpLG(Function<String, OperationalLimitsGroup> groupFactory, OperationalLimitsGroupModificationInfos opLGModificationInfos, OperationalLimitsGroup modifiedOperationalLimitsGroup, List<ReportNode> operationalLimitsGroupReports, OperationalLimitsGroupInfos.Applicability applicability) { |
| 453 | + private void replaceOpLG(Function<String, OperationalLimitsGroup> groupFactory, |
| 454 | + OperationalLimitsGroupModificationInfos opLGModificationInfos, |
| 455 | + OperationalLimitsGroup modifiedOperationalLimitsGroup, |
| 456 | + OperationalLimitsGroupInfos.Applicability applicability, |
| 457 | + ReportNode limitsSetsReportNode) { |
| 458 | + |
| 459 | + List<ReportNode> limitSetReports = new ArrayList<>(); |
441 | 460 | if (modifiedOperationalLimitsGroup != null) { |
442 | 461 | modifiedOperationalLimitsGroup.removeCurrentLimits(); |
| 462 | + removeAllProperties(modifiedOperationalLimitsGroup, limitSetReports); |
443 | 463 | } |
| 464 | + |
444 | 465 | OperationalLimitsGroup newOperationalLimitsGroup = groupFactory.apply(opLGModificationInfos.getId()); |
445 | | - operationalLimitsGroupReports.add(ReportNode.newRootReportNode() |
446 | | - .withAllResourceBundlesFromClasspath() |
| 466 | + modifyCurrentLimits(opLGModificationInfos, newOperationalLimitsGroup.newCurrentLimits(), null, limitSetReports); |
| 467 | + addProperties(newOperationalLimitsGroup, opLGModificationInfos, limitSetReports); |
| 468 | + |
| 469 | + if (!CollectionUtils.isEmpty(limitSetReports)) { |
| 470 | + ReportNode reportNode = limitsSetsReportNode.newReportNode() |
447 | 471 | .withMessageTemplate("network.modification.operationalLimitsGroupReplaced") |
448 | 472 | .withUntypedValue(OPERATIONAL_LIMITS_GROUP_NAME, opLGModificationInfos.getId()) |
449 | 473 | .withUntypedValue(SIDE, applicability.toString()) |
450 | 474 | .withSeverity(TypedValue.INFO_SEVERITY) |
| 475 | + .add(); |
| 476 | + ModificationUtils.getInstance().reportModifications(reportNode, limitSetReports); |
| 477 | + } |
| 478 | + } |
| 479 | + |
| 480 | + private void addProperties(OperationalLimitsGroup limitsGroup, OperationalLimitsGroupModificationInfos operationalLimitsGroupInfos, List<ReportNode> limitSetsReports) { |
| 481 | + if (limitsGroup == null || CollectionUtils.isEmpty(operationalLimitsGroupInfos.getLimitsProperties())) { |
| 482 | + return; |
| 483 | + } |
| 484 | + |
| 485 | + operationalLimitsGroupInfos.getLimitsProperties().forEach((LimitsPropertyInfos property) -> { |
| 486 | + limitSetsReports.add(ReportNode.newRootReportNode() |
| 487 | + .withMessageTemplate("network.modification.propertyAdded") |
| 488 | + .withUntypedValue(NAME, property.name()) |
| 489 | + .withUntypedValue(VALUE, property.value()) |
| 490 | + .withSeverity(TypedValue.DETAIL_SEVERITY) |
451 | 491 | .build()); |
452 | | - modifyCurrentLimits(opLGModificationInfos, newOperationalLimitsGroup.newCurrentLimits(), null, operationalLimitsGroupReports); |
| 492 | + limitsGroup.setProperty(property.name(), property.value()); |
| 493 | + }); |
| 494 | + } |
| 495 | + |
| 496 | + private void removeAllProperties(OperationalLimitsGroup limitsGroup, List<ReportNode> limitSetsReports) { |
| 497 | + |
| 498 | + if (limitsGroup == null) { |
| 499 | + return; |
| 500 | + } |
| 501 | + |
| 502 | + Iterator<String> propertiesIt = limitsGroup.getPropertyNames().iterator(); |
| 503 | + while (propertiesIt.hasNext()) { |
| 504 | + String propertyName = propertiesIt.next(); |
| 505 | + limitsGroup.removeProperty(propertyName); |
| 506 | + limitSetsReports.add(ReportNode.newRootReportNode() |
| 507 | + .withMessageTemplate("network.modification.propertyDeleted") |
| 508 | + .withUntypedValue(NAME, propertyName) |
| 509 | + .withSeverity(TypedValue.DETAIL_SEVERITY).build()); |
| 510 | + } |
| 511 | + } |
| 512 | + |
| 513 | + private void modifyProperties(OperationalLimitsGroup limitsGroup, |
| 514 | + OperationalLimitsGroupModificationInfos operationalLimitsGroupInfos, |
| 515 | + List<ReportNode> limitSetsReports) { |
| 516 | + if (limitsGroup == null || operationalLimitsGroupInfos == null) { |
| 517 | + return; |
| 518 | + } |
| 519 | + |
| 520 | + Set<String> currentProperties = limitsGroup.getPropertyNames(); |
| 521 | + |
| 522 | + List<LimitsPropertyInfos> propertiesToModify = new ArrayList<>(); |
| 523 | + List<LimitsPropertyInfos> propertiesToAdd = new ArrayList<>(); |
| 524 | + List<String> propertiesToRemove; |
| 525 | + |
| 526 | + if (!CollectionUtils.isEmpty(operationalLimitsGroupInfos.getLimitsProperties())) { |
| 527 | + for (LimitsPropertyInfos propertyInfos : operationalLimitsGroupInfos.getLimitsProperties()) { |
| 528 | + if (currentProperties.contains(propertyInfos.name())) { |
| 529 | + propertiesToModify.add(propertyInfos); |
| 530 | + } else { |
| 531 | + propertiesToAdd.add(propertyInfos); |
| 532 | + } |
| 533 | + } |
| 534 | + |
| 535 | + propertiesToRemove = currentProperties.stream().filter( |
| 536 | + (String propertyName) -> propertiesToModify.stream().filter(propertyInfos -> |
| 537 | + propertyInfos.name().equals(propertyName)).toList().isEmpty()).toList(); |
| 538 | + } else { |
| 539 | + propertiesToRemove = new ArrayList<>(currentProperties); |
| 540 | + } |
| 541 | + |
| 542 | + propertiesToRemove.forEach((String propertyName) -> { |
| 543 | + limitsGroup.removeProperty(propertyName); |
| 544 | + limitSetsReports.add(ReportNode.newRootReportNode() |
| 545 | + .withMessageTemplate("network.modification.propertyDeleted") |
| 546 | + .withUntypedValue(NAME, propertyName) |
| 547 | + .withSeverity(TypedValue.DETAIL_SEVERITY).build()); |
| 548 | + }); |
| 549 | + |
| 550 | + propertiesToModify.forEach((LimitsPropertyInfos property) -> { |
| 551 | + // Skip changes when value does not change |
| 552 | + if (limitsGroup.getProperty(property.name()).equals(property.value())) { |
| 553 | + return; |
| 554 | + } |
| 555 | + limitSetsReports.add(ReportNode.newRootReportNode() |
| 556 | + .withMessageTemplate("network.modification.propertyChanged") |
| 557 | + .withUntypedValue(NAME, property.name()) |
| 558 | + .withUntypedValue("to", property.value()) |
| 559 | + .withUntypedValue("from", limitsGroup.getProperty(property.name())) |
| 560 | + .withSeverity(TypedValue.DETAIL_SEVERITY).build()); |
| 561 | + limitsGroup.setProperty(property.name(), property.value()); |
| 562 | + }); |
| 563 | + |
| 564 | + propertiesToAdd.forEach((LimitsPropertyInfos property) -> { |
| 565 | + limitSetsReports.add(ReportNode.newRootReportNode() |
| 566 | + .withMessageTemplate("network.modification.propertyAdded") |
| 567 | + .withUntypedValue(NAME, property.name()) |
| 568 | + .withUntypedValue(VALUE, property.value()) |
| 569 | + .withSeverity(TypedValue.DETAIL_SEVERITY) |
| 570 | + .build()); |
| 571 | + limitsGroup.setProperty(property.name(), property.value()); |
| 572 | + }); |
453 | 573 | } |
454 | 574 |
|
455 | 575 | private void modifyOLG( |
456 | 576 | OperationalLimitsGroupModificationInfos operationalLimitsGroupInfos, |
457 | 577 | OperationalLimitsGroup modifiedOperationalLimitsGroup, |
458 | | - List<ReportNode> olgsReports, |
459 | | - OperationalLimitsGroupInfos.Applicability applicability) { |
| 578 | + OperationalLimitsGroupInfos.Applicability applicability, |
| 579 | + ReportNode limitsSetsReportNode) { |
| 580 | + |
| 581 | + List<ReportNode> limitSetsReports = new ArrayList<>(); |
| 582 | + |
460 | 583 | modifiedOperationalLimitsGroup.getCurrentLimits().ifPresent(currentLimits -> { |
461 | | - List<ReportNode> limitsReports = new ArrayList<>(); |
462 | | - modifyCurrentLimits(operationalLimitsGroupInfos, modifiedOperationalLimitsGroup.newCurrentLimits(), currentLimits, limitsReports); |
463 | | - if (!limitsReports.isEmpty()) { |
464 | | - // operational limits group is logged only if it contains at least a change of limit |
465 | | - limitsReports.addFirst(ReportNode.newRootReportNode() |
466 | | - .withAllResourceBundlesFromClasspath() |
467 | | - .withMessageTemplate("network.modification.operationalLimitsGroupModified") |
468 | | - .withUntypedValue(OPERATIONAL_LIMITS_GROUP_NAME, operationalLimitsGroupInfos.getId()) |
469 | | - .withUntypedValue(SIDE, applicability.toString()) |
470 | | - .withSeverity(TypedValue.INFO_SEVERITY) |
471 | | - .build()); |
472 | | - olgsReports.addAll(limitsReports); |
| 584 | + modifyCurrentLimits(operationalLimitsGroupInfos, modifiedOperationalLimitsGroup.newCurrentLimits(), currentLimits, limitSetsReports); |
| 585 | + modifyProperties(modifiedOperationalLimitsGroup, operationalLimitsGroupInfos, limitSetsReports); |
| 586 | + |
| 587 | + if (!limitSetsReports.isEmpty()) { |
| 588 | + ReportNode limitSetReport = limitsSetsReportNode.newReportNode() |
| 589 | + .withMessageTemplate("network.modification.operationalLimitsGroupModified") |
| 590 | + .withUntypedValue(OPERATIONAL_LIMITS_GROUP_NAME, operationalLimitsGroupInfos.getId()) |
| 591 | + .withUntypedValue(SIDE, applicability.toString()) |
| 592 | + .withSeverity(TypedValue.INFO_SEVERITY).add(); |
| 593 | + ModificationUtils.getInstance().reportModifications(limitSetReport, limitSetsReports); |
473 | 594 | } |
474 | 595 | }); |
475 | 596 | } |
476 | 597 |
|
477 | | - private void addOpLG(Function<String, OperationalLimitsGroup> groupFactory, OperationalLimitsGroupModificationInfos operationalLimitsGroupInfos, OperationalLimitsGroup modifiedOperationalLimitsGroup, List<ReportNode> operationalLimitsGroupReports, OperationalLimitsGroupInfos.Applicability applicability) { |
| 598 | + private void addOpLG(Function<String, OperationalLimitsGroup> groupFactory, OperationalLimitsGroupModificationInfos operationalLimitsGroupInfos, |
| 599 | + OperationalLimitsGroup modifiedOperationalLimitsGroup, |
| 600 | + OperationalLimitsGroupInfos.Applicability applicability, ReportNode limitsSetsReportNode) { |
| 601 | + |
| 602 | + List<ReportNode> limitSetReports = new ArrayList<>(); |
478 | 603 | if (modifiedOperationalLimitsGroup != null) { |
479 | 604 | throw new PowsyblException("Cannot add " + modifiedOperationalLimitsGroup.getId() + " operational limit group, one with the given name already exists"); |
480 | 605 | } |
481 | 606 | OperationalLimitsGroup newOperationalLimitsGroup = groupFactory.apply(operationalLimitsGroupInfos.getId()); |
482 | | - operationalLimitsGroupReports.add(ReportNode.newRootReportNode() |
483 | | - .withAllResourceBundlesFromClasspath() |
| 607 | + modifyCurrentLimits(operationalLimitsGroupInfos, newOperationalLimitsGroup.newCurrentLimits(), |
| 608 | + newOperationalLimitsGroup.getCurrentLimits().orElse(null), limitSetReports); |
| 609 | + addProperties(newOperationalLimitsGroup, operationalLimitsGroupInfos, limitSetReports); |
| 610 | + |
| 611 | + if (!CollectionUtils.isEmpty(limitSetReports)) { |
| 612 | + ReportNode limitSetNode = limitsSetsReportNode.newReportNode() |
484 | 613 | .withMessageTemplate("network.modification.operationalLimitsGroupAdded") |
485 | 614 | .withUntypedValue(OPERATIONAL_LIMITS_GROUP_NAME, operationalLimitsGroupInfos.getId()) |
486 | 615 | .withUntypedValue(SIDE, applicability.toString()) |
487 | 616 | .withSeverity(TypedValue.INFO_SEVERITY) |
488 | | - .build()); |
489 | | - modifyCurrentLimits(operationalLimitsGroupInfos, newOperationalLimitsGroup.newCurrentLimits(), newOperationalLimitsGroup.getCurrentLimits().orElse(null), operationalLimitsGroupReports); |
| 617 | + .add(); |
| 618 | + ModificationUtils.getInstance().reportModifications(limitSetNode, limitSetReports); |
| 619 | + } |
490 | 620 | } |
491 | 621 |
|
492 | 622 | protected void modifyCurrentLimits( |
|
0 commit comments