Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.powsybl.commons.report.ReportNode;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -33,6 +34,9 @@
@ModificationErrorTypeName("COMPOSITE_MODIFICATION_ERROR")
public class CompositeModificationInfos extends ModificationInfos {

@Schema(description = "composite modification name")
private String compositeName;

Choose a reason for hiding this comment

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

Why ?


@Schema(description = "composite modification list")
@JsonInclude(JsonInclude.Include.NON_NULL)
private List<ModificationInfos> modifications;
Expand All @@ -41,4 +45,12 @@ public class CompositeModificationInfos extends ModificationInfos {
public AbstractModification toModification() {
return new CompositeModification(this);
}

@Override
public ReportNode createSubReportNode(ReportNode reportNode) {
return reportNode.newReportNode()
.withMessageTemplate("network.modification.composite")
.withUntypedValue("modificationName", getCompositeName())
.add();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,44 @@
package org.gridsuite.modification.modifications;

import com.powsybl.commons.report.ReportNode;
import com.powsybl.commons.report.TypedValue;
import com.powsybl.iidm.network.Network;
import org.gridsuite.modification.dto.CompositeModificationInfos;
import org.gridsuite.modification.report.NetworkModificationReportResourceBundle;

import static org.gridsuite.modification.modifications.byfilter.AbstractModificationByAssignment.VALUE_KEY_ERROR_MESSAGE;

/**
* @author Ghazwa Rehili <ghazwa.rehili at rte-france.com>
*/
public class CompositeModification extends AbstractModification {

private final CompositeModificationInfos compositeModificationInfos;

public CompositeModification(CompositeModificationInfos compositeModificationInfos) {
this.compositeModificationInfos = compositeModificationInfos;
}

@Override
public void apply(Network network, ReportNode subReportNode) {
throw new UnsupportedOperationException();
compositeModificationInfos.getModifications().forEach(

Choose a reason for hiding this comment

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

Need to do same as AbstractTabularModification ?

modif -> {
ReportNode modifNode = modif.createSubReportNode(subReportNode);
try {
modif.toModification().apply(network, modifNode);
} catch (Exception e) {
// in case of error in a network modification, the composite modification doesn't interrupt its execution :
// the following modifications will be carried out
modifNode.newReportNode()
.withResourceBundles(NetworkModificationReportResourceBundle.BASE_NAME)
.withMessageTemplate("network.modification.compositeReportException")
.withUntypedValue("modificationName", modif.toModification().getName())
.withUntypedValue(VALUE_KEY_ERROR_MESSAGE, e.getMessage())
.withSeverity(TypedValue.ERROR_SEVERITY)
.add();
}
}
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ network.modification.noLimitSetSelectedOnSide1 = No limit set selected on side 1
network.modification.noLimitSetSelectedOnSide2 = No limit set selected on side 2
network.modification.limitSetAbsentOnSide1 = limit set '${selectedOperationalLimitsGroup}' on side 1 does not exist
network.modification.limitSetAbsentOnSide2 = limit set '${selectedOperationalLimitsGroup}' on side 2 does not exist
network.modification.composite = Composite modification : '${modificationName}'
network.modification.compositeReportException = Cannot execute ${modificationName} : ${errorMessage}
network.modification.applicabilityChanged = limit set ${operationalLimitsGroupName} applicability changed to ${applicability}
network.modification.limits = Limits
network.modification.activeLimitsSets = Active limits sets
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,22 @@
*/
package org.gridsuite.modification.modifications;

import com.powsybl.commons.PowsyblException;
import com.powsybl.commons.report.ReportNode;
import com.powsybl.iidm.network.Generator;
import com.powsybl.iidm.network.LoadType;
import com.powsybl.iidm.network.Network;

import org.gridsuite.modification.ModificationType;
import org.gridsuite.modification.dto.CompositeModificationInfos;
import org.gridsuite.modification.dto.ModificationInfos;
import org.gridsuite.modification.dto.*;
import org.gridsuite.modification.report.NetworkModificationReportResourceBundle;
import org.gridsuite.modification.utils.ModificationCreation;
import org.gridsuite.modification.utils.NetworkCreation;
import java.util.List;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.gridsuite.modification.utils.TestUtils.*;
import static org.junit.jupiter.api.Assertions.*;

/**
* @author Ghazwa Rehili <ghazwa.rehili at rte-france.com>
Expand All @@ -27,13 +31,48 @@ class CompositeModificationsTest extends AbstractNetworkModificationTest {

@Override
public void checkModification() {
Network network = getNetwork();
CompositeModificationInfos compositeModificationInfos = (CompositeModificationInfos) buildModification();

// checks that the sub sub sub netmod is executed at the right depth
ReportNode report = compositeModificationInfos.createSubReportNode(ReportNode.newRootReportNode()
.withResourceBundles(NetworkModificationReportResourceBundle.BASE_NAME)
.withMessageTemplate("test")
.build());
CompositeModification netmod = (CompositeModification) compositeModificationInfos.toModification();
assertDoesNotThrow(() -> netmod.apply(network, report));
assertLogMessageAtDepth(
"Generator with id=idGenerator modified :",
"network.modification.generatorModification",
report,
4
);
assertLogMessageAtDepth(
"Composite modification : 'sub sub composite'",
"network.modification.composite",
report,
2
);

// regular throwing exception netmod
GeneratorCreation throwingExceptionNetMod = (GeneratorCreation) buildThrowingModification().toModification();
assertThrows(PowsyblException.class, () -> throwingExceptionNetMod.apply(network));
// but doesn't throw once inside a composite modification
compositeModificationInfos.setModifications(List.of(buildThrowingModification()));
CompositeModification netmodContainingError = (CompositeModification) compositeModificationInfos.toModification();
assertDoesNotThrow(() -> netmodContainingError.apply(network, report));
// but the thrown message is inside the report :
assertLogMessageWithoutRank(
"Cannot execute GeneratorCreation : The network " + getNetwork().getId() + " already contains an object 'GeneratorImpl' with the id 'idGenerator'",
"network.modification.compositeReportException",
report
);
}

@Override
public void testApply() throws Exception {
CompositeModificationInfos compositeModificationInfos = (CompositeModificationInfos) buildModification();
compositeModificationInfos.getModifications().forEach(modificationInfos -> modificationInfos.toModification().apply(getNetwork()));
assertAfterNetworkModificationApplication();
private GeneratorCreationInfos buildThrowingModification() {
return ModificationCreation.getCreationGenerator(
"v1", "idGenerator", "nameGenerator", "1B", "v2load", "LOAD", "v1"
);
}

@Override
Expand All @@ -44,19 +83,44 @@ protected Network createNetwork(UUID networkUuid) {
@Override
protected ModificationInfos buildModification() {
List<ModificationInfos> modifications = List.of(
ModificationCreation.getCreationGenerator("v1", "idGenerator", "nameGenerator", "1B", "v2load", "LOAD",
"v1"),
CompositeModificationInfos.builder()
.compositeName("sub composite 1")
.modifications(
List.of(
ModificationCreation.getModificationGenerator("idGenerator", "other idGenerator name"),
// this should throw an error but not stop the execution of the composite modification and all the other content
buildThrowingModification()
)
).build(),
ModificationCreation.getModificationGenerator("idGenerator", "new idGenerator name"),
ModificationCreation.getCreationLoad("v1", "idLoad", "nameLoad", "1.1", LoadType.UNDEFINED),
ModificationCreation.getCreationBattery("v1", "idBattery", "nameBattry", "1.1"));
ModificationCreation.getCreationBattery("v1", "idBattery", "nameBattery", "1.1"),
// test of a composite modification inside a composite modification inside a composite modification
CompositeModificationInfos.builder()
.compositeName("sub composite 2")
.modifications(
List.of(
CompositeModificationInfos.builder()
.compositeName("sub sub composite")
.modifications(
List.of(ModificationCreation.getModificationGenerator("idGenerator", "other idGenerator name again"))
).build(),
ModificationCreation.getModificationGenerator("idGenerator", "even newer idGenerator name")
)
).build()
);
return CompositeModificationInfos.builder()
.compositeName("main composite")
.modifications(modifications)
.stashed(false)
.build();
}

@Override
protected void assertAfterNetworkModificationApplication() {
assertNotNull(getNetwork().getGenerator("idGenerator"));
Generator gen = getNetwork().getGenerator("idGenerator");
assertNotNull(gen);
assertEquals("even newer idGenerator name", gen.getOptionalName().orElseThrow());
assertNotNull(getNetwork().getLoad("idLoad"));
assertNotNull(getNetwork().getBattery("idBattery"));
}
Expand Down
28 changes: 28 additions & 0 deletions src/test/java/org/gridsuite/modification/utils/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ public static void assertLogNthMessage(String expectedMessage, String reportKey,
assertEquals(expectedMessage, message.get().trim());
}

public static void assertLogMessageAtDepth(String expectedMessage, String reportKey, ReportNode reportNode, int depth) {
Optional<String> message = getMessageFromReporterAtDepth(reportKey, reportNode, 1, depth);
assertTrue(message.isPresent());
assertEquals(expectedMessage, message.get().trim());
}

public static void assertLogMessage(String expectedMessage, String reportKey, ReportNode reportNode) {
assertLogNthMessage(expectedMessage, reportKey, reportNode, 1);
}
Expand Down Expand Up @@ -85,6 +91,28 @@ private static boolean assertMessageFoundFromReporter(String expectedMessage, St
return foundInSubReporters;
}

private static Optional<String> getMessageFromReporterAtDepth(String reportKey, ReportNode reporterModel, int currentDepth, int expectedDepth) {
Optional<String> message = Optional.empty();

Iterator<ReportNode> reportersIterator = reporterModel.getChildren().iterator();
while (message.isEmpty() && reportersIterator.hasNext() && currentDepth < expectedDepth) {
message = getMessageFromReporterAtDepth(reportKey, reportersIterator.next(), currentDepth + 1, expectedDepth);
}

Iterator<ReportNode> reportsIterator = reporterModel.getChildren().iterator();
while (message.isEmpty() && reportsIterator.hasNext()) {
ReportNode report = reportsIterator.next();
if (currentDepth == expectedDepth && report.getMessageKey().equals(reportKey)) {
message = Optional.of(formatReportMessage(report, reporterModel));
}
}

return message;
}

/**
* @param rank order position inside reporterModel
*/
private static Optional<String> getMessageFromReporter(String reportKey, ReportNode reporterModel, int rank) {
Optional<String> message = Optional.empty();

Expand Down
Loading