From 211522c6c3c38230a30c58416b4ef2fada0e9f96 Mon Sep 17 00:00:00 2001 From: Thang PHAM <117309322+thangqp@users.noreply.github.com> Date: Thu, 3 Oct 2024 16:19:54 +0200 Subject: [PATCH] Modification by filter (without formula data migration) (#526) Signed-off-by: Thang PHAM byfilter}/formula/FormulaInfos.java | 21 +- .../dto/{ => byfilter}/formula/Operator.java | 2 +- .../formula/ReferenceFieldOrValue.java | 50 ++ .../dto/formula/ReferenceFieldOrValue.java | 68 --- .../equipmentfield/GeneratorField.java | 109 ---- .../byfilter/AbstractAssignmentEntity.java | 39 ++ .../ByFormulaModificationEntity.java | 10 +- .../ModificationByAssignmentEntity.java | 83 +++ .../byfilter/assignment/AssignmentEntity.java | 79 +++ .../{ => byfilter/formula}/FormulaEntity.java | 51 +- .../modifications/ByFormulaModification.java | 307 ---------- .../AbstractModificationByAssignment.java | 368 +++++++++++ .../byfilter/ByFormulaModification.java | 111 ++++ .../byfilter/ModificationByAssignment.java | 107 ++++ .../changesets/changelog_20240912T130742Z.xml | 44 ++ .../db/changelog/db.changelog-master.yaml | 5 +- .../AbstractModificationByAssignmentTest.java | 263 ++++++++ .../BatteryModificationByAssignmentTest.java | 214 +++++++ ...GeneratorModificationByAssignmentTest.java | 441 ++++++++++++++ .../LoadModificationByAssignmentTest.java | 134 ++++ ...mpensatorModificationByAssignmentTest.java | 184 ++++++ ...ansformerModificationByAssignmentTest.java | 576 ++++++++++++++++++ ...tageLevelModificationByAssignmentTest.java | 225 +++++++ .../AbstractByFormulaModificationTest.java | 13 +- .../BatteryByFormulaModificationTest.java | 10 +- .../GeneratorByFormulaModificationTest.java | 10 +- .../LoadByFormulaModificationTest.java | 17 +- ...tCompensatorByFormulaModificationTest.java | 10 +- ...sTransformerByFormulaModificationTest.java | 10 +- ...VoltageLevelByFormulaModificationTest.java | 21 +- 50 files changed, 3580 insertions(+), 657 deletions(-) create mode 100644 src/main/java/org/gridsuite/modification/server/dto/ModificationByAssignmentInfos.java create mode 100644 src/main/java/org/gridsuite/modification/server/dto/byfilter/AbstractAssignmentInfos.java create mode 100644 src/main/java/org/gridsuite/modification/server/dto/byfilter/DataType.java create mode 100644 src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/AssignmentInfos.java create mode 100644 src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/BooleanAssignmentInfos.java create mode 100644 src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/DoubleAssignmentInfos.java create mode 100644 src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/EnumAssignmentInfos.java create mode 100644 src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/IntegerAssignmentInfos.java create mode 100644 src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/PropertyAssignmentInfos.java rename src/main/java/org/gridsuite/modification/server/dto/{formula => byfilter}/equipmentfield/BatteryField.java (79%) create mode 100644 src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/FieldUtils.java create mode 100644 src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/GeneratorField.java rename src/main/java/org/gridsuite/modification/server/dto/{formula => byfilter}/equipmentfield/LoadField.java (63%) rename src/main/java/org/gridsuite/modification/server/dto/{formula => byfilter}/equipmentfield/ShuntCompensatorField.java (71%) rename src/main/java/org/gridsuite/modification/server/dto/{formula => byfilter}/equipmentfield/TwoWindingsTransformerField.java (61%) rename src/main/java/org/gridsuite/modification/server/dto/{formula => byfilter}/equipmentfield/VoltageLevelField.java (60%) rename src/main/java/org/gridsuite/modification/server/dto/{ => byfilter}/formula/FormulaInfos.java (67%) rename src/main/java/org/gridsuite/modification/server/dto/{ => byfilter}/formula/Operator.java (87%) create mode 100644 src/main/java/org/gridsuite/modification/server/dto/byfilter/formula/ReferenceFieldOrValue.java delete mode 100644 src/main/java/org/gridsuite/modification/server/dto/formula/ReferenceFieldOrValue.java delete mode 100644 src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/GeneratorField.java create mode 100644 src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/AbstractAssignmentEntity.java rename src/main/java/org/gridsuite/modification/server/entities/equipment/modification/{ => byfilter}/ByFormulaModificationEntity.java (92%) create mode 100644 src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/ModificationByAssignmentEntity.java create mode 100644 src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/assignment/AssignmentEntity.java rename src/main/java/org/gridsuite/modification/server/entities/equipment/modification/{ => byfilter/formula}/FormulaEntity.java (64%) delete mode 100644 src/main/java/org/gridsuite/modification/server/modifications/ByFormulaModification.java create mode 100644 src/main/java/org/gridsuite/modification/server/modifications/byfilter/AbstractModificationByAssignment.java create mode 100644 src/main/java/org/gridsuite/modification/server/modifications/byfilter/ByFormulaModification.java create mode 100644 src/main/java/org/gridsuite/modification/server/modifications/byfilter/ModificationByAssignment.java create mode 100644 src/main/resources/db/changelog/changesets/changelog_20240912T130742Z.xml create mode 100644 src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/AbstractModificationByAssignmentTest.java create mode 100644 src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/BatteryModificationByAssignmentTest.java create mode 100644 src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/GeneratorModificationByAssignmentTest.java create mode 100644 src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/LoadModificationByAssignmentTest.java create mode 100644 src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/ShuntCompensatorModificationByAssignmentTest.java create mode 100644 src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/TwoWindingsTransformerModificationByAssignmentTest.java create mode 100644 src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/VoltageLevelModificationByAssignmentTest.java rename src/test/java/org/gridsuite/modification/server/modifications/{ => byfilter/formula}/AbstractByFormulaModificationTest.java (96%) rename src/test/java/org/gridsuite/modification/server/modifications/{ => byfilter/formula}/BatteryByFormulaModificationTest.java (96%) rename src/test/java/org/gridsuite/modification/server/modifications/{ => byfilter/formula}/GeneratorByFormulaModificationTest.java (98%) rename src/test/java/org/gridsuite/modification/server/modifications/{ => byfilter/formula}/LoadByFormulaModificationTest.java (85%) rename src/test/java/org/gridsuite/modification/server/modifications/{ => byfilter/formula}/ShuntCompensatorByFormulaModificationTest.java (96%) rename src/test/java/org/gridsuite/modification/server/modifications/{ => byfilter/formula}/TwoWindingsTransformerByFormulaModificationTest.java (98%) rename src/test/java/org/gridsuite/modification/server/modifications/{ => byfilter/formula}/VoltageLevelByFormulaModificationTest.java (94%) diff --git a/src/main/java/org/gridsuite/modification/server/ModificationType.java b/src/main/java/org/gridsuite/modification/server/ModificationType.java index 0f055ca6d..a95415d71 100644 --- a/src/main/java/org/gridsuite/modification/server/ModificationType.java +++ b/src/main/java/org/gridsuite/modification/server/ModificationType.java @@ -50,6 +50,7 @@ public enum ModificationType { TABULAR_MODIFICATION(PreloadingStrategy.COLLECTION), TABULAR_CREATION(PreloadingStrategy.COLLECTION), BY_FORMULA_MODIFICATION(PreloadingStrategy.COLLECTION), + MODIFICATION_BY_ASSIGNMENT(PreloadingStrategy.COLLECTION), COMPOSITE_MODIFICATION(PreloadingStrategy.COLLECTION); private final PreloadingStrategy strategy; diff --git a/src/main/java/org/gridsuite/modification/server/NetworkModificationException.java b/src/main/java/org/gridsuite/modification/server/NetworkModificationException.java index 530d3b4c0..493c4f654 100644 --- a/src/main/java/org/gridsuite/modification/server/NetworkModificationException.java +++ b/src/main/java/org/gridsuite/modification/server/NetworkModificationException.java @@ -113,6 +113,7 @@ public enum Type { CREATE_CONVERTER_STATION_ERROR(HttpStatus.INTERNAL_SERVER_ERROR), MODIFY_CONVERTER_STATION_ERROR(HttpStatus.INTERNAL_SERVER_ERROR), BY_FORMULA_MODIFICATION_ERROR(HttpStatus.INTERNAL_SERVER_ERROR), + MODIFICATION_BY_ASSIGNMENT_ERROR(HttpStatus.INTERNAL_SERVER_ERROR), HVDC_LINE_NOT_FOUND(HttpStatus.NOT_FOUND), COMPOSITE_MODIFICATION_ERROR(HttpStatus.INTERNAL_SERVER_ERROR), WRONG_HVDC_ANGLE_DROOP_ACTIVE_POWER_CONTROL(HttpStatus.BAD_REQUEST); diff --git a/src/main/java/org/gridsuite/modification/server/dto/ByFormulaModificationInfos.java b/src/main/java/org/gridsuite/modification/server/dto/ByFormulaModificationInfos.java index afa985a77..91c5c3b70 100644 --- a/src/main/java/org/gridsuite/modification/server/dto/ByFormulaModificationInfos.java +++ b/src/main/java/org/gridsuite/modification/server/dto/ByFormulaModificationInfos.java @@ -19,9 +19,9 @@ import lombok.experimental.SuperBuilder; import org.gridsuite.modification.server.ModificationType; import org.gridsuite.modification.server.dto.annotation.ModificationErrorTypeName; -import org.gridsuite.modification.server.dto.formula.FormulaInfos; -import org.gridsuite.modification.server.entities.equipment.modification.ByFormulaModificationEntity; -import org.gridsuite.modification.server.modifications.ByFormulaModification; +import org.gridsuite.modification.server.dto.byfilter.formula.FormulaInfos; +import org.gridsuite.modification.server.entities.equipment.modification.byfilter.ByFormulaModificationEntity; +import org.gridsuite.modification.server.modifications.byfilter.ByFormulaModification; import java.util.List; @@ -57,6 +57,6 @@ public ByFormulaModification toModification() { @Override public ReportNode createSubReportNode(ReportNode reportNode) { - return reportNode.newReportNode().withMessageTemplate(ModificationType.BY_FORMULA_MODIFICATION.name(), "By formula modification").add(); + return reportNode.newReportNode().withMessageTemplate(ModificationType.BY_FORMULA_MODIFICATION.name(), "Modification by formula").add(); } } diff --git a/src/main/java/org/gridsuite/modification/server/dto/ModificationByAssignmentInfos.java b/src/main/java/org/gridsuite/modification/server/dto/ModificationByAssignmentInfos.java new file mode 100644 index 000000000..20863caee --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/ModificationByAssignmentInfos.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.dto; + +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.powsybl.commons.report.ReportNode; +import com.powsybl.iidm.network.IdentifiableType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.SuperBuilder; +import org.gridsuite.modification.server.ModificationType; +import org.gridsuite.modification.server.dto.annotation.ModificationErrorTypeName; +import org.gridsuite.modification.server.dto.byfilter.assignment.AssignmentInfos; +import org.gridsuite.modification.server.entities.equipment.modification.byfilter.ModificationByAssignmentEntity; +import org.gridsuite.modification.server.modifications.byfilter.ModificationByAssignment; + +import java.util.List; + +/** + * @author Thang PHAM + */ +@SuperBuilder +@NoArgsConstructor +@Getter +@Setter +@JsonTypeName("MODIFICATION_BY_ASSIGNMENT") +@ModificationErrorTypeName("MODIFICATION_BY_ASSIGNMENT_ERROR") +@ToString(callSuper = true) +@Schema(description = "Modification by assignment") +public class ModificationByAssignmentInfos extends ModificationInfos { + @Schema(description = "Equipment type") + private IdentifiableType equipmentType; + + @Schema(description = "list of modifications") + private List> assignmentInfosList; + + @Override + public ModificationByAssignmentEntity toEntity() { + return new ModificationByAssignmentEntity(this); + } + + @Override + public ModificationByAssignment toModification() { + return new ModificationByAssignment(this); + } + + @Override + public ReportNode createSubReportNode(ReportNode reportNode) { + return reportNode.newReportNode().withMessageTemplate(ModificationType.MODIFICATION_BY_ASSIGNMENT.name(), "Modification by filter").add(); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/dto/ModificationInfos.java b/src/main/java/org/gridsuite/modification/server/dto/ModificationInfos.java index d2178532c..eb5811353 100644 --- a/src/main/java/org/gridsuite/modification/server/dto/ModificationInfos.java +++ b/src/main/java/org/gridsuite/modification/server/dto/ModificationInfos.java @@ -68,6 +68,7 @@ @JsonSubTypes.Type(value = ConverterStationCreationInfos.class), @JsonSubTypes.Type(value = TabularModificationInfos.class), @JsonSubTypes.Type(value = ByFormulaModificationInfos.class), + @JsonSubTypes.Type(value = ModificationByAssignmentInfos.class), @JsonSubTypes.Type(value = VscModificationInfos.class), @JsonSubTypes.Type(value = ConverterStationModificationInfos.class), @JsonSubTypes.Type(value = TabularCreationInfos.class), diff --git a/src/main/java/org/gridsuite/modification/server/dto/byfilter/AbstractAssignmentInfos.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/AbstractAssignmentInfos.java new file mode 100644 index 000000000..3257c6936 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/AbstractAssignmentInfos.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.dto.byfilter; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.SuperBuilder; +import org.gridsuite.modification.server.dto.FilterInfos; + +import java.util.List; +import java.util.UUID; + +/** + * @author Thang PHAM + */ +@SuperBuilder +@NoArgsConstructor +@Getter +@Setter +public abstract class AbstractAssignmentInfos { + @Schema(description = "id") + private UUID id; + + @Schema(description = "List of filters") + private List filters; + + @Schema(description = "Edited field") + private String editedField; + + @JsonIgnore + public String getEditedFieldLabel() { + return editedField; + } +} diff --git a/src/main/java/org/gridsuite/modification/server/dto/byfilter/DataType.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/DataType.java new file mode 100644 index 000000000..5ab6d5e87 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/DataType.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.dto.byfilter; + +/** + * @author Thang PHAM + */ +public enum DataType { + ENUM, + BOOLEAN, + INTEGER, + DOUBLE, + PROPERTY +} diff --git a/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/AssignmentInfos.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/AssignmentInfos.java new file mode 100644 index 000000000..2dd980a66 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/AssignmentInfos.java @@ -0,0 +1,54 @@ + /** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.dto.byfilter.assignment; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.SuperBuilder; +import org.gridsuite.modification.server.dto.byfilter.AbstractAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.DataType; +import org.gridsuite.modification.server.entities.equipment.modification.byfilter.assignment.AssignmentEntity; + +/** + * @author Thang PHAM + */ +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + property = "dataType", + include = JsonTypeInfo.As.EXISTING_PROPERTY) +@JsonSubTypes({ + @JsonSubTypes.Type(value = BooleanAssignmentInfos.class, name = "BOOLEAN"), + @JsonSubTypes.Type(value = EnumAssignmentInfos.class, name = "ENUM"), + @JsonSubTypes.Type(value = DoubleAssignmentInfos.class, name = "DOUBLE"), + @JsonSubTypes.Type(value = IntegerAssignmentInfos.class, name = "INTEGER"), + @JsonSubTypes.Type(value = PropertyAssignmentInfos.class, name = "PROPERTY"), +}) +@JsonInclude(JsonInclude.Include.NON_NULL) +@SuperBuilder +@NoArgsConstructor +@Getter +@Setter +public class AssignmentInfos extends AbstractAssignmentInfos { + @Schema(description = "Value") + private T value; + + public DataType getDataType() { + throw new UnsupportedOperationException("This method should not be called"); + } + + @JsonIgnore + public AssignmentEntity toEntity() { + return new AssignmentEntity(this); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/BooleanAssignmentInfos.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/BooleanAssignmentInfos.java new file mode 100644 index 000000000..d62bab7c1 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/BooleanAssignmentInfos.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.dto.byfilter.assignment; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.gridsuite.modification.server.dto.byfilter.DataType; + +/** + * @author Thang PHAM + */ +@SuperBuilder +@NoArgsConstructor +public class BooleanAssignmentInfos extends AssignmentInfos { + @Override + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + public DataType getDataType() { + return DataType.BOOLEAN; + } +} diff --git a/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/DoubleAssignmentInfos.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/DoubleAssignmentInfos.java new file mode 100644 index 000000000..a560ea9d4 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/DoubleAssignmentInfos.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.dto.byfilter.assignment; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.gridsuite.modification.server.dto.byfilter.DataType; + +/** + * @author Thang PHAM + */ +@SuperBuilder +@NoArgsConstructor +public class DoubleAssignmentInfos extends AssignmentInfos { + @Override + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + public DataType getDataType() { + return DataType.DOUBLE; + } +} diff --git a/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/EnumAssignmentInfos.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/EnumAssignmentInfos.java new file mode 100644 index 000000000..dc134c0da --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/EnumAssignmentInfos.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.dto.byfilter.assignment; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.gridsuite.modification.server.dto.byfilter.DataType; + +/** + * @author Thang PHAM + */ +@SuperBuilder +@NoArgsConstructor +public class EnumAssignmentInfos extends AssignmentInfos { + @Override + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + public DataType getDataType() { + return DataType.ENUM; + } +} diff --git a/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/IntegerAssignmentInfos.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/IntegerAssignmentInfos.java new file mode 100644 index 000000000..ec17e0eb4 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/IntegerAssignmentInfos.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.dto.byfilter.assignment; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.gridsuite.modification.server.dto.byfilter.DataType; + +/** + * @author Thang PHAM + */ +@SuperBuilder +@NoArgsConstructor +public class IntegerAssignmentInfos extends AssignmentInfos { + @Override + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + public DataType getDataType() { + return DataType.INTEGER; + } +} diff --git a/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/PropertyAssignmentInfos.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/PropertyAssignmentInfos.java new file mode 100644 index 000000000..383ed2368 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/assignment/PropertyAssignmentInfos.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.dto.byfilter.assignment; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.gridsuite.modification.server.dto.byfilter.DataType; +import org.gridsuite.modification.server.entities.equipment.modification.byfilter.assignment.AssignmentEntity; + +/** + * @author Thang PHAM + */ +@SuperBuilder +@NoArgsConstructor +public class PropertyAssignmentInfos extends AssignmentInfos { + @Schema(description = "Property name") + @Getter + private String propertyName; + + @Override + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + public DataType getDataType() { + return DataType.PROPERTY; + } + + @JsonIgnore + @Override + public String getEditedFieldLabel() { + return propertyName + " " + super.getEditedFieldLabel(); + } + + @Override + public AssignmentEntity toEntity() { + AssignmentEntity assignmentEntity = super.toEntity(); + assignmentEntity.setPropertyName(propertyName); + return assignmentEntity; + } +} diff --git a/src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/BatteryField.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/BatteryField.java similarity index 79% rename from src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/BatteryField.java rename to src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/BatteryField.java index 7c82638e7..117db9718 100644 --- a/src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/BatteryField.java +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/BatteryField.java @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.gridsuite.modification.server.dto.formula.equipmentfield; +package org.gridsuite.modification.server.dto.byfilter.equipmentfield; import com.powsybl.iidm.network.Battery; import com.powsybl.iidm.network.extensions.ActivePowerControl; @@ -30,21 +30,21 @@ public enum BatteryField { REACTIVE_POWER_SET_POINT, DROOP; - public static Double getReferenceValue(Battery battery, String batteryField) { + public static String getReferenceValue(Battery battery, String batteryField) { ActivePowerControl activePowerControl = battery.getExtension(ActivePowerControl.class); BatteryField field = BatteryField.valueOf(batteryField); return switch (field) { - case MINIMUM_ACTIVE_POWER -> battery.getMinP(); - case MAXIMUM_ACTIVE_POWER -> battery.getMaxP(); - case ACTIVE_POWER_SET_POINT -> battery.getTargetP(); - case REACTIVE_POWER_SET_POINT -> battery.getTargetQ(); - case DROOP -> activePowerControl != null ? activePowerControl.getDroop() : null; + case MINIMUM_ACTIVE_POWER -> String.valueOf(battery.getMinP()); + case MAXIMUM_ACTIVE_POWER -> String.valueOf(battery.getMaxP()); + case ACTIVE_POWER_SET_POINT -> String.valueOf(battery.getTargetP()); + case REACTIVE_POWER_SET_POINT -> String.valueOf(battery.getTargetQ()); + case DROOP -> activePowerControl != null ? String.valueOf(activePowerControl.getDroop()) : null; }; } - public static void setNewValue(Battery battery, String batteryField, @NotNull Double newValue) { + public static void setNewValue(Battery battery, String batteryField, @NotNull String newValue) { BatteryField field = BatteryField.valueOf(batteryField); - final AttributeModification attributeModification = new AttributeModification<>(newValue, OperationType.SET); + final AttributeModification attributeModification = new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET); switch (field) { case MINIMUM_ACTIVE_POWER -> modifyBatteryActiveLimitsAttributes(null, attributeModification, battery, null); @@ -64,7 +64,7 @@ public static void setNewValue(Battery battery, String batteryField, @NotNull Do ActivePowerControlAdder activePowerControlAdder = battery.newExtension(ActivePowerControlAdder.class); ModificationUtils.getInstance().modifyActivePowerControlAttributes( activePowerControl, activePowerControlAdder, null, - new AttributeModification<>(newValue.floatValue(), OperationType.SET), null, null); + new AttributeModification<>(Float.parseFloat(newValue), OperationType.SET), null, null); } } } diff --git a/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/FieldUtils.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/FieldUtils.java new file mode 100644 index 000000000..66e924caf --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/FieldUtils.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.dto.byfilter.equipmentfield; + +import com.powsybl.iidm.network.*; +import org.gridsuite.modification.server.NetworkModificationException; + +import javax.annotation.Nullable; + +/** + * @author Thang PHAM + */ +public final class FieldUtils { + + private FieldUtils() { + + } + + @Nullable + public static String getFieldValue(Identifiable equipment, String equipmentField) { + return switch (equipment.getType()) { + case GENERATOR -> GeneratorField.getReferenceValue((Generator) equipment, equipmentField); + case BATTERY -> BatteryField.getReferenceValue((Battery) equipment, equipmentField); + case SHUNT_COMPENSATOR -> + ShuntCompensatorField.getReferenceValue((ShuntCompensator) equipment, equipmentField); + case VOLTAGE_LEVEL -> VoltageLevelField.getReferenceValue((VoltageLevel) equipment, equipmentField); + case LOAD -> LoadField.getReferenceValue((Load) equipment, equipmentField); + case TWO_WINDINGS_TRANSFORMER -> + TwoWindingsTransformerField.getReferenceValue((TwoWindingsTransformer) equipment, equipmentField); + default -> throw new NetworkModificationException(NetworkModificationException.Type.MODIFICATION_ERROR, + "Unsupported getting value for equipment type : " + equipment.getType().name()); + }; + } + + public static void setFieldValue(Identifiable equipment, String equipmentField, String newValue) { + switch (equipment.getType()) { + case GENERATOR -> GeneratorField.setNewValue((Generator) equipment, equipmentField, newValue); + case BATTERY -> BatteryField.setNewValue((Battery) equipment, equipmentField, newValue); + case SHUNT_COMPENSATOR -> ShuntCompensatorField.setNewValue((ShuntCompensator) equipment, equipmentField, newValue); + case VOLTAGE_LEVEL -> VoltageLevelField.setNewValue((VoltageLevel) equipment, equipmentField, newValue); + case LOAD -> LoadField.setNewValue((Load) equipment, equipmentField, newValue); + case TWO_WINDINGS_TRANSFORMER -> TwoWindingsTransformerField.setNewValue((TwoWindingsTransformer) equipment, equipmentField, newValue); + default -> throw new NetworkModificationException(NetworkModificationException.Type.MODIFICATION_ERROR, + "Unsupported setting value for equipment type : " + equipment.getType().name()); + } + } +} diff --git a/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/GeneratorField.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/GeneratorField.java new file mode 100644 index 000000000..028c313f4 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/GeneratorField.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2023, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.dto.byfilter.equipmentfield; + +import com.powsybl.iidm.network.Generator; +import com.powsybl.iidm.network.extensions.*; +import com.powsybl.network.store.iidm.impl.extensions.CoordinatedReactiveControlAdderImpl; +import jakarta.validation.constraints.NotNull; +import org.gridsuite.modification.server.dto.AttributeModification; +import org.gridsuite.modification.server.dto.OperationType; +import org.gridsuite.modification.server.modifications.ModificationUtils; + +import static org.gridsuite.modification.server.NetworkModificationException.Type.MODIFY_GENERATOR_ERROR; +import static org.gridsuite.modification.server.modifications.GeneratorModification.*; + +/** + * @author Seddik Yengui + */ +public enum GeneratorField { + VOLTAGE_REGULATOR_ON, + MINIMUM_ACTIVE_POWER, + MAXIMUM_ACTIVE_POWER, + RATED_NOMINAL_POWER, + ACTIVE_POWER_SET_POINT, + REACTIVE_POWER_SET_POINT, + VOLTAGE_SET_POINT, + PLANNED_ACTIVE_POWER_SET_POINT, + MARGINAL_COST, + PLANNED_OUTAGE_RATE, + FORCED_OUTAGE_RATE, + DROOP, + TRANSIENT_REACTANCE, + STEP_UP_TRANSFORMER_REACTANCE, + Q_PERCENT; + + public static String getReferenceValue(Generator generator, String generatorField) { + ActivePowerControl activePowerControl = generator.getExtension(ActivePowerControl.class); + GeneratorStartup generatorStartup = generator.getExtension(GeneratorStartup.class); + GeneratorShortCircuit generatorShortCircuit = generator.getExtension(GeneratorShortCircuit.class); + CoordinatedReactiveControl coordinatedReactiveControl = generator.getExtension(CoordinatedReactiveControl.class); + GeneratorField field = GeneratorField.valueOf(generatorField); + return switch (field) { + case VOLTAGE_REGULATOR_ON -> String.valueOf(generator.isVoltageRegulatorOn()); + case MAXIMUM_ACTIVE_POWER -> String.valueOf(generator.getMaxP()); + case MINIMUM_ACTIVE_POWER -> String.valueOf(generator.getMinP()); + case ACTIVE_POWER_SET_POINT -> String.valueOf(generator.getTargetP()); + case RATED_NOMINAL_POWER -> String.valueOf(generator.getRatedS()); + case REACTIVE_POWER_SET_POINT -> String.valueOf(generator.getTargetQ()); + case VOLTAGE_SET_POINT -> String.valueOf(generator.getTargetV()); + case PLANNED_ACTIVE_POWER_SET_POINT -> generatorStartup != null ? String.valueOf(generatorStartup.getPlannedActivePowerSetpoint()) : null; + case MARGINAL_COST -> generatorStartup != null ? String.valueOf(generatorStartup.getMarginalCost()) : null; + case PLANNED_OUTAGE_RATE -> generatorStartup != null ? String.valueOf(generatorStartup.getPlannedOutageRate()) : null; + case FORCED_OUTAGE_RATE -> generatorStartup != null ? String.valueOf(generatorStartup.getForcedOutageRate()) : null; + case DROOP -> activePowerControl != null ? String.valueOf(activePowerControl.getDroop()) : null; + case TRANSIENT_REACTANCE -> generatorShortCircuit != null ? String.valueOf(generatorShortCircuit.getDirectTransX()) : null; + case STEP_UP_TRANSFORMER_REACTANCE -> generatorShortCircuit != null ? String.valueOf(generatorShortCircuit.getStepUpTransformerX()) : null; + case Q_PERCENT -> coordinatedReactiveControl != null ? String.valueOf(coordinatedReactiveControl.getQPercent()) : null; + }; + } + + public static void setNewValue(Generator generator, String generatorField, @NotNull String newValue) { + GeneratorField field = GeneratorField.valueOf(generatorField); + switch (field) { + case MAXIMUM_ACTIVE_POWER -> modifyGeneratorActiveLimitsAttributes( + new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), + null, null, generator, null); + case MINIMUM_ACTIVE_POWER -> modifyGeneratorActiveLimitsAttributes( + null, new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), null, generator, null); + case ACTIVE_POWER_SET_POINT -> { + ModificationUtils.getInstance().checkActivePowerZeroOrBetweenMinAndMaxActivePower( + new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), + null, null, generator.getMinP(), generator.getMaxP(), generator.getTargetP(), + MODIFY_GENERATOR_ERROR, "Generator '" + generator.getId() + "' : " + ); + generator.setTargetP(Double.parseDouble(newValue)); + } + case RATED_NOMINAL_POWER -> modifyGeneratorActiveLimitsAttributes( + null, null, new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), generator, null); + case REACTIVE_POWER_SET_POINT -> modifyTargetQ(generator, new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET)); + case VOLTAGE_SET_POINT -> modifyTargetV(generator, new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET)); + case PLANNED_ACTIVE_POWER_SET_POINT -> modifyGeneratorStartUpAttributes( + new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), null, + null, null, generator, null, null); + case MARGINAL_COST -> modifyGeneratorStartUpAttributes( + null, new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), + null, null, generator, null, null); + case PLANNED_OUTAGE_RATE -> modifyGeneratorStartUpAttributes( + null, null, new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), + null, generator, null, null); + case FORCED_OUTAGE_RATE -> + modifyGeneratorStartUpAttributes(null, null, null, new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), generator, null, null); + case DROOP -> { + ActivePowerControl activePowerControl = generator.getExtension(ActivePowerControl.class); + ActivePowerControlAdder activePowerControlAdder = generator.newExtension(ActivePowerControlAdder.class); + ModificationUtils.getInstance().modifyActivePowerControlAttributes(activePowerControl, activePowerControlAdder, null, + new AttributeModification<>(Float.parseFloat(newValue), OperationType.SET), null, null); + } + case TRANSIENT_REACTANCE -> modifyGeneratorShortCircuitAttributes( + new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), + null, generator, null); + case STEP_UP_TRANSFORMER_REACTANCE -> modifyGeneratorShortCircuitAttributes( + null, new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), generator, null); + case Q_PERCENT -> generator.newExtension(CoordinatedReactiveControlAdderImpl.class) + .withQPercent(Double.parseDouble(newValue)) + .add(); + case VOLTAGE_REGULATOR_ON -> generator.setVoltageRegulatorOn(Boolean.parseBoolean(newValue)); + } + } +} diff --git a/src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/LoadField.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/LoadField.java similarity index 63% rename from src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/LoadField.java rename to src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/LoadField.java index 8c01d3f96..b0d52a427 100644 --- a/src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/LoadField.java +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/LoadField.java @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.gridsuite.modification.server.dto.formula.equipmentfield; +package org.gridsuite.modification.server.dto.byfilter.equipmentfield; import com.powsybl.iidm.network.Load; import org.gridsuite.modification.server.dto.AttributeModification; @@ -13,28 +13,32 @@ import static org.gridsuite.modification.server.modifications.LoadModification.modifyP0; import static org.gridsuite.modification.server.modifications.LoadModification.modifyQ0; +import com.powsybl.iidm.network.LoadType; +import jakarta.validation.constraints.NotNull; /** * @author Seddik Yengui */ - public enum LoadField { + LOAD_TYPE, ACTIVE_POWER, REACTIVE_POWER; - public static Double getReferenceValue(Load load, String loadField) { + public static String getReferenceValue(Load load, String loadField) { LoadField field = LoadField.valueOf(loadField); return switch (field) { - case ACTIVE_POWER -> load.getP0(); - case REACTIVE_POWER -> load.getQ0(); + case LOAD_TYPE -> load.getLoadType().name(); + case ACTIVE_POWER -> String.valueOf(load.getP0()); + case REACTIVE_POWER -> String.valueOf(load.getQ0()); }; } - public static void setNewValue(Load load, String loadField, Double newValue) { + public static void setNewValue(Load load, String loadField, @NotNull String newValue) { LoadField field = LoadField.valueOf(loadField); switch (field) { - case ACTIVE_POWER -> modifyP0(load, new AttributeModification<>(newValue, OperationType.SET), null); - case REACTIVE_POWER -> modifyQ0(load, new AttributeModification<>(newValue, OperationType.SET), null); + case LOAD_TYPE -> load.setLoadType(LoadType.valueOf(newValue)); + case ACTIVE_POWER -> modifyP0(load, new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), null); + case REACTIVE_POWER -> modifyQ0(load, new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), null); } } } diff --git a/src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/ShuntCompensatorField.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/ShuntCompensatorField.java similarity index 71% rename from src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/ShuntCompensatorField.java rename to src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/ShuntCompensatorField.java index 87dabb14a..1f97de712 100644 --- a/src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/ShuntCompensatorField.java +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/ShuntCompensatorField.java @@ -5,12 +5,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.gridsuite.modification.server.dto.formula.equipmentfield; +package org.gridsuite.modification.server.dto.byfilter.equipmentfield; import com.powsybl.iidm.network.ShuntCompensator; import com.powsybl.iidm.network.ShuntCompensatorLinearModel; import com.powsybl.iidm.network.ShuntCompensatorModelType; import com.powsybl.iidm.network.VoltageLevel; +import jakarta.validation.constraints.NotNull; import org.gridsuite.modification.server.NetworkModificationException; import org.gridsuite.modification.server.dto.AttributeModification; import org.gridsuite.modification.server.dto.OperationType; @@ -21,25 +22,24 @@ /** * @author Seddik Yengui */ - public enum ShuntCompensatorField { MAXIMUM_SECTION_COUNT, SECTION_COUNT, MAXIMUM_SUSCEPTANCE, MAXIMUM_Q_AT_NOMINAL_VOLTAGE; - public static Double getReferenceValue(ShuntCompensator shuntCompensator, String shuntCompensatorField) { + public static String getReferenceValue(ShuntCompensator shuntCompensator, String shuntCompensatorField) { VoltageLevel voltageLevel = shuntCompensator.getTerminal().getVoltageLevel(); ShuntCompensatorField field = ShuntCompensatorField.valueOf(shuntCompensatorField); return switch (field) { - case MAXIMUM_SECTION_COUNT -> (double) shuntCompensator.getMaximumSectionCount(); - case SECTION_COUNT -> (double) shuntCompensator.getSectionCount(); - case MAXIMUM_SUSCEPTANCE -> shuntCompensator.getB() * shuntCompensator.getMaximumSectionCount(); - case MAXIMUM_Q_AT_NOMINAL_VOLTAGE -> Math.abs(Math.pow(voltageLevel.getNominalV(), 2) * shuntCompensator.getB()) * shuntCompensator.getMaximumSectionCount(); + case MAXIMUM_SECTION_COUNT -> String.valueOf(shuntCompensator.getMaximumSectionCount()); + case SECTION_COUNT -> String.valueOf(shuntCompensator.getSectionCount()); + case MAXIMUM_SUSCEPTANCE -> String.valueOf(shuntCompensator.getB() * shuntCompensator.getMaximumSectionCount()); + case MAXIMUM_Q_AT_NOMINAL_VOLTAGE -> String.valueOf(Math.abs(Math.pow(voltageLevel.getNominalV(), 2) * shuntCompensator.getB()) * shuntCompensator.getMaximumSectionCount()); }; } - public static void setNewValue(ShuntCompensator shuntCompensator, String shuntCompensatorField, Double newValue) { + public static void setNewValue(ShuntCompensator shuntCompensator, String shuntCompensatorField, @NotNull String newValue) { if (shuntCompensator.getModelType() != ShuntCompensatorModelType.LINEAR) { throw new NetworkModificationException(NetworkModificationException.Type.BY_FORMULA_MODIFICATION_ERROR, String.format("Shunt compensator with %s model is not supported", shuntCompensator.getModelType())); @@ -52,12 +52,12 @@ public static void setNewValue(ShuntCompensator shuntCompensator, String shuntCo shuntCompensatorType = ShuntCompensatorType.CAPACITOR; } switch (field) { - case MAXIMUM_SECTION_COUNT -> modifyMaximumSectionCount(new AttributeModification<>(newValue.intValue(), OperationType.SET), + case MAXIMUM_SECTION_COUNT -> modifyMaximumSectionCount(new AttributeModification<>((int) Double.parseDouble(newValue), OperationType.SET), null, null, null, shuntCompensator, model); - case SECTION_COUNT -> modifySectionCount(new AttributeModification<>(newValue.intValue(), OperationType.SET), null, shuntCompensator); - case MAXIMUM_SUSCEPTANCE -> modifyMaxSusceptance(new AttributeModification<>(newValue, OperationType.SET), + case SECTION_COUNT -> modifySectionCount(new AttributeModification<>((int) Double.parseDouble(newValue), OperationType.SET), null, shuntCompensator); + case MAXIMUM_SUSCEPTANCE -> modifyMaxSusceptance(new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), shuntCompensator.getMaximumSectionCount(), null, model); - case MAXIMUM_Q_AT_NOMINAL_VOLTAGE -> modifyMaximumQAtNominalVoltage(new AttributeModification<>(newValue, OperationType.SET), + case MAXIMUM_Q_AT_NOMINAL_VOLTAGE -> modifyMaximumQAtNominalVoltage(new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), voltageLevel, shuntCompensator.getMaximumSectionCount(), null, model, shuntCompensatorType); } } diff --git a/src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/TwoWindingsTransformerField.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/TwoWindingsTransformerField.java similarity index 61% rename from src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/TwoWindingsTransformerField.java rename to src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/TwoWindingsTransformerField.java index 6a13e93d6..78d35d9bd 100644 --- a/src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/TwoWindingsTransformerField.java +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/TwoWindingsTransformerField.java @@ -1,12 +1,24 @@ -package org.gridsuite.modification.server.dto.formula.equipmentfield; +/** + * Copyright (c) 2023, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.dto.byfilter.equipmentfield; import com.powsybl.iidm.network.PhaseTapChanger; import com.powsybl.iidm.network.RatioTapChanger; import com.powsybl.iidm.network.TwoWindingsTransformer; +import jakarta.validation.constraints.NotNull; import org.gridsuite.modification.server.dto.AttributeModification; import org.gridsuite.modification.server.dto.OperationType; + import static org.gridsuite.modification.server.modifications.TwoWindingsTransformerModification.*; +/** + * @author Seddik Yengui + */ public enum TwoWindingsTransformerField { R, X, @@ -24,35 +36,35 @@ public enum TwoWindingsTransformerField { PHASE_TAP_POSITION, PHASE_TARGET_DEADBAND; - public static Double getReferenceValue(TwoWindingsTransformer transformer, String twoWindingsTransformerField) { + public static String getReferenceValue(TwoWindingsTransformer transformer, String twoWindingsTransformerField) { TwoWindingsTransformerField field = TwoWindingsTransformerField.valueOf(twoWindingsTransformerField); final PhaseTapChanger phaseTapChanger = transformer.getPhaseTapChanger(); final RatioTapChanger ratioTapChanger = transformer.getRatioTapChanger(); return switch (field) { - case R -> transformer.getR(); - case X -> transformer.getX(); - case G -> transformer.getG(); - case B -> transformer.getB(); - case RATED_U1 -> transformer.getRatedU1(); - case RATED_U2 -> transformer.getRatedU2(); - case RATED_S -> transformer.getRatedS(); - case TARGET_V -> ratioTapChanger != null ? ratioTapChanger.getTargetV() : null; - case RATIO_LOW_TAP_POSITION -> ratioTapChanger != null ? (double) ratioTapChanger.getLowTapPosition() : null; - case RATIO_TAP_POSITION -> ratioTapChanger != null ? (double) ratioTapChanger.getTapPosition() : null; - case RATIO_TARGET_DEADBAND -> ratioTapChanger != null ? ratioTapChanger.getTargetDeadband() : null; - case REGULATION_VALUE -> phaseTapChanger != null ? phaseTapChanger.getRegulationValue() : null; - case PHASE_LOW_TAP_POSITION -> phaseTapChanger != null ? (double) phaseTapChanger.getLowTapPosition() : null; - case PHASE_TAP_POSITION -> phaseTapChanger != null ? (double) phaseTapChanger.getTapPosition() : null; - case PHASE_TARGET_DEADBAND -> phaseTapChanger != null ? phaseTapChanger.getTargetDeadband() : null; + case R -> String.valueOf(transformer.getR()); + case X -> String.valueOf(transformer.getX()); + case G -> String.valueOf(transformer.getG()); + case B -> String.valueOf(transformer.getB()); + case RATED_U1 -> String.valueOf(transformer.getRatedU1()); + case RATED_U2 -> String.valueOf(transformer.getRatedU2()); + case RATED_S -> String.valueOf(transformer.getRatedS()); + case TARGET_V -> ratioTapChanger != null ? String.valueOf(ratioTapChanger.getTargetV()) : null; + case RATIO_LOW_TAP_POSITION -> ratioTapChanger != null ? String.valueOf(ratioTapChanger.getLowTapPosition()) : null; + case RATIO_TAP_POSITION -> ratioTapChanger != null ? String.valueOf(ratioTapChanger.getTapPosition()) : null; + case RATIO_TARGET_DEADBAND -> ratioTapChanger != null ? String.valueOf(ratioTapChanger.getTargetDeadband()) : null; + case REGULATION_VALUE -> phaseTapChanger != null ? String.valueOf(phaseTapChanger.getRegulationValue()) : null; + case PHASE_LOW_TAP_POSITION -> phaseTapChanger != null ? String.valueOf(phaseTapChanger.getLowTapPosition()) : null; + case PHASE_TAP_POSITION -> phaseTapChanger != null ? String.valueOf(phaseTapChanger.getTapPosition()) : null; + case PHASE_TARGET_DEADBAND -> phaseTapChanger != null ? String.valueOf(phaseTapChanger.getTargetDeadband()) : null; }; } - public static void setNewValue(TwoWindingsTransformer transformer, String twoWindingsTransformerField, Double newValue) { + public static void setNewValue(TwoWindingsTransformer transformer, String twoWindingsTransformerField, @NotNull String newValue) { TwoWindingsTransformerField field = TwoWindingsTransformerField.valueOf(twoWindingsTransformerField); final PhaseTapChanger phaseTapChanger = transformer.getPhaseTapChanger(); final RatioTapChanger ratioTapChanger = transformer.getRatioTapChanger(); final PhaseTapChanger.RegulationMode regulationMode = phaseTapChanger != null ? phaseTapChanger.getRegulationMode() : null; - final AttributeModification attributeModification = new AttributeModification<>(newValue, OperationType.SET); + final AttributeModification attributeModification = new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET); switch (field) { case R -> modifyR(transformer, attributeModification, null); @@ -64,17 +76,16 @@ public static void setNewValue(TwoWindingsTransformer transformer, String twoWin case RATED_S -> modifyRatedS(transformer, attributeModification, null); case TARGET_V -> modifyTargets(ratioTapChanger, null, true, attributeModification, null, null); case RATIO_LOW_TAP_POSITION -> processTapChangerPositionsAndSteps(ratioTapChanger, null, true, - new AttributeModification<>(newValue.intValue(), OperationType.SET), null, null, null); + new AttributeModification<>((int) Double.parseDouble(newValue), OperationType.SET), null, null, null); case RATIO_TAP_POSITION -> processTapChangerPositionsAndSteps(ratioTapChanger, null, true, - null, new AttributeModification<>(newValue.intValue(), OperationType.SET), null, null); + null, new AttributeModification<>((int) Double.parseDouble(newValue), OperationType.SET), null, null); case RATIO_TARGET_DEADBAND -> modifyTargets(ratioTapChanger, null, true, null, attributeModification, null); case REGULATION_VALUE -> processPhaseTapRegulation( - phaseTapChanger, null, regulationMode, true, attributeModification, null, null - ); + phaseTapChanger, null, regulationMode, true, attributeModification, null, null); case PHASE_LOW_TAP_POSITION -> processTapChangerPositionsAndSteps(phaseTapChanger, null, true, - new AttributeModification<>(newValue.intValue(), OperationType.SET), null, null, null); + new AttributeModification<>((int) Double.parseDouble(newValue), OperationType.SET), null, null, null); case PHASE_TAP_POSITION -> processTapChangerPositionsAndSteps(phaseTapChanger, null, true, - null, new AttributeModification<>(newValue.intValue(), OperationType.SET), null, null); + null, new AttributeModification<>((int) Double.parseDouble(newValue), OperationType.SET), null, null); case PHASE_TARGET_DEADBAND -> processPhaseTapRegulation( phaseTapChanger, null, null, true, null, attributeModification, null ); diff --git a/src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/VoltageLevelField.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/VoltageLevelField.java similarity index 60% rename from src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/VoltageLevelField.java rename to src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/VoltageLevelField.java index 69f366ad4..ee01ff24c 100644 --- a/src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/VoltageLevelField.java +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/equipmentfield/VoltageLevelField.java @@ -5,10 +5,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.gridsuite.modification.server.dto.formula.equipmentfield; +package org.gridsuite.modification.server.dto.byfilter.equipmentfield; import com.powsybl.iidm.network.VoltageLevel; import com.powsybl.iidm.network.extensions.IdentifiableShortCircuit; +import jakarta.validation.constraints.NotNull; import org.gridsuite.modification.server.dto.AttributeModification; import org.gridsuite.modification.server.dto.OperationType; @@ -17,7 +18,6 @@ /** * @author Seddik Yengui */ - public enum VoltageLevelField { NOMINAL_VOLTAGE, LOW_VOLTAGE_LIMIT, @@ -25,28 +25,28 @@ public enum VoltageLevelField { LOW_SHORT_CIRCUIT_CURRENT_LIMIT, HIGH_SHORT_CIRCUIT_CURRENT_LIMIT; - public static Double getReferenceValue(VoltageLevel voltageLevel, String voltageLevelField) { + public static String getReferenceValue(VoltageLevel voltageLevel, String voltageLevelField) { IdentifiableShortCircuit identifiableShortCircuit = voltageLevel.getExtension(IdentifiableShortCircuit.class); VoltageLevelField field = VoltageLevelField.valueOf(voltageLevelField); return switch (field) { - case NOMINAL_VOLTAGE -> voltageLevel.getNominalV(); - case LOW_VOLTAGE_LIMIT -> voltageLevel.getLowVoltageLimit(); - case HIGH_VOLTAGE_LIMIT -> voltageLevel.getHighVoltageLimit(); - case LOW_SHORT_CIRCUIT_CURRENT_LIMIT -> identifiableShortCircuit == null ? null : identifiableShortCircuit.getIpMin(); - case HIGH_SHORT_CIRCUIT_CURRENT_LIMIT -> identifiableShortCircuit == null ? null : identifiableShortCircuit.getIpMax(); + case NOMINAL_VOLTAGE -> String.valueOf(voltageLevel.getNominalV()); + case LOW_VOLTAGE_LIMIT -> String.valueOf(voltageLevel.getLowVoltageLimit()); + case HIGH_VOLTAGE_LIMIT -> String.valueOf(voltageLevel.getHighVoltageLimit()); + case LOW_SHORT_CIRCUIT_CURRENT_LIMIT -> identifiableShortCircuit != null ? String.valueOf(identifiableShortCircuit.getIpMin()) : null; + case HIGH_SHORT_CIRCUIT_CURRENT_LIMIT -> identifiableShortCircuit != null ? String.valueOf(identifiableShortCircuit.getIpMax()) : null; }; } - public static void setNewValue(VoltageLevel voltageLevel, String voltageLevelField, Double newValue) { + public static void setNewValue(VoltageLevel voltageLevel, String voltageLevelField, @NotNull String newValue) { VoltageLevelField field = VoltageLevelField.valueOf(voltageLevelField); switch (field) { - case NOMINAL_VOLTAGE -> modifyNominalV(voltageLevel, new AttributeModification<>(newValue, OperationType.SET), null); - case LOW_VOLTAGE_LIMIT -> modifLowVoltageLimit(voltageLevel, new AttributeModification<>(newValue, OperationType.SET), null); - case HIGH_VOLTAGE_LIMIT -> modifyHighVoltageLimit(voltageLevel, new AttributeModification<>(newValue, OperationType.SET), null); + case NOMINAL_VOLTAGE -> modifyNominalV(voltageLevel, new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), null); + case LOW_VOLTAGE_LIMIT -> modifLowVoltageLimit(voltageLevel, new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), null); + case HIGH_VOLTAGE_LIMIT -> modifyHighVoltageLimit(voltageLevel, new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), null); case LOW_SHORT_CIRCUIT_CURRENT_LIMIT -> modifyVoltageLevelShortCircuit( - new AttributeModification<>(newValue, OperationType.SET), null, null, voltageLevel); + new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), null, null, voltageLevel); case HIGH_SHORT_CIRCUIT_CURRENT_LIMIT -> modifyVoltageLevelShortCircuit( - null, new AttributeModification<>(newValue, OperationType.SET), null, voltageLevel); + null, new AttributeModification<>(Double.parseDouble(newValue), OperationType.SET), null, voltageLevel); } } } diff --git a/src/main/java/org/gridsuite/modification/server/dto/formula/FormulaInfos.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/formula/FormulaInfos.java similarity index 67% rename from src/main/java/org/gridsuite/modification/server/dto/formula/FormulaInfos.java rename to src/main/java/org/gridsuite/modification/server/dto/byfilter/formula/FormulaInfos.java index 736556a4d..663191c4e 100644 --- a/src/main/java/org/gridsuite/modification/server/dto/formula/FormulaInfos.java +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/formula/FormulaInfos.java @@ -5,19 +5,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.gridsuite.modification.server.dto.formula; +package org.gridsuite.modification.server.dto.byfilter.formula; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.SuperBuilder; -import org.gridsuite.modification.server.dto.FilterInfos; -import org.gridsuite.modification.server.entities.equipment.modification.FormulaEntity; - -import java.util.List; -import java.util.UUID; +import org.gridsuite.modification.server.dto.byfilter.AbstractAssignmentInfos; +import org.gridsuite.modification.server.entities.equipment.modification.byfilter.formula.FormulaEntity; /** * @author Seddik Yengui @@ -25,18 +21,9 @@ @SuperBuilder @NoArgsConstructor -@AllArgsConstructor @Getter @Setter -public class FormulaInfos { - @Schema(description = "id") - private UUID id; - - @Schema(description = "List of filters") - private List filters; - - @Schema(description = "Edited field") - private String editedField; +public class FormulaInfos extends AbstractAssignmentInfos { @Schema(description = "First reference field or value") private ReferenceFieldOrValue fieldOrValue1; diff --git a/src/main/java/org/gridsuite/modification/server/dto/formula/Operator.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/formula/Operator.java similarity index 87% rename from src/main/java/org/gridsuite/modification/server/dto/formula/Operator.java rename to src/main/java/org/gridsuite/modification/server/dto/byfilter/formula/Operator.java index d00f5e65d..df134ec57 100644 --- a/src/main/java/org/gridsuite/modification/server/dto/formula/Operator.java +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/formula/Operator.java @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.gridsuite.modification.server.dto.formula; +package org.gridsuite.modification.server.dto.byfilter.formula; /** * @author Seddik Yengui diff --git a/src/main/java/org/gridsuite/modification/server/dto/byfilter/formula/ReferenceFieldOrValue.java b/src/main/java/org/gridsuite/modification/server/dto/byfilter/formula/ReferenceFieldOrValue.java new file mode 100644 index 000000000..1967b81dd --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/byfilter/formula/ReferenceFieldOrValue.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2023, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.dto.byfilter.formula; + +import com.powsybl.iidm.network.Identifiable; +import lombok.*; +import org.gridsuite.modification.server.NetworkModificationException; + +import static org.gridsuite.modification.server.dto.byfilter.equipmentfield.FieldUtils.getFieldValue; + + +/** + * @author Seddik Yengui + */ + +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +public class ReferenceFieldOrValue { + private String equipmentField; + + private Double value; + + public Double getRefOrValue(Identifiable identifiable) { + if (value == null && equipmentField == null) { + throw new NetworkModificationException(NetworkModificationException.Type.BY_FORMULA_MODIFICATION_ERROR, + "There is no value or reference to any of the equipment fields"); + } + + if (value != null && !Double.isNaN(value)) { + return value; + } + + String referenceValue = getFieldValue(identifiable, equipmentField); + + if (referenceValue == null) { + return Double.NaN; + } + + return Double.parseDouble(referenceValue); + } + +} diff --git a/src/main/java/org/gridsuite/modification/server/dto/formula/ReferenceFieldOrValue.java b/src/main/java/org/gridsuite/modification/server/dto/formula/ReferenceFieldOrValue.java deleted file mode 100644 index aaae6b502..000000000 --- a/src/main/java/org/gridsuite/modification/server/dto/formula/ReferenceFieldOrValue.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (c) 2023, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package org.gridsuite.modification.server.dto.formula; - -import com.powsybl.iidm.network.Battery; -import com.powsybl.iidm.network.Generator; -import com.powsybl.iidm.network.Identifiable; -import com.powsybl.iidm.network.IdentifiableType; -import com.powsybl.iidm.network.Load; -import com.powsybl.iidm.network.ShuntCompensator; -import com.powsybl.iidm.network.TwoWindingsTransformer; -import com.powsybl.iidm.network.VoltageLevel; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import org.gridsuite.modification.server.NetworkModificationException; -import org.gridsuite.modification.server.dto.formula.equipmentfield.BatteryField; -import org.gridsuite.modification.server.dto.formula.equipmentfield.GeneratorField; -import org.gridsuite.modification.server.dto.formula.equipmentfield.LoadField; -import org.gridsuite.modification.server.dto.formula.equipmentfield.ShuntCompensatorField; -import org.gridsuite.modification.server.dto.formula.equipmentfield.TwoWindingsTransformerField; -import org.gridsuite.modification.server.dto.formula.equipmentfield.VoltageLevelField; - - -/** - * @author Seddik Yengui - */ - -@Builder -@NoArgsConstructor -@AllArgsConstructor -@Getter -@Setter -public class ReferenceFieldOrValue { - private String equipmentField; - - private Double value; - - public Double getRefOrValue(Identifiable identifiable) { - if (value == null && equipmentField == null) { - throw new NetworkModificationException(NetworkModificationException.Type.BY_FORMULA_MODIFICATION_ERROR, - "There is no value or reference to any of the equipment fields"); - } - - if (value != null && !Double.isNaN(value)) { - return value; - } - - IdentifiableType identifiableType = identifiable.getType(); - return switch (identifiableType) { - case GENERATOR -> GeneratorField.getReferenceValue((Generator) identifiable, equipmentField); - case BATTERY -> BatteryField.getReferenceValue((Battery) identifiable, equipmentField); - case SHUNT_COMPENSATOR -> ShuntCompensatorField.getReferenceValue((ShuntCompensator) identifiable, equipmentField); - case VOLTAGE_LEVEL -> VoltageLevelField.getReferenceValue((VoltageLevel) identifiable, equipmentField); - case LOAD -> LoadField.getReferenceValue((Load) identifiable, equipmentField); - case TWO_WINDINGS_TRANSFORMER -> TwoWindingsTransformerField.getReferenceValue((TwoWindingsTransformer) identifiable, equipmentField); - default -> throw new NetworkModificationException(NetworkModificationException.Type.BY_FORMULA_MODIFICATION_ERROR, - String.format("Unsupported equipment type : %s", identifiableType.name())); - }; - } -} diff --git a/src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/GeneratorField.java b/src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/GeneratorField.java deleted file mode 100644 index d36390c58..000000000 --- a/src/main/java/org/gridsuite/modification/server/dto/formula/equipmentfield/GeneratorField.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright (c) 2023, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package org.gridsuite.modification.server.dto.formula.equipmentfield; - -import com.powsybl.iidm.network.Generator; -import com.powsybl.iidm.network.extensions.ActivePowerControl; -import com.powsybl.iidm.network.extensions.ActivePowerControlAdder; -import com.powsybl.iidm.network.extensions.CoordinatedReactiveControl; -import com.powsybl.iidm.network.extensions.GeneratorShortCircuit; -import com.powsybl.iidm.network.extensions.GeneratorStartup; -import com.powsybl.network.store.iidm.impl.extensions.CoordinatedReactiveControlAdderImpl; -import org.gridsuite.modification.server.dto.AttributeModification; -import org.gridsuite.modification.server.dto.OperationType; -import org.gridsuite.modification.server.modifications.ModificationUtils; - -import static org.gridsuite.modification.server.NetworkModificationException.Type.MODIFY_GENERATOR_ERROR; -import static org.gridsuite.modification.server.modifications.GeneratorModification.*; - -/** - * @author Seddik Yengui - */ - -public enum GeneratorField { - MINIMUM_ACTIVE_POWER, - MAXIMUM_ACTIVE_POWER, - RATED_NOMINAL_POWER, - ACTIVE_POWER_SET_POINT, - REACTIVE_POWER_SET_POINT, - VOLTAGE_SET_POINT, - PLANNED_ACTIVE_POWER_SET_POINT, - MARGINAL_COST, - PLANNED_OUTAGE_RATE, - FORCED_OUTAGE_RATE, - DROOP, - TRANSIENT_REACTANCE, - STEP_UP_TRANSFORMER_REACTANCE, - Q_PERCENT; - - public static Double getReferenceValue(Generator generator, String generatorField) { - ActivePowerControl activePowerControl = generator.getExtension(ActivePowerControl.class); - GeneratorStartup generatorStartup = generator.getExtension(GeneratorStartup.class); - GeneratorShortCircuit generatorShortCircuit = generator.getExtension(GeneratorShortCircuit.class); - CoordinatedReactiveControl coordinatedReactiveControl = generator.getExtension(CoordinatedReactiveControl.class); - GeneratorField field = GeneratorField.valueOf(generatorField); - return switch (field) { - case MAXIMUM_ACTIVE_POWER -> generator.getMaxP(); - case MINIMUM_ACTIVE_POWER -> generator.getMinP(); - case ACTIVE_POWER_SET_POINT -> generator.getTargetP(); - case RATED_NOMINAL_POWER -> generator.getRatedS(); - case REACTIVE_POWER_SET_POINT -> generator.getTargetQ(); - case VOLTAGE_SET_POINT -> generator.getTargetV(); - case PLANNED_ACTIVE_POWER_SET_POINT -> generatorStartup != null ? generatorStartup.getPlannedActivePowerSetpoint() : null; - case MARGINAL_COST -> generatorStartup != null ? generatorStartup.getMarginalCost() : null; - case PLANNED_OUTAGE_RATE -> generatorStartup != null ? generatorStartup.getPlannedOutageRate() : null; - case FORCED_OUTAGE_RATE -> generatorStartup != null ? generatorStartup.getForcedOutageRate() : null; - case DROOP -> activePowerControl != null ? activePowerControl.getDroop() : null; - case TRANSIENT_REACTANCE -> generatorShortCircuit != null ? generatorShortCircuit.getDirectTransX() : null; - case STEP_UP_TRANSFORMER_REACTANCE -> generatorShortCircuit != null ? generatorShortCircuit.getStepUpTransformerX() : null; - case Q_PERCENT -> coordinatedReactiveControl != null ? coordinatedReactiveControl.getQPercent() : null; - }; - } - - public static void setNewValue(Generator generator, String generatorField, double newValue) { - if (!Double.isNaN(newValue)) { - GeneratorField field = GeneratorField.valueOf(generatorField); - final AttributeModification attributeModification = new AttributeModification<>(newValue, OperationType.SET); - switch (field) { - case MAXIMUM_ACTIVE_POWER -> modifyGeneratorActiveLimitsAttributes( - attributeModification, null, null, generator, null); - case MINIMUM_ACTIVE_POWER -> modifyGeneratorActiveLimitsAttributes(null, attributeModification, null, generator, null); - case ACTIVE_POWER_SET_POINT -> { - ModificationUtils.getInstance().checkActivePowerZeroOrBetweenMinAndMaxActivePower( - attributeModification, null, null, - generator.getMinP(), generator.getMaxP(), generator.getTargetP(), - MODIFY_GENERATOR_ERROR, "Generator '" + generator.getId() + "' : " - ); - generator.setTargetP(newValue); - } - case RATED_NOMINAL_POWER -> modifyGeneratorActiveLimitsAttributes(null, null, attributeModification, generator, null); - case REACTIVE_POWER_SET_POINT -> modifyTargetQ(generator, attributeModification); - case VOLTAGE_SET_POINT -> modifyTargetV(generator, attributeModification); - case PLANNED_ACTIVE_POWER_SET_POINT -> - modifyGeneratorStartUpAttributes(attributeModification, null, null, null, generator, null, null); - case MARGINAL_COST -> - modifyGeneratorStartUpAttributes(null, attributeModification, null, null, generator, null, null); - case PLANNED_OUTAGE_RATE -> - modifyGeneratorStartUpAttributes(null, null, attributeModification, null, generator, null, null); - case FORCED_OUTAGE_RATE -> - modifyGeneratorStartUpAttributes(null, null, null, attributeModification, generator, null, null); - case DROOP -> { - ActivePowerControl activePowerControl = generator.getExtension(ActivePowerControl.class); - ActivePowerControlAdder activePowerControlAdder = generator.newExtension(ActivePowerControlAdder.class); - ModificationUtils.getInstance().modifyActivePowerControlAttributes(activePowerControl, activePowerControlAdder, null, - new AttributeModification<>((float) newValue, OperationType.SET), null, null); - } - case TRANSIENT_REACTANCE -> modifyGeneratorShortCircuitAttributes(attributeModification, null, generator, null); - case STEP_UP_TRANSFORMER_REACTANCE -> modifyGeneratorShortCircuitAttributes(null, attributeModification, generator, null); - case Q_PERCENT -> generator.newExtension(CoordinatedReactiveControlAdderImpl.class) - .withQPercent(newValue) - .add(); - } - } - } -} diff --git a/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/AbstractAssignmentEntity.java b/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/AbstractAssignmentEntity.java new file mode 100644 index 000000000..908298762 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/AbstractAssignmentEntity.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.entities.equipment.modification.byfilter; + +import jakarta.persistence.*; +import lombok.NoArgsConstructor; +import org.gridsuite.modification.server.dto.byfilter.AbstractAssignmentInfos; + +import java.util.UUID; + +/** + * @author Thang PHAM + */ +@NoArgsConstructor +@MappedSuperclass +public abstract class AbstractAssignmentEntity { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "id") + private UUID id; + + @Column + private String editedField; + + protected AbstractAssignmentEntity(AbstractAssignmentInfos abstractAssignmentInfos) { + this.id = null; + this.editedField = abstractAssignmentInfos.getEditedField(); + } + + protected void assignAttributes(AbstractAssignmentInfos modificationByFilterInfos) { + modificationByFilterInfos.setId(id); + modificationByFilterInfos.setEditedField(editedField); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/ByFormulaModificationEntity.java b/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/ByFormulaModificationEntity.java similarity index 92% rename from src/main/java/org/gridsuite/modification/server/entities/equipment/modification/ByFormulaModificationEntity.java rename to src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/ByFormulaModificationEntity.java index 384ff94d2..c925de273 100644 --- a/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/ByFormulaModificationEntity.java +++ b/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/ByFormulaModificationEntity.java @@ -1,15 +1,13 @@ -package org.gridsuite.modification.server.entities.equipment.modification; +package org.gridsuite.modification.server.entities.equipment.modification.byfilter; import com.powsybl.iidm.network.IdentifiableType; import jakarta.persistence.*; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.NonNull; -import lombok.Setter; +import lombok.*; import org.gridsuite.modification.server.dto.ByFormulaModificationInfos; import org.gridsuite.modification.server.dto.ModificationInfos; -import org.gridsuite.modification.server.dto.formula.FormulaInfos; +import org.gridsuite.modification.server.dto.byfilter.formula.FormulaInfos; import org.gridsuite.modification.server.entities.ModificationEntity; +import org.gridsuite.modification.server.entities.equipment.modification.byfilter.formula.FormulaEntity; import java.util.List; import java.util.stream.Collectors; diff --git a/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/ModificationByAssignmentEntity.java b/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/ModificationByAssignmentEntity.java new file mode 100644 index 000000000..de90005f1 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/ModificationByAssignmentEntity.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.entities.equipment.modification.byfilter; + +import com.powsybl.iidm.network.IdentifiableType; +import jakarta.persistence.*; +import lombok.NoArgsConstructor; +import lombok.NonNull; +import org.gridsuite.modification.server.dto.ModificationByAssignmentInfos; +import org.gridsuite.modification.server.dto.ModificationInfos; +import org.gridsuite.modification.server.dto.byfilter.assignment.AssignmentInfos; +import org.gridsuite.modification.server.entities.ModificationEntity; +import org.gridsuite.modification.server.entities.equipment.modification.byfilter.assignment.AssignmentEntity; + +import java.util.List; + +/** + * @author Thang PHAM + */ +@NoArgsConstructor +@Entity +@Table(name = "modificationByAssignment") +@PrimaryKeyJoinColumn(foreignKey = @ForeignKey(name = "modificationByAssignment_id_fk_constraint")) +public class ModificationByAssignmentEntity extends ModificationEntity { + @Enumerated(EnumType.STRING) + @Column + private IdentifiableType equipmentType; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + @JoinColumn(name = "modification_by_assignment_id", + foreignKey = @ForeignKey(name = "modification_by_assignment_id_fk")) + private List assignmentEntities; + + public ModificationByAssignmentEntity(ModificationByAssignmentInfos modificationByAssignmentInfos) { + super(modificationByAssignmentInfos); + assignAttributes(modificationByAssignmentInfos); + } + + @Override + public void update(@NonNull ModificationInfos modificationInfos) { + super.update(modificationInfos); + assignAttributes((ModificationByAssignmentInfos) modificationInfos); + } + + private void assignAttributes(ModificationByAssignmentInfos modificationByAssignmentInfos) { + this.equipmentType = modificationByAssignmentInfos.getEquipmentType(); + if (assignmentEntities == null) { + assignmentEntities = modificationByAssignmentInfos.getAssignmentInfosList() + .stream() + .map(AssignmentInfos::toEntity) + .toList(); + } else { + assignmentEntities.clear(); + assignmentEntities.addAll(modificationByAssignmentInfos.getAssignmentInfosList() + .stream() + .map(AssignmentInfos::toEntity) + .toList()); + } + } + + @Override + public ModificationByAssignmentInfos toModificationInfos() { + return toModificationByAssignmentInfosBuilder().build(); + } + + private ModificationByAssignmentInfos.ModificationByAssignmentInfosBuilder toModificationByAssignmentInfosBuilder() { + return ModificationByAssignmentInfos.builder() + .uuid(getId()) + .date(getDate()) + .stashed(getStashed()) + .activated(getActivated()) + .equipmentType(equipmentType) + .assignmentInfosList(assignmentEntities.stream() + .map(AssignmentEntity::toAssignmentInfos) + .toList() + ); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/assignment/AssignmentEntity.java b/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/assignment/AssignmentEntity.java new file mode 100644 index 000000000..ae1f2ee8c --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/assignment/AssignmentEntity.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.entities.equipment.modification.byfilter.assignment; + +import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.gridsuite.modification.server.dto.FilterInfos; +import org.gridsuite.modification.server.dto.byfilter.DataType; +import org.gridsuite.modification.server.dto.byfilter.assignment.*; +import org.gridsuite.modification.server.entities.equipment.modification.VariationFilterEntity; +import org.gridsuite.modification.server.entities.equipment.modification.byfilter.AbstractAssignmentEntity; + +import java.util.List; + +/** + * @author Thang PHAM + */ +@NoArgsConstructor +@Entity +@Table(name = "assignment", indexes = @Index(name = "modification_by_assignment_id_idx", columnList = "modification_by_assignment_id")) +public class AssignmentEntity extends AbstractAssignmentEntity { + @Column + @Enumerated(EnumType.STRING) + private DataType dataType; + + @NotNull + @Column(name = "value_") // "value" is not supported in UT with H2 + private String value; // all values of different data types will be serialized as a string, deserialization is based on dataType + + @Setter + @Column + private String propertyName; // dedicated to an exceptional case, i.e. modify a property + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + @JoinColumn(name = "assignment_id", + foreignKey = @ForeignKey(name = "assignment_id_fk")) + private List filters; + + public AssignmentEntity(AssignmentInfos assignmentInfos) { + super(assignmentInfos); + this.dataType = assignmentInfos.getDataType(); + this.value = assignmentInfos.getValue().toString(); + this.filters = assignmentInfos.getFilters().stream().map(FilterInfos::toEntity).toList(); + } + + public AssignmentInfos toAssignmentInfos() { + AssignmentInfos assignmentInfos = switch (dataType) { + case BOOLEAN -> BooleanAssignmentInfos.builder() + .value(Boolean.valueOf(value)) + .build(); + case INTEGER -> IntegerAssignmentInfos.builder() + .value(Integer.valueOf(value)) + .build(); + case DOUBLE -> DoubleAssignmentInfos.builder() + .value(Double.valueOf(value)) + .build(); + case ENUM -> EnumAssignmentInfos.builder() + .value(value) + .build(); + case PROPERTY -> PropertyAssignmentInfos.builder() + .value(value) + .propertyName(propertyName) + .build(); + }; + + assignAttributes(assignmentInfos); + assignmentInfos.setFilters(filters.stream() + .map(filterEntity -> new FilterInfos(filterEntity.getFilterId(), filterEntity.getName())) + .toList()); + return assignmentInfos; + } +} diff --git a/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/FormulaEntity.java b/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/formula/FormulaEntity.java similarity index 64% rename from src/main/java/org/gridsuite/modification/server/entities/equipment/modification/FormulaEntity.java rename to src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/formula/FormulaEntity.java index 1ea147165..4c2b4cdd0 100644 --- a/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/FormulaEntity.java +++ b/src/main/java/org/gridsuite/modification/server/entities/equipment/modification/byfilter/formula/FormulaEntity.java @@ -5,44 +5,32 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.gridsuite.modification.server.entities.equipment.modification; +package org.gridsuite.modification.server.entities.equipment.modification.byfilter.formula; import jakarta.persistence.*; -import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.Setter; import org.gridsuite.modification.server.dto.FilterInfos; -import org.gridsuite.modification.server.dto.formula.FormulaInfos; -import org.gridsuite.modification.server.dto.formula.Operator; -import org.gridsuite.modification.server.dto.formula.ReferenceFieldOrValue; +import org.gridsuite.modification.server.dto.byfilter.formula.FormulaInfos; +import org.gridsuite.modification.server.dto.byfilter.formula.Operator; +import org.gridsuite.modification.server.dto.byfilter.formula.ReferenceFieldOrValue; +import org.gridsuite.modification.server.entities.equipment.modification.VariationFilterEntity; +import org.gridsuite.modification.server.entities.equipment.modification.byfilter.AbstractAssignmentEntity; import java.util.List; -import java.util.UUID; -import java.util.stream.Collectors; /** * @author Seddik Yengui */ @NoArgsConstructor -@Getter -@Setter @Entity @Table(name = "formula", indexes = @Index(name = "by_formula_modification_id_idx", columnList = "by_formula_modification_id")) -public class FormulaEntity { - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - @Column(name = "id") - private UUID id; - +public class FormulaEntity extends AbstractAssignmentEntity { @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) @JoinColumn(name = "formula_id", foreignKey = @ForeignKey(name = "formula_id_fk")) private List filters; - @Column - private String editedField; - @Column private String equipmentField1; @@ -59,32 +47,31 @@ public class FormulaEntity { private Operator operator; public FormulaEntity(FormulaInfos formulaInfos) { - this.id = null; - this.filters = formulaInfos.getFilters().stream().map(FilterInfos::toEntity).collect(Collectors.toList()); - this.editedField = formulaInfos.getEditedField(); + super(formulaInfos); this.equipmentField1 = formulaInfos.getFieldOrValue1().getEquipmentField(); this.equipmentField2 = formulaInfos.getFieldOrValue2().getEquipmentField(); this.value1 = formulaInfos.getFieldOrValue1().getValue(); this.value2 = formulaInfos.getFieldOrValue2().getValue(); this.operator = formulaInfos.getOperator(); + this.filters = formulaInfos.getFilters().stream().map(FilterInfos::toEntity).toList(); } public FormulaInfos toFormulaInfos() { - return FormulaInfos.builder() - .id(getId()) - .filters(getFilters().stream() + FormulaInfos formulaInfos = FormulaInfos.builder() + .filters(filters.stream() .map(filterEntity -> new FilterInfos(filterEntity.getFilterId(), filterEntity.getName())) - .collect(Collectors.toList())) - .editedField(getEditedField()) + .toList()) .fieldOrValue1(ReferenceFieldOrValue.builder() - .equipmentField(getEquipmentField1()) - .value(getValue1()) + .equipmentField(equipmentField1) + .value(value1) .build()) .fieldOrValue2(ReferenceFieldOrValue.builder() - .equipmentField(getEquipmentField2()) - .value(getValue2()) + .equipmentField(equipmentField2) + .value(value2) .build()) - .operator(getOperator()) + .operator(operator) .build(); + assignAttributes(formulaInfos); + return formulaInfos; } } diff --git a/src/main/java/org/gridsuite/modification/server/modifications/ByFormulaModification.java b/src/main/java/org/gridsuite/modification/server/modifications/ByFormulaModification.java deleted file mode 100644 index a1f119008..000000000 --- a/src/main/java/org/gridsuite/modification/server/modifications/ByFormulaModification.java +++ /dev/null @@ -1,307 +0,0 @@ -/** - * Copyright (c) 2023, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package org.gridsuite.modification.server.modifications; - -import com.powsybl.commons.report.ReportNode; -import com.powsybl.commons.report.TypedValue; -import com.powsybl.iidm.network.*; -import org.gridsuite.modification.server.NetworkModificationException; -import org.gridsuite.modification.server.dto.ByFormulaModificationInfos; -import org.gridsuite.modification.server.dto.FilterEquipments; -import org.gridsuite.modification.server.dto.FilterInfos; -import org.gridsuite.modification.server.dto.formula.FormulaInfos; -import org.gridsuite.modification.server.dto.formula.Operator; -import org.gridsuite.modification.server.dto.formula.equipmentfield.*; -import org.gridsuite.modification.server.service.FilterService; -import org.jetbrains.annotations.NotNull; -import org.springframework.util.CollectionUtils; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.stream.Collectors; - -import static org.gridsuite.modification.server.modifications.ModificationUtils.*; - -public class ByFormulaModification extends AbstractModification { - public static final String EQUIPMENT_MODIFIED_REPORT_ERROR = "EquipmentModifiedReportError_"; - public static final String KEY_FILTER_NAME = "filterName"; - public static final String KEY_FIELD_NAME = "fieldName"; - public static final String KEY_EQPT_NAME = "eqptName"; - public static final String KEY_EQPT_TYPE = "eqptType"; - public static final String KEY_NB_CHANGED = "nbChanged"; - public static final String KEY_NB_UNCHANGED = "nbUnchanged"; - public static final String KEY_VALUE = "value"; - private final ByFormulaModificationInfos modificationInfos; - protected FilterService filterService; - private int equipmentNotModifiedCount; - private long equipmentCount; - private long equipmentNotFoundCount; - - public ByFormulaModification(ByFormulaModificationInfos modificationInfos) { - this.modificationInfos = modificationInfos; - equipmentNotModifiedCount = 0; - equipmentCount = 0; - equipmentNotFoundCount = 0; - } - - @Override - public void initApplicationContext(NetworkModificationApplicator modificationApplicator) { - filterService = modificationApplicator.getFilterService(); - } - - @Override - public void check(Network network) throws NetworkModificationException { - if (modificationInfos == null) { - throw new NetworkModificationException(NetworkModificationException.Type.BY_FORMULA_MODIFICATION_ERROR, "Missing required attributes to modify the equipment"); - } - - if (CollectionUtils.isEmpty(modificationInfos.getFormulaInfosList())) { - throw new NetworkModificationException(NetworkModificationException.Type.BY_FORMULA_MODIFICATION_ERROR, "At least one formula is required"); - } - - if (modificationInfos.getFormulaInfosList().stream().anyMatch(formulaInfos -> CollectionUtils.isEmpty(formulaInfos.getFilters()))) { - throw new NetworkModificationException(NetworkModificationException.Type.BY_FORMULA_MODIFICATION_ERROR, "Every formula must have at least one filter"); - } - } - - @Override - public void apply(Network network, ReportNode subReportNode) { - // collect all filters from all variations - Map filters = modificationInfos.getFormulaInfosList().stream() - .flatMap(v -> v.getFilters().stream()) - .filter(distinctByKey(FilterInfos::getId)) - .collect(Collectors.toMap(FilterInfos::getId, FilterInfos::getName)); - - Map exportFilters = ModificationUtils.getUuidFilterEquipmentsMap(filterService, network, subReportNode, filters, modificationInfos.getErrorType()); - - if (exportFilters != null) { - ReportNode formulaSubReporter = subReportNode.newReportNode().withMessageTemplate("appliedFormulasModifications", "Formulas").add(); - List formulaReports = new ArrayList<>(); - modificationInfos.getFormulaInfosList().forEach(formulaInfos -> - formulaInfos.getFilters().forEach(filterInfos -> - applyFormulaOnFilterEquipments(network, exportFilters, formulaReports, formulaInfos, filterInfos))); - subReportNode.newReportNode() - .withMessageTemplate("byFormulaModification", "New modification by formula on ${" + KEY_EQPT_TYPE + "}") - .withUntypedValue(KEY_EQPT_TYPE, modificationInfos.getIdentifiableType().name()) - .withSeverity(TypedValue.INFO_SEVERITY) - .add(); - if (equipmentNotModifiedCount == 0 && equipmentNotFoundCount == 0) { - subReportNode.newReportNode() - .withMessageTemplate("byFormulaModificationALL", "All equipment have been modified : ${" + KEY_VALUE + "} equipment(s)") - .withUntypedValue(KEY_VALUE, equipmentCount) - .withSeverity(TypedValue.INFO_SEVERITY) - .add(); - } else { - if (equipmentNotModifiedCount == equipmentCount) { - createReport(subReportNode, "byFormulaModificationNone", - "No equipment have been modified", - Map.of(), TypedValue.ERROR_SEVERITY); - } else { - subReportNode.newReportNode() - .withMessageTemplate("byFormulaModificationSome", "Some of the equipment have been modified : ${" + KEY_NB_CHANGED + "} equipment(s) modified and ${" + KEY_NB_UNCHANGED + "} equipment(s) not modified") - .withUntypedValue(KEY_NB_CHANGED, equipmentCount - equipmentNotModifiedCount) - .withUntypedValue(KEY_NB_UNCHANGED, equipmentNotModifiedCount + equipmentNotFoundCount) - .withSeverity(TypedValue.WARN_SEVERITY) - .add(); - } - } - report(formulaSubReporter, formulaReports); - } - } - - private void report(ReportNode formulaSubReportNode, List formulaReports) { - formulaReports.forEach(report -> insertReportNode(formulaSubReportNode, report)); - } - - private void applyFormulaOnFilterEquipments(Network network, - Map exportFilters, - List formulaReports, - FormulaInfos formulaInfos, - FilterInfos filterInfos) { - FilterEquipments filterEquipments = exportFilters.get(filterInfos.getId()); - - if (CollectionUtils.isEmpty(filterEquipments.getIdentifiableAttributes())) { - formulaReports.add(ReportNode.newRootReportNode() - .withMessageTemplate("byFormulaModificationFormulaFilter_" + formulaReports.size(), "No equipments were found for filter ${" + KEY_FILTER_NAME + "}") - .withUntypedValue(KEY_FILTER_NAME, filterInfos.getName()) - .withSeverity(TypedValue.WARN_SEVERITY) - .build()); - } else { - equipmentCount += filterEquipments.getIdentifiableAttributes().size(); - if (!CollectionUtils.isEmpty(filterEquipments.getNotFoundEquipments())) { - equipmentNotFoundCount += filterEquipments.getNotFoundEquipments().size(); - } - List notEditableEquipments = new ArrayList<>(); - List equipmentsReport = new ArrayList<>(); - filterEquipments.getIdentifiableAttributes() - .stream() - .map(attributes -> network.getIdentifiable(attributes.getId())) - .filter(identifiable -> { - boolean isEditableEquipment = isEquipmentEditable(identifiable, formulaInfos, equipmentsReport); - if (!isEditableEquipment) { - notEditableEquipments.add(identifiable.getId()); - equipmentNotModifiedCount += 1; - } - return isEditableEquipment; - }) - .forEach(identifiable -> applyFormula(identifiable, formulaInfos, equipmentsReport, notEditableEquipments)); - - createFormulaReports(formulaReports, formulaInfos, filterInfos, filterEquipments, notEditableEquipments); - - formulaReports.addAll(equipmentsReport); - } - } - - private void createFormulaReports(List formulaReports, FormulaInfos formulaInfos, FilterInfos filterInfos, FilterEquipments filterEquipments, List notEditableEquipments) { - if (notEditableEquipments.size() == filterEquipments.getIdentifiableAttributes().size()) { - formulaReports.add(ReportNode.newRootReportNode() - .withMessageTemplate("byFormulaModificationFormulaFilterFailed_" + formulaReports.size(), "No equipment(s) have been modified on filter ${" + KEY_FILTER_NAME + "}") - .withUntypedValue(KEY_FILTER_NAME, filterInfos.getName()) - .withSeverity(TypedValue.WARN_SEVERITY) - .build()); - } else { - formulaReports.add(ReportNode.newRootReportNode() - .withMessageTemplate("byFormulaModificationFormulaFilter_" + formulaReports.size(), "Successful application of new modification by formula on filter ${" + KEY_FILTER_NAME + "}") - .withUntypedValue(KEY_FILTER_NAME, filterInfos.getName()) - .withSeverity(TypedValue.INFO_SEVERITY) - .build()); - - formulaReports.add(ReportNode.newRootReportNode() - .withMessageTemplate("numberOfValidEquipment" + formulaReports.size(), " Number of equipment modified : ${" + KEY_NB_CHANGED + "}") - .withUntypedValue(KEY_NB_CHANGED, filterEquipments.getIdentifiableAttributes().size() - notEditableEquipments.size()) - .withSeverity(TypedValue.INFO_SEVERITY) - .build()); - - if (!CollectionUtils.isEmpty(notEditableEquipments)) { - formulaReports.add(ReportNode.newRootReportNode() - .withMessageTemplate("NotEditedEquipmentsFilter_" + formulaReports.size(), " ${" + KEY_NB_UNCHANGED + "} equipment(s) were not modified") - .withUntypedValue(KEY_NB_UNCHANGED, notEditableEquipments.size()) - .withSeverity(TypedValue.WARN_SEVERITY) - .build()); - } - } - - formulaReports.add(ReportNode.newRootReportNode() - .withMessageTemplate("editedFieldFilter_" + formulaReports.size(), " Edited field :${" + KEY_FIELD_NAME + "}") - .withUntypedValue(KEY_FIELD_NAME, formulaInfos.getEditedField()) - .withSeverity(TypedValue.INFO_SEVERITY) - .build()); - - if (!CollectionUtils.isEmpty(filterEquipments.getNotFoundEquipments())) { - String equipmentIds = String.join(", ", filterEquipments.getNotFoundEquipments()); - formulaReports.add(ReportNode.newRootReportNode() - .withMessageTemplate("filterEquipmentsNotFound_" + formulaReports.size(), " Equipment not found : ${" + KEY_VALUE + "}") - .withUntypedValue(KEY_VALUE, equipmentIds) - .withSeverity(TypedValue.WARN_SEVERITY) - .build()); - } - } - - private boolean isEquipmentEditable(Identifiable identifiable, - FormulaInfos formulaInfos, - List equipmentsReport) { - if (formulaInfos.getEditedField() == null) { - return false; - } - - if (identifiable.getType() == IdentifiableType.TWO_WINDINGS_TRANSFORMER) { - TwoWindingsTransformerField editedField = TwoWindingsTransformerField.valueOf(formulaInfos.getEditedField()); - TwoWindingsTransformer twoWindingsTransformer = (TwoWindingsTransformer) identifiable; - return switch (editedField) { - case TARGET_V, RATIO_LOW_TAP_POSITION, RATIO_TAP_POSITION, RATIO_TARGET_DEADBAND -> { - boolean isEditable = twoWindingsTransformer.getRatioTapChanger() != null; - if (!isEditable) { - equipmentsReport.add(ReportNode.newRootReportNode() - .withMessageTemplate(EQUIPMENT_MODIFIED_REPORT_ERROR + equipmentsReport.size(), " Cannot modify field ${" + KEY_FIELD_NAME + "} of equipment ${" + KEY_EQPT_NAME + "} : Ratio tab changer is null") - .withUntypedValue(KEY_FIELD_NAME, editedField.name()) - .withUntypedValue(KEY_EQPT_NAME, identifiable.getId()) - .withSeverity(TypedValue.TRACE_SEVERITY) - .build()); - } - yield isEditable; - } - case REGULATION_VALUE, PHASE_LOW_TAP_POSITION, PHASE_TAP_POSITION, PHASE_TARGET_DEADBAND -> { - boolean isEditable = twoWindingsTransformer.getPhaseTapChanger() != null; - if (!isEditable) { - equipmentsReport.add(ReportNode.newRootReportNode() - .withMessageTemplate(EQUIPMENT_MODIFIED_REPORT_ERROR + equipmentsReport.size(), " Cannot modify field ${" + KEY_FIELD_NAME + "} of equipment ${" + KEY_EQPT_NAME + "} : Phase tab changer is null") - .withUntypedValue(KEY_FIELD_NAME, editedField.name()) - .withUntypedValue(KEY_EQPT_NAME, identifiable.getId()) - .withSeverity(TypedValue.TRACE_SEVERITY) - .build()); - } - yield isEditable; - } - default -> true; - }; - } - return true; - } - - private void applyFormula(Identifiable identifiable, - FormulaInfos formulaInfos, - List reports, - List notEditableEquipments) { - Double value1 = formulaInfos.getFieldOrValue1().getRefOrValue(identifiable); - Double value2 = formulaInfos.getFieldOrValue2().getRefOrValue(identifiable); - if (value1 == null || Double.isNaN(value1) || value2 == null || Double.isNaN(value2)) { - equipmentNotModifiedCount += 1; - notEditableEquipments.add(identifiable.getId()); - reports.add(ReportNode.newRootReportNode() - .withMessageTemplate(EQUIPMENT_MODIFIED_REPORT_ERROR + reports.size(), " Cannot modify equipment ${" + KEY_EQPT_NAME + "} : At least one of the value or referenced field is null") - .withUntypedValue(KEY_EQPT_NAME, identifiable.getId()) - .withSeverity(TypedValue.TRACE_SEVERITY) - .build()); - } else if (value2 == 0 && formulaInfos.getOperator() == Operator.DIVISION) { - equipmentNotModifiedCount += 1; - notEditableEquipments.add(identifiable.getId()); - } else { - try { - final Double newValue = applyOperation(formulaInfos.getOperator(), value1, value2); - switch (identifiable.getType()) { - case GENERATOR -> GeneratorField.setNewValue((Generator) identifiable, formulaInfos.getEditedField(), newValue.doubleValue()); - case BATTERY -> BatteryField.setNewValue((Battery) identifiable, formulaInfos.getEditedField(), newValue); - case SHUNT_COMPENSATOR -> ShuntCompensatorField.setNewValue((ShuntCompensator) identifiable, formulaInfos.getEditedField(), newValue); - case VOLTAGE_LEVEL -> VoltageLevelField.setNewValue((VoltageLevel) identifiable, formulaInfos.getEditedField(), newValue); - case LOAD -> LoadField.setNewValue((Load) identifiable, formulaInfos.getEditedField(), newValue); - case TWO_WINDINGS_TRANSFORMER -> TwoWindingsTransformerField.setNewValue((TwoWindingsTransformer) identifiable, formulaInfos.getEditedField(), newValue); - default -> throw new NetworkModificationException(NetworkModificationException.Type.BY_FORMULA_MODIFICATION_ERROR, "Unsupported equipment"); - } - reports.add(ReportNode.newRootReportNode() - .withMessageTemplate("EquipmentModifiedReport_" + reports.size(), " ${" + KEY_EQPT_TYPE + "} id : ${" + KEY_EQPT_NAME + "}, new value of ${" + KEY_FIELD_NAME + "} : ${" + KEY_VALUE + "}") - .withUntypedValue(KEY_EQPT_TYPE, modificationInfos.getIdentifiableType().name()) - .withUntypedValue(KEY_EQPT_NAME, identifiable.getId()) - .withUntypedValue(KEY_FIELD_NAME, formulaInfos.getEditedField()) - .withUntypedValue(KEY_VALUE, newValue) - .withSeverity(TypedValue.TRACE_SEVERITY) - .build()); - } catch (Exception e) { - notEditableEquipments.add(identifiable.getId()); - equipmentNotModifiedCount += 1; - reports.add(ReportNode.newRootReportNode() - .withMessageTemplate("EquipmentModifiedReportExceptionf_" + reports.size(), " Cannot modify equipment ${" + KEY_EQPT_NAME + "} : ${" + KEY_VALUE + "}") - .withUntypedValue(KEY_EQPT_NAME, identifiable.getId()) - .withUntypedValue(KEY_VALUE, e.getMessage()) - .withSeverity(TypedValue.TRACE_SEVERITY) - .build()); - } - } - } - - private Double applyOperation(Operator operator, @NotNull Double value1, @NotNull Double value2) { - return switch (operator) { - case ADDITION -> value1 + value2; - case SUBTRACTION -> value1 - value2; - case MULTIPLICATION -> value1 * value2; - case DIVISION -> value1 / value2; - case PERCENTAGE -> value1 * (value2 / 100); - }; - } -} diff --git a/src/main/java/org/gridsuite/modification/server/modifications/byfilter/AbstractModificationByAssignment.java b/src/main/java/org/gridsuite/modification/server/modifications/byfilter/AbstractModificationByAssignment.java new file mode 100644 index 000000000..33fe17929 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/modifications/byfilter/AbstractModificationByAssignment.java @@ -0,0 +1,368 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.modifications.byfilter; + +import com.powsybl.commons.report.ReportNode; +import com.powsybl.commons.report.TypedValue; +import com.powsybl.iidm.network.Identifiable; +import com.powsybl.iidm.network.IdentifiableType; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.TwoWindingsTransformer; +import org.apache.commons.lang3.StringUtils; +import org.gridsuite.modification.server.NetworkModificationException; +import org.gridsuite.modification.server.dto.FilterEquipments; +import org.gridsuite.modification.server.dto.FilterInfos; +import org.gridsuite.modification.server.dto.ModificationInfos; +import org.gridsuite.modification.server.dto.byfilter.AbstractAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.equipmentfield.TwoWindingsTransformerField; +import org.gridsuite.modification.server.modifications.AbstractModification; +import org.gridsuite.modification.server.modifications.ModificationUtils; +import org.gridsuite.modification.server.modifications.NetworkModificationApplicator; +import org.gridsuite.modification.server.service.FilterService; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; + +import static org.gridsuite.modification.server.dto.byfilter.equipmentfield.FieldUtils.getFieldValue; +import static org.gridsuite.modification.server.dto.byfilter.equipmentfield.FieldUtils.setFieldValue; +import static org.gridsuite.modification.server.modifications.ModificationUtils.*; + +/** + * @author Thang PHAM + */ +public abstract class AbstractModificationByAssignment extends AbstractModification { + public static final String VALUE_KEY_FILTER_NAME = "filterName"; + public static final String VALUE_KEY_FIELD_NAME = "fieldName"; + public static final String VALUE_KEY_EQUIPMENT_NAME = "equipmentName"; + public static final String VALUE_KEY_EQUIPMENT_TYPE = "equipmentType"; + public static final String VALUE_KEY_EQUIPMENT_COUNT = "equipmentCount"; + public static final String VALUE_KEY_EQUIPMENT_IDS = "equipmentIds"; + public static final String VALUE_KEY_NB_CHANGED = "nbChanged"; + public static final String VALUE_KEY_NB_UNCHANGED = "nbUnchanged"; + public static final String VALUE_KEY_OLD_VALUE = "oldValue"; + public static final String VALUE_KEY_NEW_VALUE = "newValue"; + public static final String VALUE_KEY_MODIFICATION_TYPE_LABEL = "modificationTypeLabel"; + public static final String VALUE_KEY_FILTERS_EACH_ASSIGNMENT = "filtersEachAssignment"; + public static final String VALUE_KEY_ERROR_MESSAGE = "errorMessage"; + public static final String REPORT_KEY_RATIO_TAP_CHANGER_EQUIPMENT_MODIFIED_ERROR = "ratioTapChangerEquipmentModifiedError"; + public static final String REPORT_KEY_PHASE_TAP_CHANGER_EQUIPMENT_MODIFIED_ERROR = "phaseTapChangerEquipmentModifiedError"; + public static final String REPORT_KEY_EQUIPMENT_MODIFIED_ERROR = "equipmentModifiedError"; + public static final String REPORT_KEY_BY_FILTER_MODIFICATION_SOME = "byFilterModificationSome"; + public static final String REPORT_KEY_BY_FILTER_MODIFICATION_FAILED = "byFilterModificationFailed"; + public static final String REPORT_KEY_BY_FILTER_MODIFICATION_SUCCESS = "byFilterModificationSuccess"; + public static final String REPORT_KEY_NUMBER_OF_VALID_EQUIPMENT = "numberOfValidEquipment"; + public static final String REPORT_KEY_NOT_EDITED_EQUIPMENTS_FILTER = "notEditedEquipmentsFilter"; + public static final String REPORT_KEY_EDITED_FIELD_FILTER = "editedFieldFilter"; + public static final String REPORT_KEY_FILTER_EQUIPMENTS_NOT_FOUND = "filterEquipmentsNotFound"; + public static final String REPORT_KEY_EQUIPMENT_MODIFIED_REPORT = "equipmentModifiedReport"; + public static final String REPORT_KEY_EQUIPMENT_MODIFIED_REPORT_EXCEPTION = "equipmentModifiedReportException"; + public static final String REPORT_KEY_APPLIED_BY_FILTER_MODIFICATIONS = "appliedByFilterModifications"; + public static final String REPORT_KEY_APPLIED_ASSIGNMENT = "appliedAssignment"; + public static final String REPORT_KEY_BY_FILTER_MODIFICATION_ALL = "byFilterModificationAll"; + public static final String REPORT_KEY_BY_FILTER_MODIFICATION_NONE = "byFilterModificationNone"; + public static final String REPORT_KEY_BY_FILTER_MODIFICATION_NOT_FOUND = "byFilterModificationNotFound"; + + protected FilterService filterService; + protected int equipmentNotModifiedCount; + protected long equipmentCount; + protected long equipmentNotFoundCount; + + protected AbstractModificationByAssignment() { + equipmentNotModifiedCount = 0; + equipmentCount = 0; + equipmentNotFoundCount = 0; + } + + public abstract String getModificationTypeLabel(); + + private String getEditedFieldLabel(AbstractAssignmentInfos modificationByFilterInfos) { + return modificationByFilterInfos.getEditedFieldLabel(); + } + + public abstract ModificationInfos getModificationInfos(); + + public abstract IdentifiableType getEquipmentType(); + + public abstract NetworkModificationException.Type getExceptionType(); + + public abstract List getAssignmentInfosList(); + + protected abstract boolean preCheckValue(Identifiable equipment, + AbstractAssignmentInfos abstractAssignmentInfos, + List reports, List notEditableEquipments); + + protected abstract String getNewValue(Identifiable equipment, AbstractAssignmentInfos abstractAssignmentInfos); + + protected String getOldValue(Identifiable equipment, AbstractAssignmentInfos abstractAssignmentInfos) { + return getFieldValue(equipment, abstractAssignmentInfos.getEditedField()); + } + + protected String applyValue(Identifiable equipment, AbstractAssignmentInfos abstractAssignmentInfos) { + // get new value + String newValue = getNewValue(equipment, abstractAssignmentInfos); + + // set new value for the equipment + setFieldValue(equipment, abstractAssignmentInfos.getEditedField(), newValue); + return newValue; + } + + @Override + public void initApplicationContext(NetworkModificationApplicator modificationApplicator) { + filterService = modificationApplicator.getFilterService(); + } + + @Override + public void check(Network network) throws NetworkModificationException { + if (getModificationInfos() == null) { + throw new NetworkModificationException(getExceptionType(), "Missing required attributes to modify the equipment"); + } + + if (CollectionUtils.isEmpty(getAssignmentInfosList())) { + throw new NetworkModificationException(getExceptionType(), String.format("At least one %s is required", getModificationTypeLabel())); + } + + if (getAssignmentInfosList().stream().anyMatch(modificationByFilterInfos -> CollectionUtils.isEmpty(modificationByFilterInfos.getFilters()))) { + throw new NetworkModificationException(getExceptionType(), String.format("Every %s must have at least one filter", getModificationTypeLabel())); + } + } + + @Override + public void apply(Network network, ReportNode subReportNode) { + // collect all filters from all variations + Map filters = getFilters(); + + Map filterUuidEquipmentsMap = + ModificationUtils.getUuidFilterEquipmentsMap(filterService, network, subReportNode, filters, getModificationInfos().getErrorType()); + + if (filterUuidEquipmentsMap != null) { + ReportNode subReporter = subReportNode.newReportNode() + .withMessageTemplate(REPORT_KEY_APPLIED_BY_FILTER_MODIFICATIONS, "${" + VALUE_KEY_MODIFICATION_TYPE_LABEL + "}s on ${" + VALUE_KEY_EQUIPMENT_TYPE + "} type") + .withUntypedValue(VALUE_KEY_MODIFICATION_TYPE_LABEL, StringUtils.capitalize(getModificationTypeLabel())) + .withUntypedValue(VALUE_KEY_EQUIPMENT_TYPE, getEquipmentType().name()) + .add(); + // perform modifications + getAssignmentInfosList().forEach(abstractAssignmentInfos -> { + List reports = new ArrayList<>(); + ReportNode eachAssignmentReporter = subReporter.newReportNode() + .withMessageTemplate(REPORT_KEY_APPLIED_ASSIGNMENT, "${" + VALUE_KEY_MODIFICATION_TYPE_LABEL + "} on filters : ${" + VALUE_KEY_FILTERS_EACH_ASSIGNMENT + "}") + .withUntypedValue(VALUE_KEY_MODIFICATION_TYPE_LABEL, StringUtils.capitalize(getModificationTypeLabel())) + .withUntypedValue(VALUE_KEY_FILTERS_EACH_ASSIGNMENT, abstractAssignmentInfos.getFilters().stream().map(FilterInfos::getName) + .collect(Collectors.joining(", "))) + .add(); + abstractAssignmentInfos.getFilters().forEach(filterInfos -> applyOnFilterEquipments(network, filterUuidEquipmentsMap, reports, abstractAssignmentInfos, filterInfos)); + reports.forEach(report -> insertReportNode(eachAssignmentReporter, report)); + }); + // reporting + if (equipmentNotModifiedCount == 0 && equipmentNotFoundCount == 0) { + subReportNode.newReportNode() + .withMessageTemplate(REPORT_KEY_BY_FILTER_MODIFICATION_ALL, + "All equipments have been modified : ${" + VALUE_KEY_EQUIPMENT_COUNT + "} equipment(s)") + .withUntypedValue(VALUE_KEY_EQUIPMENT_COUNT, equipmentCount) + .withSeverity(TypedValue.INFO_SEVERITY) + .add(); + + } else { + if (equipmentNotModifiedCount == equipmentCount) { + createReport(subReportNode, REPORT_KEY_BY_FILTER_MODIFICATION_NONE, + "No equipment have been modified", + Map.of(), TypedValue.ERROR_SEVERITY); + } else { + subReportNode.newReportNode() + .withMessageTemplate(REPORT_KEY_BY_FILTER_MODIFICATION_SOME, + "Some of the equipment have been modified : ${" + VALUE_KEY_NB_CHANGED + "} equipment(s) modified and ${" + VALUE_KEY_NB_UNCHANGED + "} equipment(s) not modified") + .withUntypedValue(VALUE_KEY_NB_CHANGED, equipmentCount - equipmentNotModifiedCount) + .withUntypedValue(VALUE_KEY_NB_UNCHANGED, equipmentNotModifiedCount + equipmentNotFoundCount) + .withSeverity(TypedValue.WARN_SEVERITY) + .add(); + } + } + } + } + + protected boolean isEquipmentEditable(Identifiable equipment, + AbstractAssignmentInfos abstractAssignmentInfos, + List equipmentsReport) { + if (abstractAssignmentInfos.getEditedField() == null) { + return false; + } + + if (equipment.getType() == IdentifiableType.TWO_WINDINGS_TRANSFORMER) { + TwoWindingsTransformerField editedField = TwoWindingsTransformerField.valueOf(abstractAssignmentInfos.getEditedField()); + TwoWindingsTransformer twoWindingsTransformer = (TwoWindingsTransformer) equipment; + return switch (editedField) { + case TARGET_V, RATIO_LOW_TAP_POSITION, RATIO_TAP_POSITION, RATIO_TARGET_DEADBAND -> { + boolean isEditable = twoWindingsTransformer.getRatioTapChanger() != null; + if (!isEditable) { + equipmentsReport.add(ReportNode.newRootReportNode() + .withMessageTemplate(REPORT_KEY_RATIO_TAP_CHANGER_EQUIPMENT_MODIFIED_ERROR + equipmentsReport.size(), + " Cannot modify field ${" + VALUE_KEY_FIELD_NAME + "} of equipment ${" + VALUE_KEY_EQUIPMENT_NAME + "} : Ratio tab changer is null") + .withUntypedValue(VALUE_KEY_FIELD_NAME, editedField.name()) + .withUntypedValue(VALUE_KEY_EQUIPMENT_NAME, equipment.getId()) + .withSeverity(TypedValue.TRACE_SEVERITY) + .build()); + } + yield isEditable; + } + case REGULATION_VALUE, PHASE_LOW_TAP_POSITION, PHASE_TAP_POSITION, PHASE_TARGET_DEADBAND -> { + boolean isEditable = twoWindingsTransformer.getPhaseTapChanger() != null; + if (!isEditable) { + equipmentsReport.add(ReportNode.newRootReportNode() + .withMessageTemplate(REPORT_KEY_PHASE_TAP_CHANGER_EQUIPMENT_MODIFIED_ERROR + equipmentsReport.size(), + " Cannot modify field ${" + VALUE_KEY_FIELD_NAME + "} of equipment ${" + VALUE_KEY_EQUIPMENT_NAME + "} : Phase tab changer is null") + .withUntypedValue(VALUE_KEY_FIELD_NAME, editedField.name()) + .withUntypedValue(VALUE_KEY_EQUIPMENT_NAME, equipment.getId()) + .withSeverity(TypedValue.TRACE_SEVERITY) + .build()); + } + yield isEditable; + } + default -> true; + }; + } + return true; + } + + private void createAssignmentReports(List reports, AbstractAssignmentInfos abstractAssignmentInfos, + FilterInfos filterInfos, FilterEquipments filterEquipments, List notEditableEquipments) { + if (notEditableEquipments.size() == filterEquipments.getIdentifiableAttributes().size()) { + reports.add(ReportNode.newRootReportNode() + .withMessageTemplate(REPORT_KEY_BY_FILTER_MODIFICATION_FAILED, + "No equipment(s) have been modified on filter ${" + VALUE_KEY_FILTER_NAME + "}") + .withUntypedValue(VALUE_KEY_FILTER_NAME, filterInfos.getName()) + .withSeverity(TypedValue.WARN_SEVERITY) + .build()); + } else { + reports.add(ReportNode.newRootReportNode() + .withMessageTemplate(REPORT_KEY_BY_FILTER_MODIFICATION_SUCCESS, + "Successful application of ${" + VALUE_KEY_MODIFICATION_TYPE_LABEL + "} on filter ${" + VALUE_KEY_FILTER_NAME + "}") + .withUntypedValue(VALUE_KEY_MODIFICATION_TYPE_LABEL, getModificationTypeLabel()) + .withUntypedValue(VALUE_KEY_FILTER_NAME, filterInfos.getName()) + .withSeverity(TypedValue.INFO_SEVERITY) + .build()); + + reports.add(ReportNode.newRootReportNode() + .withMessageTemplate(REPORT_KEY_NUMBER_OF_VALID_EQUIPMENT, " Number of equipment modified : ${" + VALUE_KEY_NB_CHANGED + "}") + .withUntypedValue(VALUE_KEY_NB_CHANGED, filterEquipments.getIdentifiableAttributes().size() - notEditableEquipments.size()) + .withSeverity(TypedValue.INFO_SEVERITY) + .build()); + + if (!CollectionUtils.isEmpty(notEditableEquipments)) { + reports.add(ReportNode.newRootReportNode() + .withMessageTemplate(REPORT_KEY_NOT_EDITED_EQUIPMENTS_FILTER, + " ${" + VALUE_KEY_NB_UNCHANGED + "} equipment(s) were not modified") + .withUntypedValue(VALUE_KEY_NB_UNCHANGED, notEditableEquipments.size()) + .withSeverity(TypedValue.WARN_SEVERITY) + .build()); + } + } + + reports.add(ReportNode.newRootReportNode() + .withMessageTemplate(REPORT_KEY_EDITED_FIELD_FILTER, " Edited field : ${" + VALUE_KEY_FIELD_NAME + "}") + .withUntypedValue(VALUE_KEY_FIELD_NAME, getEditedFieldLabel(abstractAssignmentInfos)) + .withSeverity(TypedValue.INFO_SEVERITY) + .build()); + + if (!CollectionUtils.isEmpty(filterEquipments.getNotFoundEquipments())) { + String equipmentIds = String.join(", ", filterEquipments.getNotFoundEquipments()); + reports.add(ReportNode.newRootReportNode() + .withMessageTemplate(REPORT_KEY_FILTER_EQUIPMENTS_NOT_FOUND, " Equipment not found : ${" + VALUE_KEY_EQUIPMENT_IDS + "}") + .withUntypedValue(VALUE_KEY_EQUIPMENT_IDS, equipmentIds) + .withSeverity(TypedValue.WARN_SEVERITY) + .build()); + } + } + + private void applyModification(Identifiable equipment, + AbstractAssignmentInfos abstractAssignmentInfos, + List reports, + List notEditableEquipments) { + + // check pre-conditions + if (!preCheckValue(equipment, abstractAssignmentInfos, reports, notEditableEquipments)) { + return; + } + + // perform to apply new value + try { + final String oldValue = getOldValue(equipment, abstractAssignmentInfos); + final String newValue = applyValue(equipment, abstractAssignmentInfos); + reports.add(ReportNode.newRootReportNode() + .withMessageTemplate(REPORT_KEY_EQUIPMENT_MODIFIED_REPORT, + " ${" + VALUE_KEY_EQUIPMENT_TYPE + "} id : ${" + VALUE_KEY_EQUIPMENT_NAME + + "}, ${" + VALUE_KEY_FIELD_NAME + "} : ${" + VALUE_KEY_OLD_VALUE + "} → ${" + VALUE_KEY_NEW_VALUE + "}") + .withUntypedValue(VALUE_KEY_EQUIPMENT_TYPE, equipment.getType().name()) + .withUntypedValue(VALUE_KEY_EQUIPMENT_NAME, equipment.getId()) + .withUntypedValue(VALUE_KEY_FIELD_NAME, getEditedFieldLabel(abstractAssignmentInfos)) + .withUntypedValue(VALUE_KEY_OLD_VALUE, oldValue == null ? NO_VALUE : oldValue) + .withUntypedValue(VALUE_KEY_NEW_VALUE, newValue) + .withSeverity(TypedValue.TRACE_SEVERITY) + .build()); + } catch (Exception e) { + notEditableEquipments.add(equipment.getId()); + equipmentNotModifiedCount += 1; + reports.add(ReportNode.newRootReportNode() + .withMessageTemplate(REPORT_KEY_EQUIPMENT_MODIFIED_REPORT_EXCEPTION, + " Cannot modify equipment ${" + VALUE_KEY_EQUIPMENT_NAME + "} : ${" + VALUE_KEY_ERROR_MESSAGE + "}") + .withUntypedValue(VALUE_KEY_EQUIPMENT_NAME, equipment.getId()) + .withUntypedValue(VALUE_KEY_ERROR_MESSAGE, e.getMessage()) + .withSeverity(TypedValue.WARN_SEVERITY) + .build()); + } + } + + private Map getFilters() { + return getAssignmentInfosList().stream() + .flatMap(v -> v.getFilters().stream()) + .filter(distinctByKey(FilterInfos::getId)) + .collect(Collectors.toMap(FilterInfos::getId, FilterInfos::getName)); + } + + private void applyOnFilterEquipments(Network network, + Map filterUuidEquipmentsMap, + List reports, + AbstractAssignmentInfos abstractAssignmentInfos, + FilterInfos filterInfos) { + FilterEquipments filterEquipments = filterUuidEquipmentsMap.get(filterInfos.getId()); + + if (CollectionUtils.isEmpty(filterEquipments.getIdentifiableAttributes())) { + reports.add(ReportNode.newRootReportNode() + .withMessageTemplate(REPORT_KEY_BY_FILTER_MODIFICATION_NOT_FOUND, "No equipments were found for filter ${" + VALUE_KEY_FILTER_NAME + "}") + .withUntypedValue(VALUE_KEY_FILTER_NAME, filterInfos.getName()) + .withSeverity(TypedValue.WARN_SEVERITY) + .build()); + } else { + equipmentCount += filterEquipments.getIdentifiableAttributes().size(); + if (!CollectionUtils.isEmpty(filterEquipments.getNotFoundEquipments())) { + equipmentNotFoundCount += filterEquipments.getNotFoundEquipments().size(); + } + List notEditableEquipments = new ArrayList<>(); + List equipmentsReport = new ArrayList<>(); + filterEquipments.getIdentifiableAttributes() + .stream() + .map(attributes -> network.getIdentifiable(attributes.getId())) + .filter(equipment -> { + boolean isEditableEquipment = isEquipmentEditable(equipment, abstractAssignmentInfos, equipmentsReport); + if (!isEditableEquipment) { + notEditableEquipments.add(equipment.getId()); + equipmentNotModifiedCount += 1; + } + return isEditableEquipment; + }) + .forEach(equipment -> applyModification(equipment, abstractAssignmentInfos, equipmentsReport, notEditableEquipments)); + + createAssignmentReports(reports, abstractAssignmentInfos, filterInfos, filterEquipments, notEditableEquipments); + + reports.addAll(equipmentsReport); + } + } + +} diff --git a/src/main/java/org/gridsuite/modification/server/modifications/byfilter/ByFormulaModification.java b/src/main/java/org/gridsuite/modification/server/modifications/byfilter/ByFormulaModification.java new file mode 100644 index 000000000..d8071d983 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/modifications/byfilter/ByFormulaModification.java @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.modifications.byfilter; + +import com.powsybl.commons.report.ReportNode; +import com.powsybl.commons.report.TypedValue; +import com.powsybl.iidm.network.Identifiable; +import com.powsybl.iidm.network.IdentifiableType; +import org.gridsuite.modification.server.NetworkModificationException; +import org.gridsuite.modification.server.dto.ByFormulaModificationInfos; +import org.gridsuite.modification.server.dto.ModificationInfos; +import org.gridsuite.modification.server.dto.byfilter.AbstractAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.formula.FormulaInfos; +import org.gridsuite.modification.server.dto.byfilter.formula.Operator; + +import javax.annotation.Nonnull; +import java.util.Collections; +import java.util.List; + +import static org.gridsuite.modification.server.NetworkModificationException.Type.BY_FORMULA_MODIFICATION_ERROR; + +/** + * @author Thang PHAM + */ +public class ByFormulaModification extends AbstractModificationByAssignment { + private final ByFormulaModificationInfos modificationInfos; + + public ByFormulaModification(ByFormulaModificationInfos modificationInfos) { + super(); + this.modificationInfos = modificationInfos; + } + + @Override + public String getModificationTypeLabel() { + return "formula"; + } + + @Override + public ModificationInfos getModificationInfos() { + return modificationInfos; + } + + @Override + public IdentifiableType getEquipmentType() { + return modificationInfos.getIdentifiableType(); + } + + @Override + public List getAssignmentInfosList() { + return Collections.unmodifiableList(modificationInfos.getFormulaInfosList()); + } + + @Override + public NetworkModificationException.Type getExceptionType() { + return BY_FORMULA_MODIFICATION_ERROR; + } + + @Override + protected boolean preCheckValue(Identifiable equipment, AbstractAssignmentInfos abstractAssignmentInfos, List reports, List notEditableEquipments) { + FormulaInfos formulaInfos = (FormulaInfos) abstractAssignmentInfos; + Double value1 = formulaInfos.getFieldOrValue1().getRefOrValue(equipment); + Double value2 = formulaInfos.getFieldOrValue2().getRefOrValue(equipment); + if (value1 == null || Double.isNaN(value1) || value2 == null || Double.isNaN(value2)) { + equipmentNotModifiedCount += 1; + notEditableEquipments.add(equipment.getId()); + reports.add(ReportNode.newRootReportNode() + .withMessageTemplate(REPORT_KEY_EQUIPMENT_MODIFIED_ERROR, " Cannot modify equipment ${" + + VALUE_KEY_EQUIPMENT_NAME + "} : At least one of the value or referenced field is null") + .withUntypedValue(VALUE_KEY_EQUIPMENT_NAME, equipment.getId()) + .withSeverity(TypedValue.TRACE_SEVERITY) + .build()); + return false; + } + + if (value2 == 0 && formulaInfos.getOperator() == Operator.DIVISION) { + equipmentNotModifiedCount += 1; + notEditableEquipments.add(equipment.getId()); + reports.add(ReportNode.newRootReportNode() + .withMessageTemplate(REPORT_KEY_EQUIPMENT_MODIFIED_ERROR, " Cannot modify equipment ${" + + VALUE_KEY_EQUIPMENT_NAME + "} : The value or referenced field of the second operand in the division operator is zero") + .withUntypedValue(VALUE_KEY_EQUIPMENT_NAME, equipment.getId()) + .withSeverity(TypedValue.TRACE_SEVERITY) + .build()); + return false; + } + return true; + } + + @Override + protected String getNewValue(Identifiable equipment, AbstractAssignmentInfos abstractAssignmentInfos) { + FormulaInfos formulaInfos = (FormulaInfos) abstractAssignmentInfos; + Double value1 = formulaInfos.getFieldOrValue1().getRefOrValue(equipment); + Double value2 = formulaInfos.getFieldOrValue2().getRefOrValue(equipment); + return applyOperation(formulaInfos.getOperator(), value1, value2).toString(); + } + + private Double applyOperation(Operator operator, @Nonnull Double value1, @Nonnull Double value2) { + return switch (operator) { + case ADDITION -> value1 + value2; + case SUBTRACTION -> value1 - value2; + case MULTIPLICATION -> value1 * value2; + case DIVISION -> value1 / value2; + case PERCENTAGE -> value1 * (value2 / 100); + }; + } +} diff --git a/src/main/java/org/gridsuite/modification/server/modifications/byfilter/ModificationByAssignment.java b/src/main/java/org/gridsuite/modification/server/modifications/byfilter/ModificationByAssignment.java new file mode 100644 index 000000000..421e6656f --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/modifications/byfilter/ModificationByAssignment.java @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.modifications.byfilter; + +import com.powsybl.commons.report.ReportNode; +import com.powsybl.iidm.network.Identifiable; +import com.powsybl.iidm.network.IdentifiableType; +import org.gridsuite.modification.server.NetworkModificationException; +import org.gridsuite.modification.server.dto.ModificationByAssignmentInfos; +import org.gridsuite.modification.server.dto.ModificationInfos; +import org.gridsuite.modification.server.dto.byfilter.AbstractAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.DataType; +import org.gridsuite.modification.server.dto.byfilter.assignment.AssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.assignment.PropertyAssignmentInfos; + +import java.util.Collections; +import java.util.List; + +import static org.gridsuite.modification.server.NetworkModificationException.Type.MODIFICATION_BY_ASSIGNMENT_ERROR; + +/** + * @author Thang PHAM + */ +public class ModificationByAssignment extends AbstractModificationByAssignment { + private final ModificationByAssignmentInfos modificationInfos; + + public ModificationByAssignment(ModificationByAssignmentInfos modificationInfos) { + super(); + this.modificationInfos = modificationInfos; + } + + @Override + public String getModificationTypeLabel() { + return "assignment"; + } + + @Override + public ModificationInfos getModificationInfos() { + return modificationInfos; + } + + @Override + public IdentifiableType getEquipmentType() { + return modificationInfos.getEquipmentType(); + } + + @Override + public List getAssignmentInfosList() { + return Collections.unmodifiableList(modificationInfos.getAssignmentInfosList()); + } + + @Override + public NetworkModificationException.Type getExceptionType() { + return MODIFICATION_BY_ASSIGNMENT_ERROR; + } + + @Override + protected boolean isEquipmentEditable(Identifiable equipment, AbstractAssignmentInfos abstractAssignmentInfos, List equipmentsReport) { + AssignmentInfos assignmentInfos = (AssignmentInfos) abstractAssignmentInfos; + if (assignmentInfos.getDataType() == DataType.PROPERTY) { + return true; + } else { + return super.isEquipmentEditable(equipment, abstractAssignmentInfos, equipmentsReport); + } + } + + @Override + protected boolean preCheckValue(Identifiable equipment, AbstractAssignmentInfos abstractAssignmentInfos, List reports, List notEditableEquipments) { + return true; + } + + @Override + protected String getOldValue(Identifiable equipment, AbstractAssignmentInfos abstractAssignmentInfos) { + AssignmentInfos assignmentInfos = (AssignmentInfos) abstractAssignmentInfos; + if (assignmentInfos.getDataType() == DataType.PROPERTY) { + return equipment.getProperty(((PropertyAssignmentInfos) assignmentInfos).getPropertyName()); + } else { + return super.getOldValue(equipment, abstractAssignmentInfos); + } + } + + @Override + protected String getNewValue(Identifiable equipment, AbstractAssignmentInfos abstractAssignmentInfos) { + AssignmentInfos assignmentInfos = (AssignmentInfos) abstractAssignmentInfos; + if (assignmentInfos.getValue() == null) { + throw new NetworkModificationException(MODIFICATION_BY_ASSIGNMENT_ERROR, "Missing a value in the assignment"); + } + return assignmentInfos.getValue().toString(); + } + + @Override + protected String applyValue(Identifiable equipment, AbstractAssignmentInfos abstractAssignmentInfos) { + AssignmentInfos assignmentInfos = (AssignmentInfos) abstractAssignmentInfos; + if (assignmentInfos.getDataType() == DataType.PROPERTY) { + String newValue = getNewValue(equipment, abstractAssignmentInfos); + equipment.setProperty(((PropertyAssignmentInfos) assignmentInfos).getPropertyName(), newValue); + return newValue; + } else { + return super.applyValue(equipment, abstractAssignmentInfos); + } + } +} diff --git a/src/main/resources/db/changelog/changesets/changelog_20240912T130742Z.xml b/src/main/resources/db/changelog/changesets/changelog_20240912T130742Z.xml new file mode 100644 index 000000000..d7e93035e --- /dev/null +++ b/src/main/resources/db/changelog/changesets/changelog_20240912T130742Z.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 32b8d57e2..1e8120d72 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -308,4 +308,7 @@ databaseChangeLog: relativeToChangelogFile: true - include: file: changesets/changelog_20240904T211456Z.xml - relativeToChangelogFile: true \ No newline at end of file + relativeToChangelogFile: true + - include: + file: changesets/changelog_20240912T130742Z.xml + relativeToChangelogFile: true diff --git a/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/AbstractModificationByAssignmentTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/AbstractModificationByAssignmentTest.java new file mode 100644 index 000000000..9bb0958e2 --- /dev/null +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/AbstractModificationByAssignmentTest.java @@ -0,0 +1,263 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.modifications.byfilter.assignment; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.matching.StringValuePattern; +import com.powsybl.iidm.network.IdentifiableType; +import com.powsybl.iidm.network.Network; +import org.gridsuite.filter.AbstractFilter; +import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter; +import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes; +import org.gridsuite.filter.utils.EquipmentType; +import org.gridsuite.modification.server.dto.FilterInfos; +import org.gridsuite.modification.server.dto.ModificationByAssignmentInfos; +import org.gridsuite.modification.server.dto.NetworkModificationResult; +import org.gridsuite.modification.server.dto.byfilter.DataType; +import org.gridsuite.modification.server.dto.byfilter.assignment.AssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.assignment.DoubleAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.assignment.PropertyAssignmentInfos; +import org.gridsuite.modification.server.impacts.AbstractBaseImpact; +import org.gridsuite.modification.server.modifications.AbstractNetworkModificationTest; +import org.gridsuite.modification.server.service.FilterService; +import org.gridsuite.modification.server.utils.NetworkCreation; +import org.junit.Before; +import org.junit.Test; +import org.junit.jupiter.api.Tag; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MvcResult; + +import java.util.*; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.gridsuite.modification.server.Impacts.TestImpactUtils.createCollectionElementImpact; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author Thang PHAM + */ +@Tag("IntegrationTest") +public abstract class AbstractModificationByAssignmentTest extends AbstractNetworkModificationTest { + protected static final UUID FILTER_ID_1 = UUID.randomUUID(); + protected static final UUID FILTER_ID_2 = UUID.randomUUID(); + protected static final UUID FILTER_ID_3 = UUID.randomUUID(); + protected static final UUID FILTER_ID_4 = UUID.randomUUID(); + protected static final UUID FILTER_ID_5 = UUID.randomUUID(); + protected static final UUID FILTER_ID_6 = UUID.randomUUID(); + protected static final UUID FILTER_WITH_ALL_WRONG_IDS = UUID.randomUUID(); + protected static final UUID FILTER_WITH_ONE_WRONG_ID = UUID.randomUUID(); + protected final FilterInfos filter1 = new FilterInfos(FILTER_ID_1, "filter1"); + protected final FilterInfos filter2 = new FilterInfos(FILTER_ID_2, "filter2"); + protected final FilterInfos filter3 = new FilterInfos(FILTER_ID_3, "filter3"); + protected final FilterInfos filter4 = new FilterInfos(FILTER_ID_4, "filter4"); + protected final FilterInfos filter5 = new FilterInfos(FILTER_ID_5, "filter5"); + protected final FilterInfos filter6 = new FilterInfos(FILTER_ID_6, "filter6"); + protected final FilterInfos filterWithOneWrongId = new FilterInfos(FILTER_WITH_ONE_WRONG_ID, "filterWithOneWrongId"); + + public static final String PATH = "/v1/filters/metadata"; + + @Override + protected void assertResultImpacts(List impacts) { + assertThat(impacts).containsExactly(createCollectionElementImpact(getIdentifiableType())); + } + + @Before + public void specificSetUp() { + FilterService.setFilterServerBaseUri(wireMockServer.baseUrl()); + + getNetwork().getVariantManager().setWorkingVariant("variant_1"); + createEquipments(); + } + + @Test + public void testByModificationError() throws Exception { + //Test with modification = null + mockMvc.perform(post(getNetworkModificationUri()).content(mapper.writeValueAsString(null)).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()); + + // Test with empty list of assignment + checkCreationApplicationStatus(List.of(), NetworkModificationResult.ApplicationStatus.WITH_ERRORS); + + // Test with empty list of filters in assignment + List> assignmentsWithNoFilters = getAssignmentInfos().stream().peek(assignmentInfos -> assignmentInfos.setFilters(List.of())).toList(); + checkCreationApplicationStatus(assignmentsWithNoFilters, NetworkModificationResult.ApplicationStatus.WITH_ERRORS); + + // Test with editedField = null + AssignmentInfos assignmentWithNoEditedField = DoubleAssignmentInfos.builder() + .value(50.) + .filters(List.of()) + .build(); + checkCreationApplicationStatus(List.of(assignmentWithNoEditedField), NetworkModificationResult.ApplicationStatus.WITH_ERRORS); + } + + protected void checkCreateWithWarning(List> assignments, List existingEquipmentList) throws Exception { + AbstractFilter filter = getFilterEquipments(FILTER_WITH_ONE_WRONG_ID, existingEquipmentList); + + UUID stubId = wireMockServer.stubFor(WireMock.get(WireMock.urlMatching("/v1/filters/metadata\\?ids=" + FILTER_WITH_ONE_WRONG_ID)) + .willReturn(WireMock.ok() + .withBody(mapper.writeValueAsString(List.of(filter))) + .withHeader("Content-Type", "application/json"))).getId(); + + checkCreationApplicationStatus(assignments, NetworkModificationResult.ApplicationStatus.WITH_WARNINGS); + + wireMockUtils.verifyGetRequest(stubId, PATH, handleQueryParams(List.of(FILTER_WITH_ONE_WRONG_ID)), false); + } + + protected void checkCreateWithError(List> assignments, List filterEquipments) throws Exception { + String filterIds = filterEquipments.stream() + .map(AbstractFilter::getId) + .map(UUID::toString) + .collect(Collectors.joining(",")); + + UUID stubId = wireMockServer.stubFor(WireMock.get(WireMock.urlMatching("/v1/filters/metadata\\?ids=" + filterIds)) + .willReturn(WireMock.ok() + .withBody(mapper.writeValueAsString(filterEquipments)) + .withHeader("Content-Type", "application/json"))).getId(); + + checkCreationApplicationStatus(assignments, NetworkModificationResult.ApplicationStatus.WITH_ERRORS); + + wireMockUtils.verifyGetRequest(stubId, + PATH, + handleQueryParams(filterEquipments.stream().map(AbstractFilter::getId).toList()), + false); + } + + @Test + public void testModificationWithAllWrongEquipmentIds() throws Exception { + AbstractFilter filter = getFilterEquipments(FILTER_WITH_ALL_WRONG_IDS, List.of()); + + List> assignmentsWithWrongFilter = getAssignmentInfos().stream() + .peek(assignmentInfos -> assignmentInfos.setFilters(List.of(new FilterInfos(FILTER_WITH_ALL_WRONG_IDS, "filterWithWrongId")))) + .toList(); + + UUID stubId = wireMockServer.stubFor(WireMock.get(WireMock.urlMatching("/v1/filters/metadata\\?ids=" + FILTER_WITH_ALL_WRONG_IDS)) + .willReturn(WireMock.ok() + .withBody(mapper.writeValueAsString(List.of(filter))) + .withHeader("Content-Type", "application/json"))).getId(); + + checkCreationApplicationStatus(assignmentsWithWrongFilter, NetworkModificationResult.ApplicationStatus.WITH_ERRORS); + + wireMockUtils.verifyGetRequest(stubId, PATH, handleQueryParams(List.of(FILTER_WITH_ALL_WRONG_IDS)), false); + } + + @Test + @Override + public void testCreate() throws Exception { + List filters = getTestFilters(); + UUID stubId = wireMockServer.stubFor(WireMock.get(WireMock.urlMatching(getPath(true) + ".{2,}")) + .willReturn(WireMock.ok() + .withBody(mapper.writeValueAsString(filters)) + .withHeader("Content-Type", "application/json"))).getId(); + + super.testCreate(); + + wireMockUtils.verifyGetRequest(stubId, PATH, handleQueryParams(filters.stream().map(AbstractFilter::getId).toList()), false); + } + + @Test + @Override + public void testCopy() throws Exception { + List filters = getTestFilters(); + UUID stubId = wireMockServer.stubFor(WireMock.get(WireMock.urlMatching(getPath(true) + ".{2,}")) + .willReturn(WireMock.ok() + .withBody(mapper.writeValueAsString(filters)) + .withHeader("Content-Type", "application/json"))).getId(); + + super.testCopy(); + + wireMockUtils.verifyGetRequest(stubId, PATH, handleQueryParams(filters.stream().map(AbstractFilter::getId).toList()), false); + } + + protected void checkCreationApplicationStatus(List> assignmentInfos, + NetworkModificationResult.ApplicationStatus applicationStatus) throws Exception { + ModificationByAssignmentInfos modificationByAssignmentInfos = ModificationByAssignmentInfos.builder() + .equipmentType(getIdentifiableType()) + .assignmentInfosList(assignmentInfos) + .build(); + String modificationToCreateJson = mapper.writeValueAsString(modificationByAssignmentInfos); + + MvcResult mvcResult = mockMvc.perform(post(getNetworkModificationUri()).content(modificationToCreateJson).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andReturn(); + + Optional networkModificationResult = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { }); + assertTrue(networkModificationResult.isPresent()); + assertEquals(applicationStatus, networkModificationResult.get().getApplicationStatus()); + } + + @Override + protected Network createNetwork(UUID networkUuid) { + return NetworkCreation.create(networkUuid, true); + } + + @Override + protected ModificationByAssignmentInfos buildModification() { + return ModificationByAssignmentInfos.builder() + .equipmentType(getIdentifiableType()) + .assignmentInfosList(getAssignmentInfos()) + .stashed(false) + .build(); + } + + @Override + protected ModificationByAssignmentInfos buildModificationUpdate() { + return ModificationByAssignmentInfos.builder() + .equipmentType(getIdentifiableType()) + .assignmentInfosList(getUpdatedAssignmentInfos()) + .stashed(false) + .build(); + } + + protected IdentifierListFilterEquipmentAttributes getIdentifiableAttributes(String id, Double distributionKey) { + return new IdentifierListFilterEquipmentAttributes(id, distributionKey); + } + + protected AbstractFilter getFilterEquipments(UUID filterID, List identifiableAttributes) { + return IdentifierListFilter.builder().id(filterID).modificationDate(new Date()).equipmentType(getEquipmentType()) + .filterEquipmentsAttributes(identifiableAttributes) + .build(); + } + + Map handleQueryParams(List filterIds) { + return Map.of("ids", WireMock.matching(filterIds.stream().map(uuid -> ".+").collect(Collectors.joining(",")))); + } + + String getPath(boolean isRegexPath) { + if (isRegexPath) { + return "/v1/filters/metadata\\?ids="; + } + return "/v1/filters/metadata?ids="; + } + + protected abstract void createEquipments(); + + protected abstract List getTestFilters(); + + protected List> getAssignmentInfos() { + PropertyAssignmentInfos spyAssignmentInfos = spy(PropertyAssignmentInfos.builder() + .editedField(DataType.PROPERTY.name()) + .propertyName("propertyName") + .value("propertyValue") + .filters(List.of(filter1)) + .build()); + doReturn(DataType.PROPERTY).when(spyAssignmentInfos).getDataType(); + return new ArrayList<>(List.of(spyAssignmentInfos)); + } + + protected abstract List> getUpdatedAssignmentInfos(); + + protected abstract IdentifiableType getIdentifiableType(); + + protected abstract EquipmentType getEquipmentType(); +} diff --git a/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/BatteryModificationByAssignmentTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/BatteryModificationByAssignmentTest.java new file mode 100644 index 000000000..ed88c74f2 --- /dev/null +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/BatteryModificationByAssignmentTest.java @@ -0,0 +1,214 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.modifications.byfilter.assignment; + +import com.powsybl.iidm.network.IdentifiableType; +import com.powsybl.iidm.network.extensions.ActivePowerControl; +import com.powsybl.iidm.network.extensions.ActivePowerControlAdder; +import org.gridsuite.filter.AbstractFilter; +import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter; +import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes; +import org.gridsuite.filter.utils.EquipmentType; +import org.gridsuite.modification.server.dto.byfilter.assignment.AssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.assignment.DoubleAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.equipmentfield.BatteryField; +import org.junit.Test; + +import java.util.Date; +import java.util.List; + +import static org.gridsuite.modification.server.utils.NetworkUtil.createBattery; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Thang PHAM + */ +public class BatteryModificationByAssignmentTest extends AbstractModificationByAssignmentTest { + private static final String BATTERY_ID_1 = "v3Battery"; + private static final String BATTERY_ID_2 = "battery2"; + private static final String BATTERY_ID_3 = "battery3"; + private static final String BATTERY_ID_4 = "battery4"; + private static final String BATTERY_ID_5 = "battery5"; + private static final String BATTERY_ID_6 = "battery6"; + + @Test + public void testCreateWithWarning() throws Exception { + IdentifierListFilterEquipmentAttributes identifiableAttributes = getIdentifiableAttributes(BATTERY_ID_1, 1.0); + IdentifierListFilterEquipmentAttributes wrongIdAttributes = getIdentifiableAttributes("wrongId", 1.0); + + DoubleAssignmentInfos assignmentInfos = DoubleAssignmentInfos.builder() + .filters(List.of(filterWithOneWrongId)) + .editedField(BatteryField.ACTIVE_POWER_SET_POINT.name()) + .value(55.) + .build(); + + checkCreateWithWarning(List.of(assignmentInfos), List.of(identifiableAttributes, wrongIdAttributes)); + assertEquals(55, getNetwork().getBattery(BATTERY_ID_1).getTargetP(), 0); + } + + @Override + protected void createEquipments() { + getNetwork().getBattery(BATTERY_ID_1).setTargetP(100).setMaxP(500).setMinP(0).setTargetQ(80); + getNetwork().getBattery(BATTERY_ID_1).newExtension(ActivePowerControlAdder.class).withDroop(1).add(); + + createBattery(getNetwork().getVoltageLevel("v2"), BATTERY_ID_2, "v2Battery2", 20, 50, 2000, 200, 50); + createBattery(getNetwork().getVoltageLevel("v3"), BATTERY_ID_3, "v3Battery3", 30, 70, 400, 300, 50); + + createBattery(getNetwork().getVoltageLevel("v4"), BATTERY_ID_4, "v4Battery4", 40, 25, 350, 70, 50); + + createBattery(getNetwork().getVoltageLevel("v5"), BATTERY_ID_5, "v5Battery5", 50, 50, 600, 55, 140); + getNetwork().getBattery(BATTERY_ID_5).newExtension(ActivePowerControlAdder.class).withDroop(4).add(); + + createBattery(getNetwork().getVoltageLevel("v6"), BATTERY_ID_6, "v6Battery6", 60, 200, 700, 250, 210); + } + + @Override + protected List getTestFilters() { + IdentifierListFilter filter1 = IdentifierListFilter.builder().id(FILTER_ID_1).modificationDate(new Date()).equipmentType(EquipmentType.BATTERY) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(BATTERY_ID_1, 1.0), + new IdentifierListFilterEquipmentAttributes(BATTERY_ID_2, 2.0))) + .build(); + IdentifierListFilter filter2 = IdentifierListFilter.builder().id(FILTER_ID_2).modificationDate(new Date()).equipmentType(EquipmentType.BATTERY) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(BATTERY_ID_3, 2.0), + new IdentifierListFilterEquipmentAttributes(BATTERY_ID_4, 5.0))) + .build(); + IdentifierListFilter filter3 = IdentifierListFilter.builder().id(FILTER_ID_3).modificationDate(new Date()).equipmentType(EquipmentType.BATTERY) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(BATTERY_ID_5, 6.0), + new IdentifierListFilterEquipmentAttributes(BATTERY_ID_6, 7.0))) + .build(); + IdentifierListFilter filter4 = IdentifierListFilter.builder().id(FILTER_ID_4).modificationDate(new Date()).equipmentType(EquipmentType.BATTERY) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(BATTERY_ID_1, 1.0), + new IdentifierListFilterEquipmentAttributes(BATTERY_ID_5, 6.0))) + .build(); + IdentifierListFilter filter5 = IdentifierListFilter.builder().id(FILTER_ID_5).modificationDate(new Date()).equipmentType(EquipmentType.BATTERY) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(BATTERY_ID_2, 2.0), + new IdentifierListFilterEquipmentAttributes(BATTERY_ID_3, 3.0))) + .build(); + + return List.of(filter1, filter2, filter3, filter4, filter5); + } + + @Override + protected List> getAssignmentInfos() { + DoubleAssignmentInfos assignmentInfos1 = DoubleAssignmentInfos.builder() + .filters(List.of(filter1, filter2)) + .editedField(BatteryField.MAXIMUM_ACTIVE_POWER.name()) + .value(80.) + .build(); + + DoubleAssignmentInfos assignmentInfos2 = DoubleAssignmentInfos.builder() + .filters(List.of(filter3)) + .editedField(BatteryField.MINIMUM_ACTIVE_POWER.name()) + .value(30.) + .build(); + + DoubleAssignmentInfos assignmentInfos3 = DoubleAssignmentInfos.builder() + .filters(List.of(filter5)) + .editedField(BatteryField.ACTIVE_POWER_SET_POINT.name()) + .value(75.) + .build(); + + DoubleAssignmentInfos assignmentInfos4 = DoubleAssignmentInfos.builder() + .filters(List.of(filter4)) + .editedField(BatteryField.REACTIVE_POWER_SET_POINT.name()) + .value(2.) + .build(); + + DoubleAssignmentInfos assignmentInfos5 = DoubleAssignmentInfos.builder() + .filters(List.of(filter4)) + .editedField(BatteryField.DROOP.name()) + .value(2.) + .build(); + + List> infosList = super.getAssignmentInfos(); + infosList.addAll(List.of(assignmentInfos1, assignmentInfos2, assignmentInfos3, assignmentInfos4, assignmentInfos5)); + + return infosList; + } + + @Override + protected List> getUpdatedAssignmentInfos() { + DoubleAssignmentInfos assignmentInfos1 = DoubleAssignmentInfos.builder() + .filters(List.of(filter1, filter2)) + .editedField(BatteryField.MAXIMUM_ACTIVE_POWER.name()) + .value(200.) + .build(); + + DoubleAssignmentInfos assignmentInfos2 = DoubleAssignmentInfos.builder() + .filters(List.of(filter3)) + .editedField(BatteryField.MINIMUM_ACTIVE_POWER.name()) + .value(35.) + .build(); + + DoubleAssignmentInfos assignmentInfos3 = DoubleAssignmentInfos.builder() + .filters(List.of(filter3)) + .editedField(BatteryField.ACTIVE_POWER_SET_POINT.name()) + .value(10.) + .build(); + + return List.of(assignmentInfos1, assignmentInfos2, assignmentInfos3); + } + + @Override + protected void assertAfterNetworkModificationCreation() { + assertEquals(80, getNetwork().getBattery(BATTERY_ID_1).getMaxP(), 0); + assertEquals(2, getNetwork().getBattery(BATTERY_ID_1).getTargetQ(), 0); + ActivePowerControl activePowerControl1 = getNetwork().getBattery(BATTERY_ID_1).getExtension(ActivePowerControl.class); + assertNotNull(activePowerControl1); + assertEquals(2, activePowerControl1.getDroop(), 0); + + assertEquals(80, getNetwork().getBattery(BATTERY_ID_2).getMaxP(), 0); + assertEquals(75, getNetwork().getBattery(BATTERY_ID_2).getTargetP(), 0); + assertEquals(80, getNetwork().getBattery(BATTERY_ID_3).getMaxP(), 0); + assertEquals(75, getNetwork().getBattery(BATTERY_ID_3).getTargetP(), 0); + assertEquals(80, getNetwork().getBattery(BATTERY_ID_4).getMaxP(), 0); + + assertEquals(30, getNetwork().getBattery(BATTERY_ID_5).getMinP(), 0); + assertEquals(2, getNetwork().getBattery(BATTERY_ID_5).getTargetQ(), 0); + ActivePowerControl activePowerControl5 = getNetwork().getBattery(BATTERY_ID_5).getExtension(ActivePowerControl.class); + assertNotNull(activePowerControl5); + assertEquals(2, activePowerControl5.getDroop(), 0); + + assertEquals(30, getNetwork().getBattery(BATTERY_ID_6).getMinP(), 0); + } + + @Override + protected void assertAfterNetworkModificationDeletion() { + assertEquals(500, getNetwork().getBattery(BATTERY_ID_1).getMaxP(), 0); + assertEquals(80, getNetwork().getBattery(BATTERY_ID_1).getTargetQ(), 0); + ActivePowerControl activePowerControl1 = getNetwork().getBattery(BATTERY_ID_1).getExtension(ActivePowerControl.class); + assertNotNull(activePowerControl1); + assertEquals(1, activePowerControl1.getDroop(), 0); + + assertEquals(2000, getNetwork().getBattery(BATTERY_ID_2).getMaxP(), 0); + assertEquals(200, getNetwork().getBattery(BATTERY_ID_2).getTargetP(), 0); + assertEquals(400, getNetwork().getBattery(BATTERY_ID_3).getMaxP(), 0); + assertEquals(300, getNetwork().getBattery(BATTERY_ID_3).getTargetP(), 0); + assertEquals(350, getNetwork().getBattery(BATTERY_ID_4).getMaxP(), 0); + + assertEquals(50, getNetwork().getBattery(BATTERY_ID_5).getMinP(), 0); + assertEquals(140, getNetwork().getBattery(BATTERY_ID_5).getTargetQ(), 0); + ActivePowerControl activePowerControl5 = getNetwork().getBattery(BATTERY_ID_5).getExtension(ActivePowerControl.class); + assertNotNull(activePowerControl5); + assertEquals(4, activePowerControl5.getDroop(), 0); + + assertEquals(200, getNetwork().getBattery(BATTERY_ID_6).getMinP(), 0); + } + + @Override + protected IdentifiableType getIdentifiableType() { + return IdentifiableType.BATTERY; + } + + @Override + protected EquipmentType getEquipmentType() { + return EquipmentType.BATTERY; + } + +} diff --git a/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/GeneratorModificationByAssignmentTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/GeneratorModificationByAssignmentTest.java new file mode 100644 index 000000000..f4c724173 --- /dev/null +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/GeneratorModificationByAssignmentTest.java @@ -0,0 +1,441 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.modifications.byfilter.assignment; + +import com.powsybl.iidm.network.Generator; +import com.powsybl.iidm.network.IdentifiableType; +import com.powsybl.iidm.network.extensions.*; +import org.gridsuite.filter.AbstractFilter; +import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter; +import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes; +import org.gridsuite.filter.utils.EquipmentType; +import org.gridsuite.modification.server.dto.byfilter.assignment.AssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.assignment.BooleanAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.assignment.DoubleAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.equipmentfield.GeneratorField; +import org.junit.Test; +import org.junit.jupiter.api.Tag; + +import java.util.Date; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.gridsuite.modification.server.utils.NetworkUtil.createGenerator; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Thang PHAM + */ +@Tag("IntegrationTest") +public class GeneratorModificationByAssignmentTest extends AbstractModificationByAssignmentTest { + private static final String GENERATOR_ID_1 = "idGenerator"; + private static final String GENERATOR_ID_2 = "v5generator"; + private static final String GENERATOR_ID_3 = "v6generator"; + private static final String GENERATOR_ID_4 = "gen4"; + private static final String GENERATOR_ID_5 = "gen5"; + private static final String GENERATOR_ID_6 = "gen6"; + private static final String GENERATOR_ID_7 = "gen7"; + private static final String GENERATOR_ID_8 = "gen8"; + private static final String GENERATOR_ID_9 = "gen9"; + private static final String GENERATOR_ID_10 = "gen10"; + + @Test + public void testCreateWithWarning() throws Exception { + IdentifierListFilterEquipmentAttributes identifiableAttributes = getIdentifiableAttributes(GENERATOR_ID_1, 1.0); + IdentifierListFilterEquipmentAttributes wrongIdAttributes = getIdentifiableAttributes("wrongId", 1.0); + + DoubleAssignmentInfos assignmentInfos = DoubleAssignmentInfos.builder() + .filters(List.of(filterWithOneWrongId)) + .editedField(GeneratorField.ACTIVE_POWER_SET_POINT.name()) + .value(55.) + .build(); + + checkCreateWithWarning(List.of(assignmentInfos), List.of(identifiableAttributes, wrongIdAttributes)); + assertEquals(55, getNetwork().getGenerator(GENERATOR_ID_1).getTargetP(), 0); + } + + protected void createEquipments() { + getNetwork().getGenerator(GENERATOR_ID_1) + .setTargetP(100) + .setMaxP(500) + .setMinP(0) + .setTargetV(10) + .setTargetQ(20) + .newExtension(GeneratorStartupAdder.class) + .withMarginalCost(30.) + .withPlannedOutageRate(25.) + .withPlannedActivePowerSetpoint(40.) + .withForcedOutageRate(55.) + .add(); + + getNetwork().getGenerator(GENERATOR_ID_2) + .setTargetP(200) + .setMaxP(2000) + .setMinP(50) + .setTargetV(10) + .setTargetQ(20) + .newExtension(GeneratorStartupAdder.class) + .withMarginalCost(30.) + .withPlannedOutageRate(25.) + .withPlannedActivePowerSetpoint(40.) + .withForcedOutageRate(55.) + .add(); + + getNetwork().getGenerator(GENERATOR_ID_3) + .setTargetP(300) + .setMaxP(2000) + .setMinP(70) + .newExtension(GeneratorShortCircuitAdder.class) + .withDirectTransX(40.) + .withStepUpTransformerX(38.) + .add(); + + createGenerator(getNetwork().getVoltageLevel("v1"), GENERATOR_ID_4, 3, 400, 1.0, "cn10", 11, ConnectablePosition.Direction.TOP, 700, 110); + getNetwork().getGenerator(GENERATOR_ID_4) + .newExtension(GeneratorShortCircuitAdder.class) + .withDirectTransX(46.) + .withStepUpTransformerX(50.) + .add(); + + createGenerator(getNetwork().getVoltageLevel("v1"), GENERATOR_ID_5, 20, 200, 1.0, "cn10", 12, ConnectablePosition.Direction.TOP, 2000, 50); + getNetwork().getGenerator(GENERATOR_ID_5).newExtension(ActivePowerControlAdder.class).withDroop(2).add(); + + createGenerator(getNetwork().getVoltageLevel("v2"), GENERATOR_ID_6, 11, 100, 1.0, "cn10", 13, ConnectablePosition.Direction.TOP, 500, 20); + getNetwork().getGenerator(GENERATOR_ID_6).newExtension(ActivePowerControlAdder.class).withDroop(3).add(); + + createGenerator(getNetwork().getVoltageLevel("v6"), GENERATOR_ID_7, 10, 200, 1.0, "cn10", 14, ConnectablePosition.Direction.TOP, 2000, 50); + getNetwork().getGenerator(GENERATOR_ID_7).newExtension(CoordinatedReactiveControlAdder.class) + .withQPercent(6) + .add(); + getNetwork().getGenerator(GENERATOR_ID_7).newExtension(GeneratorStartupAdder.class).withMarginalCost(50).add(); + + createGenerator(getNetwork().getVoltageLevel("v3"), GENERATOR_ID_8, 10, 100, 1.0, "cn10", 15, ConnectablePosition.Direction.TOP, 500, 20); + getNetwork().getGenerator(GENERATOR_ID_8).newExtension(CoordinatedReactiveControlAdder.class) + .withQPercent(12) + .add(); + getNetwork().getGenerator(GENERATOR_ID_8).newExtension(GeneratorStartupAdder.class).withMarginalCost(60).add(); + + createGenerator(getNetwork().getVoltageLevel("v4"), GENERATOR_ID_9, 10, 200, 1.0, "cn10", 16, ConnectablePosition.Direction.TOP, 2000, 50); + getNetwork().getGenerator(GENERATOR_ID_9).setRatedS(60.); + + createGenerator(getNetwork().getVoltageLevel("v5"), GENERATOR_ID_10, 10, 100, 1.0, "cn10", 17, ConnectablePosition.Direction.TOP, 500, 20); + getNetwork().getGenerator(GENERATOR_ID_10).setRatedS(30.); + } + + protected List getTestFilters() { + IdentifierListFilter filter1 = IdentifierListFilter.builder().id(FILTER_ID_1).modificationDate(new Date()).equipmentType(EquipmentType.GENERATOR) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(GENERATOR_ID_1, 1.0), + new IdentifierListFilterEquipmentAttributes(GENERATOR_ID_2, 2.0))) + .build(); + IdentifierListFilter filter2 = IdentifierListFilter.builder().id(FILTER_ID_2).modificationDate(new Date()).equipmentType(EquipmentType.GENERATOR) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(GENERATOR_ID_3, 2.0), + new IdentifierListFilterEquipmentAttributes(GENERATOR_ID_4, 5.0))) + .build(); + IdentifierListFilter filter3 = IdentifierListFilter.builder().id(FILTER_ID_3).modificationDate(new Date()).equipmentType(EquipmentType.GENERATOR) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(GENERATOR_ID_5, 6.0), + new IdentifierListFilterEquipmentAttributes(GENERATOR_ID_6, 7.0))) + .build(); + IdentifierListFilter filter4 = IdentifierListFilter.builder().id(FILTER_ID_4).modificationDate(new Date()).equipmentType(EquipmentType.GENERATOR) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(GENERATOR_ID_7, 3.0), + new IdentifierListFilterEquipmentAttributes(GENERATOR_ID_8, 8.0))) + .build(); + IdentifierListFilter filter5 = IdentifierListFilter.builder().id(FILTER_ID_5).modificationDate(new Date()).equipmentType(EquipmentType.GENERATOR) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(GENERATOR_ID_9, 0.0), + new IdentifierListFilterEquipmentAttributes(GENERATOR_ID_10, 9.0))) + .build(); + + return List.of(filter1, filter2, filter3, filter4, filter5); + } + + @Override + protected List> getAssignmentInfos() { + + DoubleAssignmentInfos assignmentInfos1 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.REACTIVE_POWER_SET_POINT.name()) + .value(50.) + .filters(List.of(filter1, filter2)) + .build(); + + DoubleAssignmentInfos assignmentInfos2 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.DROOP.name()) + .value(2.) + .filters(List.of(filter3)) + .build(); + + DoubleAssignmentInfos assignmentInfos3 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.RATED_NOMINAL_POWER.name()) + .value(2.) + .filters(List.of(filter5)) + .build(); + + DoubleAssignmentInfos assignmentInfos4 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.MARGINAL_COST.name()) + .value(2.) + .filters(List.of(filter1)) + .build(); + + DoubleAssignmentInfos assignmentInfos5 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.VOLTAGE_SET_POINT.name()) + .value(2.) + .filters(List.of(filter4)) + .build(); + + DoubleAssignmentInfos assignmentInfos6 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.PLANNED_ACTIVE_POWER_SET_POINT.name()) + .value(10.) + .filters(List.of(filter1)) + .build(); + + DoubleAssignmentInfos assignmentInfos7 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.MINIMUM_ACTIVE_POWER.name()) + .value(2.) + .filters(List.of(filter1, filter2)) + .build(); + + DoubleAssignmentInfos assignmentInfos8 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.PLANNED_OUTAGE_RATE.name()) + .value(0.1) + .filters(List.of(filter1)) + .build(); + + DoubleAssignmentInfos assignmentInfos9 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.FORCED_OUTAGE_RATE.name()) + .value(0.05) + .filters(List.of(filter1)) + .build(); + + DoubleAssignmentInfos assignmentInfos10 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.MAXIMUM_ACTIVE_POWER.name()) + .value(50.) + .filters(List.of(filter1, filter2, filter3, filter4, filter5)) + .build(); + + DoubleAssignmentInfos assignmentInfos11 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.TRANSIENT_REACTANCE.name()) + .value(0.2) + .filters(List.of(filter2)) + .build(); + + DoubleAssignmentInfos assignmentInfos12 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.STEP_UP_TRANSFORMER_REACTANCE.name()) + .value(0.3) + .filters(List.of(filter2)) + .build(); + + DoubleAssignmentInfos assignmentInfos13 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.Q_PERCENT.name()) + .value(0.25) + .filters(List.of(filter4)) + .build(); + + BooleanAssignmentInfos assignmentInfos14 = BooleanAssignmentInfos.builder() + .editedField(GeneratorField.VOLTAGE_REGULATOR_ON.name()) + .value(true) + .filters(List.of(filter1)) + .build(); + + List> infosList = super.getAssignmentInfos(); + infosList.addAll(List.of( + assignmentInfos1, + assignmentInfos2, + assignmentInfos3, + assignmentInfos4, + assignmentInfos5, + assignmentInfos6, + assignmentInfos7, + assignmentInfos8, + assignmentInfos9, + assignmentInfos10, + assignmentInfos11, + assignmentInfos12, + assignmentInfos13, + assignmentInfos14 + )); + + return infosList; + } + + @Override + protected List> getUpdatedAssignmentInfos() { + DoubleAssignmentInfos assignmentInfos1 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.REACTIVE_POWER_SET_POINT.name()) + .value(2.) + .filters(List.of(filter1, filter2)) + .build(); + + DoubleAssignmentInfos assignmentInfos2 = DoubleAssignmentInfos.builder() + .editedField(GeneratorField.MINIMUM_ACTIVE_POWER.name()) + .value(0.5) + .filters(List.of(filter3)) + .build(); + + return List.of(assignmentInfos1, assignmentInfos2); + } + + @Override + protected void assertAfterNetworkModificationCreation() { + Generator generator1 = getNetwork().getGenerator(GENERATOR_ID_1); + GeneratorStartup generatorStartup1 = generator1.getExtension(GeneratorStartup.class); + assertNotNull(generatorStartup1); + assertThat(generator1.getProperty("propertyName")).isEqualTo("propertyValue"); + assertEquals(100, generator1.getTargetP(), 0); + assertEquals(2, generatorStartup1.getMarginalCost(), 0); + assertEquals(0.1, generatorStartup1.getPlannedOutageRate(), 0); + assertEquals(0.05, generatorStartup1.getForcedOutageRate(), 0); + assertEquals(10, generatorStartup1.getPlannedActivePowerSetpoint(), 0); + assertEquals(50, generator1.getMaxP(), 0); + assertEquals(2, generator1.getMinP(), 0); + assertEquals(true, generator1.isVoltageRegulatorOn()); + + Generator generator2 = getNetwork().getGenerator(GENERATOR_ID_2); + GeneratorStartup generatorStartup2 = generator2.getExtension(GeneratorStartup.class); + assertNotNull(generatorStartup2); + assertThat(generator2.getProperty("propertyName")).isEqualTo("propertyValue"); + assertEquals(200, generator2.getTargetP(), 0); + assertEquals(2, generatorStartup2.getMarginalCost(), 0); + assertEquals(0.1, generatorStartup2.getPlannedOutageRate(), 0); + assertEquals(0.05, generatorStartup2.getForcedOutageRate(), 0); + assertEquals(10, generatorStartup2.getPlannedActivePowerSetpoint(), 0); + assertEquals(50, generator2.getMaxP(), 0); + assertEquals(2, generator2.getMinP(), 0); + + Generator generator3 = getNetwork().getGenerator(GENERATOR_ID_3); + GeneratorShortCircuit generatorShortCircuit3 = generator3.getExtension(GeneratorShortCircuit.class); + assertNotNull(generatorShortCircuit3); + assertEquals(300, generator3.getTargetP(), 0); + assertEquals(0.2, generatorShortCircuit3.getDirectTransX(), 0); + assertEquals(0.3, generatorShortCircuit3.getStepUpTransformerX(), 0); + assertEquals(50, generator3.getMaxP(), 0); + assertEquals(2, generator3.getMinP(), 0); + + Generator generator4 = getNetwork().getGenerator(GENERATOR_ID_4); + GeneratorShortCircuit generatorShortCircuit4 = generator4.getExtension(GeneratorShortCircuit.class); + assertNotNull(generatorShortCircuit4); + assertEquals(0.2, generatorShortCircuit4.getDirectTransX(), 0); + assertEquals(0.3, generatorShortCircuit4.getStepUpTransformerX(), 0); + assertEquals(400, generator4.getTargetP(), 0); + assertEquals(50, generator4.getMaxP(), 0); + assertEquals(2, generator4.getMinP(), 0); + + Generator generator5 = getNetwork().getGenerator(GENERATOR_ID_5); + ActivePowerControl activePowerControl5 = generator5.getExtension(ActivePowerControl.class); + assertNotNull(activePowerControl5); + assertEquals(50, generator5.getMaxP(), 0); + assertEquals(2, activePowerControl5.getDroop(), 0); + + Generator generator6 = getNetwork().getGenerator(GENERATOR_ID_6); + ActivePowerControl activePowerControl6 = generator6.getExtension(ActivePowerControl.class); + assertNotNull(activePowerControl6); + assertEquals(50, generator6.getMaxP(), 0); + assertEquals(2, activePowerControl6.getDroop(), 0); + + Generator generator7 = getNetwork().getGenerator(GENERATOR_ID_7); + CoordinatedReactiveControl coordinatedReactiveControl7 = generator7.getExtension(CoordinatedReactiveControl.class); + assertNotNull(coordinatedReactiveControl7); + GeneratorStartup generatorStartup7 = generator7.getExtension(GeneratorStartup.class); + assertNotNull(generatorStartup7); + assertEquals(50, generatorStartup7.getMarginalCost(), 0); + assertEquals(0.25, coordinatedReactiveControl7.getQPercent(), 0); + + Generator generator8 = getNetwork().getGenerator(GENERATOR_ID_8); + CoordinatedReactiveControl coordinatedReactiveControl8 = generator8.getExtension(CoordinatedReactiveControl.class); + assertNotNull(coordinatedReactiveControl8); + GeneratorStartup generatorStartup8 = generator8.getExtension(GeneratorStartup.class); + assertNotNull(generatorStartup8); + assertEquals(60, generatorStartup8.getMarginalCost(), 0); + assertEquals(0.25, coordinatedReactiveControl8.getQPercent(), 0); + + assertEquals(2, getNetwork().getGenerator(GENERATOR_ID_9).getRatedS(), 0); + assertEquals(2, getNetwork().getGenerator(GENERATOR_ID_10).getRatedS(), 0); + } + + @Override + protected void assertAfterNetworkModificationDeletion() { + Generator generator1 = getNetwork().getGenerator(GENERATOR_ID_1); + GeneratorStartup generatorStartup1 = generator1.getExtension(GeneratorStartup.class); + assertNotNull(generatorStartup1); + assertEquals(100, generator1.getTargetP(), 0); + assertEquals(30, generatorStartup1.getMarginalCost(), 0); + assertEquals(25, generatorStartup1.getPlannedOutageRate(), 0); + assertEquals(55, generatorStartup1.getForcedOutageRate(), 0); + assertEquals(40, generatorStartup1.getPlannedActivePowerSetpoint(), 0); + assertEquals(500, generator1.getMaxP(), 0); + assertEquals(0, generator1.getMinP(), 0); + + Generator generator2 = getNetwork().getGenerator(GENERATOR_ID_2); + GeneratorStartup generatorStartup2 = generator2.getExtension(GeneratorStartup.class); + assertNotNull(generatorStartup2); + assertEquals(200, generator2.getTargetP(), 0); + assertEquals(30, generatorStartup2.getMarginalCost(), 0); + assertEquals(25, generatorStartup2.getPlannedOutageRate(), 0); + assertEquals(55, generatorStartup2.getForcedOutageRate(), 0); + assertEquals(40, generatorStartup2.getPlannedActivePowerSetpoint(), 0); + assertEquals(2000, generator2.getMaxP(), 0); + assertEquals(50, generator2.getMinP(), 0); + + Generator generator3 = getNetwork().getGenerator(GENERATOR_ID_3); + GeneratorShortCircuit generatorShortCircuit3 = generator3.getExtension(GeneratorShortCircuit.class); + assertNotNull(generatorShortCircuit3); + assertEquals(300, generator3.getTargetP(), 0); + assertEquals(40, generatorShortCircuit3.getDirectTransX(), 0); + assertEquals(38, generatorShortCircuit3.getStepUpTransformerX(), 0); + assertEquals(2000, generator3.getMaxP(), 0); + assertEquals(70, generator3.getMinP(), 0); + + Generator generator4 = getNetwork().getGenerator(GENERATOR_ID_4); + GeneratorShortCircuit generatorShortCircuit4 = generator4.getExtension(GeneratorShortCircuit.class); + assertNotNull(generatorShortCircuit4); + assertEquals(46, generatorShortCircuit4.getDirectTransX(), 0); + assertEquals(50, generatorShortCircuit4.getStepUpTransformerX(), 0); + assertEquals(400, generator4.getTargetP(), 0); + assertEquals(700, generator4.getMaxP(), 0); + assertEquals(110, generator4.getMinP(), 0); + + Generator generator5 = getNetwork().getGenerator(GENERATOR_ID_5); + ActivePowerControl activePowerControl5 = generator5.getExtension(ActivePowerControl.class); + assertNotNull(activePowerControl5); + assertEquals(2000, generator5.getMaxP(), 0); + assertEquals(2, activePowerControl5.getDroop(), 0); + + Generator generator6 = getNetwork().getGenerator(GENERATOR_ID_6); + ActivePowerControl activePowerControl6 = generator6.getExtension(ActivePowerControl.class); + assertNotNull(activePowerControl6); + assertEquals(500, generator6.getMaxP(), 0); + assertEquals(3, activePowerControl6.getDroop(), 0); + + Generator generator7 = getNetwork().getGenerator(GENERATOR_ID_7); + CoordinatedReactiveControl coordinatedReactiveControl7 = generator7.getExtension(CoordinatedReactiveControl.class); + assertNotNull(coordinatedReactiveControl7); + GeneratorStartup generatorStartup7 = generator7.getExtension(GeneratorStartup.class); + assertNotNull(generatorStartup7); + assertEquals(50, generatorStartup7.getMarginalCost(), 0); + assertEquals(6, coordinatedReactiveControl7.getQPercent(), 0); + + Generator generator8 = getNetwork().getGenerator(GENERATOR_ID_8); + CoordinatedReactiveControl coordinatedReactiveControl8 = generator8.getExtension(CoordinatedReactiveControl.class); + assertNotNull(coordinatedReactiveControl8); + GeneratorStartup generatorStartup8 = generator8.getExtension(GeneratorStartup.class); + assertNotNull(generatorStartup8); + assertEquals(60, generatorStartup8.getMarginalCost(), 0); + assertEquals(12, coordinatedReactiveControl8.getQPercent(), 0); + + assertEquals(60, getNetwork().getGenerator(GENERATOR_ID_9).getRatedS(), 0); + assertEquals(30, getNetwork().getGenerator(GENERATOR_ID_10).getRatedS(), 0); + } + + @Override + protected IdentifiableType getIdentifiableType() { + return IdentifiableType.GENERATOR; + } + + @Override + protected EquipmentType getEquipmentType() { + return EquipmentType.GENERATOR; + } +} diff --git a/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/LoadModificationByAssignmentTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/LoadModificationByAssignmentTest.java new file mode 100644 index 000000000..e4fb3de38 --- /dev/null +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/LoadModificationByAssignmentTest.java @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.modifications.byfilter.assignment; + +import com.powsybl.iidm.network.IdentifiableType; +import com.powsybl.iidm.network.LoadType; +import org.gridsuite.filter.AbstractFilter; +import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter; +import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes; +import org.gridsuite.filter.utils.EquipmentType; +import org.gridsuite.modification.server.dto.byfilter.assignment.AssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.assignment.DoubleAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.assignment.EnumAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.equipmentfield.LoadField; +import org.gridsuite.modification.server.impacts.AbstractBaseImpact; + +import java.util.Date; +import java.util.List; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.gridsuite.modification.server.Impacts.TestImpactUtils.createSubstationImpacts; +import static org.gridsuite.modification.server.utils.NetworkUtil.createLoad; +import static org.junit.Assert.assertEquals; + +/** + * @author Thang PHAM + */ +public class LoadModificationByAssignmentTest extends AbstractModificationByAssignmentTest { + private static final String LOAD_ID_1 = "load1"; + private static final String LOAD_ID_2 = "load2"; + private static final String LOAD_ID_3 = "load3"; + private static final String LOAD_ID_4 = "load4"; + + @Override + protected void createEquipments() { + createLoad(getNetwork().getVoltageLevel("v1"), LOAD_ID_1, "load1", 100, 100, 120, null, 5, null); + createLoad(getNetwork().getVoltageLevel("v2"), LOAD_ID_2, "load2", 200, 80, 90, null, 5, null); + createLoad(getNetwork().getVoltageLevel("v3"), LOAD_ID_3, "load3", 300, 100, 70, null, 5, null); + createLoad(getNetwork().getVoltageLevel("v4"), LOAD_ID_4, "load4", 400, 50, 150, null, 5, null); + } + + @Override + protected List getTestFilters() { + IdentifierListFilter filter1 = IdentifierListFilter.builder().id(FILTER_ID_1).modificationDate(new Date()).equipmentType(EquipmentType.LOAD) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(LOAD_ID_1, 1.0), + new IdentifierListFilterEquipmentAttributes(LOAD_ID_2, 2.0))) + .build(); + IdentifierListFilter filter2 = IdentifierListFilter.builder().id(FILTER_ID_2).modificationDate(new Date()).equipmentType(EquipmentType.LOAD) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(LOAD_ID_3, 2.0), + new IdentifierListFilterEquipmentAttributes(LOAD_ID_4, 5.0))) + .build(); + + return List.of(filter1, filter2); + } + + @Override + protected List> getAssignmentInfos() { + DoubleAssignmentInfos assignmentInfos1 = DoubleAssignmentInfos.builder() + .editedField(LoadField.ACTIVE_POWER.name()) + .value(25.) + .filters(List.of(filter1)) + .build(); + + DoubleAssignmentInfos assignmentInfos2 = DoubleAssignmentInfos.builder() + .editedField(LoadField.REACTIVE_POWER.name()) + .value(2.5) + .filters(List.of(filter2)) + .build(); + + EnumAssignmentInfos assignmentInfos3 = EnumAssignmentInfos.builder() + .editedField(LoadField.LOAD_TYPE.name()) + .value(LoadType.AUXILIARY.name()) + .filters(List.of(filter1)) + .build(); + + List> infosList = super.getAssignmentInfos(); + infosList.addAll(List.of(assignmentInfos1, assignmentInfos2, assignmentInfos3)); + + return infosList; + } + + @Override + protected List> getUpdatedAssignmentInfos() { + DoubleAssignmentInfos assignmentInfos1 = DoubleAssignmentInfos.builder() + .editedField(LoadField.ACTIVE_POWER.name()) + .value(200.) + .filters(List.of(filter1)) + .build(); + + return List.of(assignmentInfos1); + } + + @Override + protected void assertAfterNetworkModificationCreation() { + assertEquals(25, getNetwork().getLoad(LOAD_ID_1).getP0(), 0); + assertEquals(25, getNetwork().getLoad(LOAD_ID_2).getP0(), 0); + assertEquals(2.5, getNetwork().getLoad(LOAD_ID_3).getQ0(), 0); + assertEquals(2.5, getNetwork().getLoad(LOAD_ID_4).getQ0(), 0); + assertThat(getNetwork().getLoad(LOAD_ID_1).getLoadType()).isEqualTo(LoadType.AUXILIARY); + assertThat(getNetwork().getLoad(LOAD_ID_2).getLoadType()).isEqualTo(LoadType.AUXILIARY); + } + + @Override + protected void assertAfterNetworkModificationDeletion() { + assertEquals(100, getNetwork().getLoad(LOAD_ID_1).getP0(), 0); + assertEquals(80, getNetwork().getLoad(LOAD_ID_2).getP0(), 0); + assertEquals(70, getNetwork().getLoad(LOAD_ID_3).getQ0(), 0); + assertEquals(150, getNetwork().getLoad(LOAD_ID_4).getQ0(), 0); + } + + @Override + protected IdentifiableType getIdentifiableType() { + return IdentifiableType.LOAD; + } + + @Override + protected EquipmentType getEquipmentType() { + return EquipmentType.LOAD; + } + + @Override + protected void assertResultImpacts(List impacts) { + // NOTE: this assert is based on the return of NetworkStoreListener#reduceNetworkImpacts() + // since the test network has only 4 loads which is less than the collectionThreshold 5 + assertThat(impacts).containsAll(createSubstationImpacts(Set.of("s1", "s2"))); + } + +} diff --git a/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/ShuntCompensatorModificationByAssignmentTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/ShuntCompensatorModificationByAssignmentTest.java new file mode 100644 index 000000000..727b1d4b2 --- /dev/null +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/ShuntCompensatorModificationByAssignmentTest.java @@ -0,0 +1,184 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.modifications.byfilter.assignment; + +import com.powsybl.iidm.network.IdentifiableType; +import com.powsybl.iidm.network.ShuntCompensator; +import com.powsybl.iidm.network.ShuntCompensatorLinearModel; +import com.powsybl.iidm.network.extensions.ConnectablePosition; +import org.gridsuite.filter.AbstractFilter; +import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter; +import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes; +import org.gridsuite.filter.utils.EquipmentType; +import org.gridsuite.modification.server.dto.byfilter.assignment.AssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.assignment.DoubleAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.assignment.IntegerAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.equipmentfield.ShuntCompensatorField; +import org.junit.Test; + +import java.util.Date; +import java.util.List; + +import static org.gridsuite.modification.server.utils.NetworkUtil.createShuntCompensator; +import static org.junit.Assert.assertEquals; + +/** + * @author Thang PHAM + */ +public class ShuntCompensatorModificationByAssignmentTest extends AbstractModificationByAssignmentTest { + private static final String SHUNT_COMPENSATOR_ID_1 = "v1shunt"; + private static final String SHUNT_COMPENSATOR_ID_2 = "v2shunt"; + private static final String SHUNT_COMPENSATOR_ID_3 = "v3shunt"; + private static final String SHUNT_COMPENSATOR_ID_4 = "v4shunt"; + private static final String SHUNT_COMPENSATOR_ID_5 = "v5shunt"; + + @Test + public void testCreateWithWarning() throws Exception { + IdentifierListFilterEquipmentAttributes identifiableAttributes = getIdentifiableAttributes(SHUNT_COMPENSATOR_ID_1, 1.0); + IdentifierListFilterEquipmentAttributes wrongIdAttributes = getIdentifiableAttributes("wrongId", 1.0); + + IntegerAssignmentInfos assignmentInfos = IntegerAssignmentInfos.builder() + .editedField(ShuntCompensatorField.MAXIMUM_SECTION_COUNT.name()) + .value(2) + .filters(List.of(filterWithOneWrongId)) + .build(); + + checkCreateWithWarning(List.of(assignmentInfos), List.of(identifiableAttributes, wrongIdAttributes)); + assertEquals(2, getNetwork().getShuntCompensator(SHUNT_COMPENSATOR_ID_1).getMaximumSectionCount(), 0); + } + + @Override + protected void createEquipments() { + createShuntCompensator(getNetwork().getVoltageLevel("v1"), SHUNT_COMPENSATOR_ID_1, "v1shunt", 8, 225., 10, true, 4, 2, 3, 2, "cn11", 22, ConnectablePosition.Direction.BOTTOM); + createShuntCompensator(getNetwork().getVoltageLevel("v3"), SHUNT_COMPENSATOR_ID_3, "v3shunt", 10, 305., 20, true, 6, 3, 3, 4, "cn11", 22, ConnectablePosition.Direction.BOTTOM); + createShuntCompensator(getNetwork().getVoltageLevel("v4"), SHUNT_COMPENSATOR_ID_4, "v3shunt", 10, 305., 20, true, 15, 4, 3, 10, "cn11", 22, ConnectablePosition.Direction.BOTTOM); + } + + @Override + protected List getTestFilters() { + IdentifierListFilter filter1 = IdentifierListFilter.builder().id(FILTER_ID_1).modificationDate(new Date()).equipmentType(EquipmentType.SHUNT_COMPENSATOR) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(SHUNT_COMPENSATOR_ID_1, 1.0))) + .build(); + IdentifierListFilter filter2 = IdentifierListFilter.builder().id(FILTER_ID_2).modificationDate(new Date()).equipmentType(EquipmentType.SHUNT_COMPENSATOR) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(SHUNT_COMPENSATOR_ID_2, 1.0))) + .build(); + IdentifierListFilter filter3 = IdentifierListFilter.builder().id(FILTER_ID_3).modificationDate(new Date()).equipmentType(EquipmentType.SHUNT_COMPENSATOR) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(SHUNT_COMPENSATOR_ID_3, 1.0))) + .build(); + IdentifierListFilter filter4 = IdentifierListFilter.builder().id(FILTER_ID_4).modificationDate(new Date()).equipmentType(EquipmentType.SHUNT_COMPENSATOR) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(SHUNT_COMPENSATOR_ID_4, 1.0))) + .build(); + IdentifierListFilter filter5 = IdentifierListFilter.builder().id(FILTER_ID_5).modificationDate(new Date()).equipmentType(EquipmentType.SHUNT_COMPENSATOR) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(SHUNT_COMPENSATOR_ID_5, 1.0))) + .build(); + + return List.of(filter1, filter2, filter3, filter4, filter5); + } + + @Override + protected List> getAssignmentInfos() { + IntegerAssignmentInfos assignmentInfos1 = IntegerAssignmentInfos.builder() + .editedField(ShuntCompensatorField.MAXIMUM_SECTION_COUNT.name()) + .value(8) + .filters(List.of(filter1, filter2)) + .build(); + + IntegerAssignmentInfos assignmentInfos2 = IntegerAssignmentInfos.builder() + .editedField(ShuntCompensatorField.SECTION_COUNT.name()) + .value(2) + .filters(List.of(filter3)) + .build(); + + DoubleAssignmentInfos assignmentInfos3 = DoubleAssignmentInfos.builder() + .editedField(ShuntCompensatorField.MAXIMUM_SUSCEPTANCE.name()) + .value(5.) + .filters(List.of(filter4)) + .build(); + + DoubleAssignmentInfos assignmentInfos4 = DoubleAssignmentInfos.builder() + .editedField(ShuntCompensatorField.MAXIMUM_Q_AT_NOMINAL_VOLTAGE.name()) + .value(10.) + .filters(List.of(filter5)) + .build(); + + List> infosList = super.getAssignmentInfos(); + infosList.addAll(List.of(assignmentInfos1, assignmentInfos2, assignmentInfos3, assignmentInfos4)); + + return infosList; + } + + @Override + protected List> getUpdatedAssignmentInfos() { + IntegerAssignmentInfos assignmentInfos1 = IntegerAssignmentInfos.builder() + .editedField(ShuntCompensatorField.MAXIMUM_SECTION_COUNT.name()) + .value(150) + .filters(List.of(filter1, filter2)) + .build(); + + IntegerAssignmentInfos assignmentInfos2 = IntegerAssignmentInfos.builder() + .editedField(ShuntCompensatorField.SECTION_COUNT.name()) + .value(2) + .filters(List.of(filter3)) + .build(); + return List.of(assignmentInfos1, assignmentInfos2); + } + + @Override + protected void assertAfterNetworkModificationCreation() { + ShuntCompensator shuntCompensator1 = getNetwork().getShuntCompensator(SHUNT_COMPENSATOR_ID_1); + assertEquals(8, shuntCompensator1.getMaximumSectionCount()); + assertEquals(1, shuntCompensator1.getModel(ShuntCompensatorLinearModel.class).getBPerSection(), 0); + + ShuntCompensator shuntCompensator2 = getNetwork().getShuntCompensator(SHUNT_COMPENSATOR_ID_2); + assertEquals(8, shuntCompensator2.getMaximumSectionCount()); + assertEquals(0.375, shuntCompensator2.getModel(ShuntCompensatorLinearModel.class).getBPerSection(), 0); + + ShuntCompensator shuntCompensator3 = getNetwork().getShuntCompensator(SHUNT_COMPENSATOR_ID_3); + assertEquals(6, shuntCompensator3.getMaximumSectionCount()); + assertEquals(3, shuntCompensator3.getModel(ShuntCompensatorLinearModel.class).getBPerSection(), 0); + + ShuntCompensator shuntCompensator4 = getNetwork().getShuntCompensator(SHUNT_COMPENSATOR_ID_4); + assertEquals(10, shuntCompensator4.getSectionCount()); + + ShuntCompensator shuntCompensator5 = getNetwork().getShuntCompensator(SHUNT_COMPENSATOR_ID_5); + assertEquals(2, shuntCompensator5.getSectionCount()); + } + + @Override + protected void assertAfterNetworkModificationDeletion() { + ShuntCompensator shuntCompensator1 = getNetwork().getShuntCompensator(SHUNT_COMPENSATOR_ID_1); + assertEquals(4, shuntCompensator1.getMaximumSectionCount()); + assertEquals(2, shuntCompensator1.getModel(ShuntCompensatorLinearModel.class).getBPerSection(), 0); + + ShuntCompensator shuntCompensator2 = getNetwork().getShuntCompensator(SHUNT_COMPENSATOR_ID_2); + assertEquals(3, shuntCompensator2.getMaximumSectionCount()); + assertEquals(1, shuntCompensator2.getModel(ShuntCompensatorLinearModel.class).getBPerSection(), 0); + + ShuntCompensator shuntCompensator3 = getNetwork().getShuntCompensator(SHUNT_COMPENSATOR_ID_3); + assertEquals(6, shuntCompensator3.getMaximumSectionCount()); + assertEquals(3, shuntCompensator3.getModel(ShuntCompensatorLinearModel.class).getBPerSection(), 0); + + ShuntCompensator shuntCompensator4 = getNetwork().getShuntCompensator(SHUNT_COMPENSATOR_ID_4); + assertEquals(10, shuntCompensator4.getSectionCount()); + + ShuntCompensator shuntCompensator5 = getNetwork().getShuntCompensator(SHUNT_COMPENSATOR_ID_5); + assertEquals(2, shuntCompensator5.getSectionCount()); + assertEquals(1, shuntCompensator5.getModel(ShuntCompensatorLinearModel.class).getBPerSection(), 0); + } + + @Override + protected IdentifiableType getIdentifiableType() { + return IdentifiableType.SHUNT_COMPENSATOR; + } + + @Override + protected EquipmentType getEquipmentType() { + return EquipmentType.SHUNT_COMPENSATOR; + } + +} diff --git a/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/TwoWindingsTransformerModificationByAssignmentTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/TwoWindingsTransformerModificationByAssignmentTest.java new file mode 100644 index 000000000..0b1cb2f14 --- /dev/null +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/TwoWindingsTransformerModificationByAssignmentTest.java @@ -0,0 +1,576 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.modifications.byfilter.assignment; + +import com.github.tomakehurst.wiremock.client.WireMock; +import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.extensions.ConnectablePosition; +import org.gridsuite.filter.AbstractFilter; +import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter; +import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes; +import org.gridsuite.filter.utils.EquipmentType; +import org.gridsuite.modification.server.dto.NetworkModificationResult; +import org.gridsuite.modification.server.dto.byfilter.assignment.AssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.assignment.DoubleAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.assignment.IntegerAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.equipmentfield.TwoWindingsTransformerField; +import org.junit.Test; + +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import static org.gridsuite.modification.server.utils.NetworkUtil.createTwoWindingsTransformer; +import static org.junit.Assert.*; + +/** + * @author Thang PHAM + */ +public class TwoWindingsTransformerModificationByAssignmentTest extends AbstractModificationByAssignmentTest { + private static final String TWT_ID_1 = "twt1"; + private static final String TWT_ID_2 = "twt2"; + private static final String TWT_ID_3 = "twt3"; + private static final String TWT_ID_4 = "twt4"; + private static final String TWT_ID_5 = "twt5"; + private static final String TWT_ID_6 = "twt6"; + + @Test + public void testModifyTwtWithError() throws Exception { + // Test modifying ratio tab changer field when ratio tab changer is null + IdentifierListFilterEquipmentAttributes identifiableAttributes1 = getIdentifiableAttributes(TWT_ID_4, 1.); + IdentifierListFilterEquipmentAttributes identifiableAttributes2 = getIdentifiableAttributes(TWT_ID_6, 1.); + AbstractFilter filter = getFilterEquipments(FILTER_ID_4, List.of(identifiableAttributes1, identifiableAttributes2)); + DoubleAssignmentInfos assignmentInfos = DoubleAssignmentInfos.builder() + .editedField(TwoWindingsTransformerField.RATIO_TAP_POSITION.name()) + .value(1.) + .filters(List.of(filter4)) + .build(); + + checkCreateWithError(List.of(assignmentInfos), List.of(filter)); + + assertNull(getNetwork().getTwoWindingsTransformer(TWT_ID_4).getRatioTapChanger()); + assertNull(getNetwork().getTwoWindingsTransformer(TWT_ID_6).getRatioTapChanger()); + + // Test modifying phase tab changer field when phase tab changer is null + IdentifierListFilterEquipmentAttributes identifiableAttributes3 = getIdentifiableAttributes(TWT_ID_1, 1.); + IdentifierListFilterEquipmentAttributes identifiableAttributes4 = getIdentifiableAttributes(TWT_ID_2, 1.); + AbstractFilter filter2 = getFilterEquipments(FILTER_ID_1, List.of(identifiableAttributes3, identifiableAttributes4)); + DoubleAssignmentInfos assignmentInfos2 = DoubleAssignmentInfos.builder() + .editedField(TwoWindingsTransformerField.PHASE_TAP_POSITION.name()) + .value(1.) + .filters(List.of(filter1)) + .build(); + + checkCreateWithError(List.of(assignmentInfos2), List.of(filter2)); + + assertNull(getNetwork().getTwoWindingsTransformer(TWT_ID_1).getPhaseTapChanger()); + assertNull(getNetwork().getTwoWindingsTransformer(TWT_ID_2).getPhaseTapChanger()); + } + + @Test + public void testModifyTwtWithWarning() throws Exception { + IdentifierListFilterEquipmentAttributes identifiableAttributes1 = getIdentifiableAttributes(TWT_ID_1, 1.); + IdentifierListFilterEquipmentAttributes identifiableAttributes2 = getIdentifiableAttributes(TWT_ID_2, 1.); + IdentifierListFilterEquipmentAttributes identifiableAttributes3 = getIdentifiableAttributes(TWT_ID_4, 1.); + IdentifierListFilterEquipmentAttributes identifiableAttributes4 = getIdentifiableAttributes(TWT_ID_6, 1.); + AbstractFilter filterTwt1 = getFilterEquipments(FILTER_ID_1, List.of(identifiableAttributes1, identifiableAttributes2)); + AbstractFilter filterTwt2 = getFilterEquipments(FILTER_ID_4, List.of(identifiableAttributes3, identifiableAttributes4)); + + UUID stubId = wireMockServer.stubFor(WireMock.get(WireMock.urlMatching(getPath(true) + ".{2,}")) + .willReturn(WireMock.ok() + .withBody(mapper.writeValueAsString(List.of(filterTwt1, filterTwt2))) + .withHeader("Content-Type", "application/json"))).getId(); + + IntegerAssignmentInfos assignmentInfos = IntegerAssignmentInfos.builder() + .filters(List.of(filter1, filter4)) + .editedField(TwoWindingsTransformerField.RATIO_TAP_POSITION.name()) + .value(4) + .build(); + + checkCreationApplicationStatus(List.of(assignmentInfos), NetworkModificationResult.ApplicationStatus.WITH_WARNINGS); + + assertNotNull(getNetwork().getTwoWindingsTransformer(TWT_ID_1).getRatioTapChanger()); + assertNotNull(getNetwork().getTwoWindingsTransformer(TWT_ID_2).getRatioTapChanger()); + assertEquals(4, getNetwork().getTwoWindingsTransformer(TWT_ID_1).getRatioTapChanger().getTapPosition()); + assertEquals(4, getNetwork().getTwoWindingsTransformer(TWT_ID_2).getRatioTapChanger().getTapPosition()); + assertNull(getNetwork().getTwoWindingsTransformer(TWT_ID_4).getRatioTapChanger()); + assertNull(getNetwork().getTwoWindingsTransformer(TWT_ID_6).getRatioTapChanger()); + + wireMockUtils.verifyGetRequest(stubId, PATH, handleQueryParams(List.of(FILTER_ID_1, FILTER_ID_4)), false); + } + + @Override + protected void createEquipments() { + Substation s1 = getNetwork().getSubstation("s1"); + Substation s3 = getNetwork().getSubstation("s3"); + TwoWindingsTransformer twt1 = createTwoWindingsTransformer(s1, TWT_ID_1, TWT_ID_1, 30, 40, 50, + 60, 10, 20, 100, 100, + "v1", "v2", + "trf1", 11, ConnectablePosition.Direction.TOP, + "trf1", 22, ConnectablePosition.Direction.BOTTOM); + twt1.setRatedS(11); + addRatioTapChangerSteps(twt1.newRatioTapChanger().setTargetV(50).setLowTapPosition(0).setTapPosition(1).setTargetDeadband(55)); + + TwoWindingsTransformer twt2 = createTwoWindingsTransformer(s1, TWT_ID_2, TWT_ID_2, 35, 45, 55, + 65, 15, 25, 101, 100, + "v1", "v4", + "trf1", 33, ConnectablePosition.Direction.TOP, + "trf1", 44, ConnectablePosition.Direction.BOTTOM); + twt2.setRatedS(10); + addRatioTapChangerSteps(twt2.newRatioTapChanger().setTargetV(53).setLowTapPosition(3).setTapPosition(4).setTargetDeadband(58)); + + TwoWindingsTransformer twt3 = createTwoWindingsTransformer(s1, TWT_ID_3, TWT_ID_3, 40, 50, 60, + 70, 20, 30, 101, 101, + "v2", "v4", + "trf1", 10, ConnectablePosition.Direction.TOP, + "trf1", 20, ConnectablePosition.Direction.BOTTOM); + twt3.setRatedS(25); + addRatioTapChangerSteps(twt3.newRatioTapChanger().setTargetV(56).setLowTapPosition(0).setTapPosition(1).setTargetDeadband(61)); + + TwoWindingsTransformer twt4 = createTwoWindingsTransformer(s3, TWT_ID_4, TWT_ID_4, 45, 55, 65, + 75, 25, 35, 100, 100, + "v5", "v6", + "trf1", 30, ConnectablePosition.Direction.TOP, + "trf1", 40, ConnectablePosition.Direction.BOTTOM); + twt4.setRatedS(15); + addPhaseTapChangerSteps(twt4.newPhaseTapChanger() + .setRegulationValue(45) + .setLowTapPosition(1) + .setTapPosition(2) + .setTargetDeadband(34) + .setRegulationMode(PhaseTapChanger.RegulationMode.ACTIVE_POWER_CONTROL)); + + TwoWindingsTransformer twt5 = createTwoWindingsTransformer(s3, TWT_ID_5, TWT_ID_5, 50, 60, 70, + 80, 30, 40, 101, 101, + "v5", "v6", + "trf1", 15, ConnectablePosition.Direction.TOP, + "trf1", 26, ConnectablePosition.Direction.BOTTOM); + twt5.setRatedS(30); + addPhaseTapChangerSteps(twt5.newPhaseTapChanger().setRegulationValue(46).setLowTapPosition(2).setTapPosition(2).setTargetDeadband(35)); + + TwoWindingsTransformer twt6 = createTwoWindingsTransformer(s3, TWT_ID_6, TWT_ID_6, 55, 65, 75, 85, + 35, 45, 102, 102, + "v5", "v6", + "trf1", 38, ConnectablePosition.Direction.TOP, + "trf1", 49, ConnectablePosition.Direction.BOTTOM); + twt6.setRatedS(20); + addPhaseTapChangerSteps(twt6.newPhaseTapChanger().setRegulationValue(47).setLowTapPosition(1).setTapPosition(1).setTargetDeadband(36)); + } + + @Override + protected List getTestFilters() { + IdentifierListFilter filter1 = IdentifierListFilter.builder().id(FILTER_ID_1).modificationDate(new Date()).equipmentType(EquipmentType.TWO_WINDINGS_TRANSFORMER) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(TWT_ID_1, 1.0), + new IdentifierListFilterEquipmentAttributes(TWT_ID_2, 2.0))) + .build(); + IdentifierListFilter filter2 = IdentifierListFilter.builder().id(FILTER_ID_2).modificationDate(new Date()).equipmentType(EquipmentType.TWO_WINDINGS_TRANSFORMER) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(TWT_ID_1, 1.0), + new IdentifierListFilterEquipmentAttributes(TWT_ID_3, 2.0))) + .build(); + IdentifierListFilter filter3 = IdentifierListFilter.builder().id(FILTER_ID_3).modificationDate(new Date()).equipmentType(EquipmentType.TWO_WINDINGS_TRANSFORMER) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(TWT_ID_4, 5.0), + new IdentifierListFilterEquipmentAttributes(TWT_ID_5, 6.0))) + .build(); + IdentifierListFilter filter4 = IdentifierListFilter.builder().id(FILTER_ID_4).modificationDate(new Date()).equipmentType(EquipmentType.TWO_WINDINGS_TRANSFORMER) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(TWT_ID_4, 5.0), + new IdentifierListFilterEquipmentAttributes(TWT_ID_6, 7.0))) + .build(); + + return List.of(filter1, filter2, filter3, filter4); + } + + @Override + protected List> getAssignmentInfos() { + DoubleAssignmentInfos assignmentInfos1 = DoubleAssignmentInfos.builder() + .filters(List.of(filter1)) + .editedField(TwoWindingsTransformerField.TARGET_V.name()) + .value(2.) + .build(); + + IntegerAssignmentInfos assignmentInfos2 = IntegerAssignmentInfos.builder() + .filters(List.of(filter2)) + .editedField(TwoWindingsTransformerField.RATIO_TAP_POSITION.name()) + .value(4) + .build(); + + IntegerAssignmentInfos assignmentInfos3 = IntegerAssignmentInfos.builder() + .filters(List.of(filter2)) + .editedField(TwoWindingsTransformerField.RATIO_LOW_TAP_POSITION.name()) + .value(4) + .build(); + + DoubleAssignmentInfos assignmentInfos4 = DoubleAssignmentInfos.builder() + .filters(List.of(filter1)) + .editedField(TwoWindingsTransformerField.RATIO_TARGET_DEADBAND.name()) + .value(5.) + .build(); + + DoubleAssignmentInfos assignmentInfos5 = DoubleAssignmentInfos.builder() + .filters(List.of(filter4)) + .editedField(TwoWindingsTransformerField.REGULATION_VALUE.name()) + .value(2.) + .build(); + + IntegerAssignmentInfos assignmentInfos6 = IntegerAssignmentInfos.builder() + .filters(List.of(filter3)) + .editedField(TwoWindingsTransformerField.PHASE_TAP_POSITION.name()) + .value(2) + .build(); + + IntegerAssignmentInfos assignmentInfos7 = IntegerAssignmentInfos.builder() + .filters(List.of(filter3)) + .editedField(TwoWindingsTransformerField.PHASE_LOW_TAP_POSITION.name()) + .value(2) + .build(); + + DoubleAssignmentInfos assignmentInfos8 = DoubleAssignmentInfos.builder() + .filters(List.of(filter4)) + .editedField(TwoWindingsTransformerField.PHASE_TARGET_DEADBAND.name()) + .value(10.) + .build(); + + DoubleAssignmentInfos assignmentInfos9 = DoubleAssignmentInfos.builder() + .filters(List.of(filter1, filter4)) + .editedField(TwoWindingsTransformerField.X.name()) + .value(20.) + .build(); + + DoubleAssignmentInfos assignmentInfos10 = DoubleAssignmentInfos.builder() + .filters(List.of(filter2, filter3)) + .editedField(TwoWindingsTransformerField.R.name()) + .value(2.) + .build(); + + DoubleAssignmentInfos assignmentInfos11 = DoubleAssignmentInfos.builder() + .filters(List.of(filter4, filter2)) + .editedField(TwoWindingsTransformerField.G.name()) + .value(25.) + .build(); + + DoubleAssignmentInfos assignmentInfos12 = DoubleAssignmentInfos.builder() + .filters(List.of(filter1, filter3)) + .editedField(TwoWindingsTransformerField.B.name()) + .value(2.5) + .build(); + + DoubleAssignmentInfos assignmentInfos13 = DoubleAssignmentInfos.builder() + .filters(List.of(filter2)) + .editedField(TwoWindingsTransformerField.RATED_U1.name()) + .value(15.) + .build(); + + DoubleAssignmentInfos assignmentInfos14 = DoubleAssignmentInfos.builder() + .filters(List.of(filter3, filter2)) + .editedField(TwoWindingsTransformerField.RATED_U2.name()) + .value(0.5) + .build(); + + DoubleAssignmentInfos assignmentInfos15 = DoubleAssignmentInfos.builder() + .filters(List.of(filter1, filter2)) + .editedField(TwoWindingsTransformerField.RATED_S.name()) + .value(2.) + .build(); + List> infosList = super.getAssignmentInfos(); + infosList.addAll(List.of(assignmentInfos1, + assignmentInfos2, + assignmentInfos3, + assignmentInfos4, + assignmentInfos5, + assignmentInfos6, + assignmentInfos7, + assignmentInfos8, + assignmentInfos9, + assignmentInfos10, + assignmentInfos11, + assignmentInfos12, + assignmentInfos13, + assignmentInfos14, + assignmentInfos15)); + + return infosList; + } + + @Override + protected List> getUpdatedAssignmentInfos() { + DoubleAssignmentInfos assignmentInfos1 = DoubleAssignmentInfos.builder() + .filters(List.of(filter3)) + .editedField(TwoWindingsTransformerField.TARGET_V.name()) + .value(2.) + .build(); + + IntegerAssignmentInfos assignmentInfos2 = IntegerAssignmentInfos.builder() + .filters(List.of(filter2)) + .editedField(TwoWindingsTransformerField.RATIO_TAP_POSITION.name()) + .value(3) + .build(); + + IntegerAssignmentInfos assignmentInfos3 = IntegerAssignmentInfos.builder() + .filters(List.of(filter1)) + .editedField(TwoWindingsTransformerField.RATIO_LOW_TAP_POSITION.name()) + .value(3) + .build(); + + return List.of(assignmentInfos1, + assignmentInfos2, + assignmentInfos3); + } + + @Override + protected IdentifiableType getIdentifiableType() { + return IdentifiableType.TWO_WINDINGS_TRANSFORMER; + } + + @Override + protected EquipmentType getEquipmentType() { + return EquipmentType.TWO_WINDINGS_TRANSFORMER; + } + + @Override + protected void assertAfterNetworkModificationCreation() { + TwoWindingsTransformer twt1 = getNetwork().getTwoWindingsTransformer(TWT_ID_1); + RatioTapChanger ratioTapChanger1 = twt1.getRatioTapChanger(); + assertNotNull(ratioTapChanger1); + assertEquals(2, ratioTapChanger1.getTargetV(), 0); + assertEquals(4, ratioTapChanger1.getLowTapPosition()); + assertEquals(4, ratioTapChanger1.getTapPosition()); + assertEquals(5, ratioTapChanger1.getTargetDeadband(), 0); + assertEquals(20, twt1.getX(), 0); + assertEquals(2.5, twt1.getB(), 0); + assertEquals(2, twt1.getR(), 0); + assertEquals(25, twt1.getG(), 0); + assertEquals(15, twt1.getRatedU1(), 0); + assertEquals(0.5, twt1.getRatedU2(), 0); + assertEquals(2, twt1.getRatedS(), 0); + + TwoWindingsTransformer twt2 = getNetwork().getTwoWindingsTransformer(TWT_ID_2); + RatioTapChanger ratioTapChanger2 = twt2.getRatioTapChanger(); + assertNotNull(ratioTapChanger2); + assertEquals(2, ratioTapChanger2.getTargetV(), 0); + assertEquals(3, ratioTapChanger2.getLowTapPosition()); + assertEquals(4, ratioTapChanger2.getTapPosition()); + assertEquals(5, ratioTapChanger2.getTargetDeadband(), 0); + assertEquals(20, twt2.getX(), 0); + assertEquals(2.5, twt2.getB(), 0); + assertEquals(15, twt2.getRatedU1(), 0); + assertEquals(2, twt2.getRatedS(), 0); + + TwoWindingsTransformer twt3 = getNetwork().getTwoWindingsTransformer(TWT_ID_3); + RatioTapChanger ratioTapChanger3 = twt3.getRatioTapChanger(); + assertNotNull(ratioTapChanger3); + assertEquals(4, ratioTapChanger3.getLowTapPosition()); + assertEquals(4, ratioTapChanger3.getTapPosition()); + assertEquals(2, twt3.getR(), 0); + assertEquals(25, twt3.getG(), 0); + assertEquals(15, twt3.getRatedU1(), 0); + assertEquals(0.5, twt3.getRatedU2(), 0); + assertEquals(2, twt3.getRatedS(), 0); + + TwoWindingsTransformer twt4 = getNetwork().getTwoWindingsTransformer(TWT_ID_4); + PhaseTapChanger phaseTapChanger4 = twt4.getPhaseTapChanger(); + assertNotNull(phaseTapChanger4); + assertEquals(2, phaseTapChanger4.getRegulationValue(), 0); + assertEquals(2, phaseTapChanger4.getLowTapPosition()); + assertEquals(2, phaseTapChanger4.getTapPosition()); + assertEquals(10, phaseTapChanger4.getTargetDeadband(), 0); + assertEquals(2, twt4.getR(), 0); + assertEquals(20, twt4.getX(), 0); + assertEquals(25, twt4.getG(), 0); + assertEquals(2.5, twt4.getB(), 0); + assertEquals(25, twt4.getRatedU1(), 0); + assertEquals(0.5, twt4.getRatedU2(), 0); + assertEquals(15, twt4.getRatedS(), 0); + + TwoWindingsTransformer twt5 = getNetwork().getTwoWindingsTransformer(TWT_ID_5); + PhaseTapChanger phaseTapChanger5 = twt5.getPhaseTapChanger(); + assertNotNull(phaseTapChanger4); + assertEquals(2, phaseTapChanger5.getLowTapPosition()); + assertEquals(2, phaseTapChanger5.getTapPosition()); + assertEquals(2, twt5.getR(), 0); + assertEquals(2.5, twt5.getB(), 0); + assertEquals(0.5, twt5.getRatedU2(), 0); + + TwoWindingsTransformer twt6 = getNetwork().getTwoWindingsTransformer(TWT_ID_6); + PhaseTapChanger phaseTapChanger6 = twt6.getPhaseTapChanger(); + assertNotNull(phaseTapChanger4); + assertEquals(2, phaseTapChanger6.getRegulationValue(), 0); + assertEquals(10, phaseTapChanger6.getTargetDeadband(), 0); + assertEquals(20, twt6.getX(), 0); + assertEquals(25, twt6.getG(), 0); + } + + @Override + protected void assertAfterNetworkModificationDeletion() { + TwoWindingsTransformer twt1 = getNetwork().getTwoWindingsTransformer(TWT_ID_1); + RatioTapChanger ratioTapChanger1 = twt1.getRatioTapChanger(); + assertNotNull(ratioTapChanger1); + assertEquals(50, ratioTapChanger1.getTargetV(), 0); + assertEquals(0, ratioTapChanger1.getLowTapPosition()); + assertEquals(1, ratioTapChanger1.getTapPosition()); + assertEquals(55, ratioTapChanger1.getTargetDeadband(), 0); + assertEquals(40, twt1.getX(), 0); + assertEquals(60, twt1.getB(), 0); + assertEquals(30, twt1.getR(), 0); + assertEquals(50, twt1.getG(), 0); + assertEquals(10, twt1.getRatedU1(), 0); + assertEquals(20, twt1.getRatedU2(), 0); + assertEquals(11, twt1.getRatedS(), 0); + + TwoWindingsTransformer twt2 = getNetwork().getTwoWindingsTransformer(TWT_ID_2); + RatioTapChanger ratioTapChanger2 = twt2.getRatioTapChanger(); + assertNotNull(ratioTapChanger2); + assertEquals(53, ratioTapChanger2.getTargetV(), 0); + assertEquals(3, ratioTapChanger2.getLowTapPosition()); + assertEquals(4, ratioTapChanger2.getTapPosition()); + assertEquals(58, ratioTapChanger2.getTargetDeadband(), 0); + assertEquals(45, twt2.getX(), 0); + assertEquals(65, twt2.getB(), 0); + assertEquals(15, twt2.getRatedU1(), 0); + assertEquals(10, twt2.getRatedS(), 0); + + TwoWindingsTransformer twt3 = getNetwork().getTwoWindingsTransformer(TWT_ID_3); + RatioTapChanger ratioTapChanger3 = twt3.getRatioTapChanger(); + assertNotNull(ratioTapChanger3); + assertEquals(0, ratioTapChanger3.getLowTapPosition()); + assertEquals(1, ratioTapChanger3.getTapPosition()); + assertEquals(40, twt3.getR(), 0); + assertEquals(60, twt3.getG(), 0); + assertEquals(20, twt3.getRatedU1(), 0); + assertEquals(30, twt3.getRatedU2(), 0); + assertEquals(25, twt3.getRatedS(), 0); + + TwoWindingsTransformer twt4 = getNetwork().getTwoWindingsTransformer(TWT_ID_4); + PhaseTapChanger phaseTapChanger4 = twt4.getPhaseTapChanger(); + assertNotNull(phaseTapChanger4); + assertEquals(45, phaseTapChanger4.getRegulationValue(), 0); + assertEquals(1, phaseTapChanger4.getLowTapPosition()); + assertEquals(2, phaseTapChanger4.getTapPosition()); + assertEquals(34, phaseTapChanger4.getTargetDeadband(), 0); + assertEquals(45, twt4.getR(), 0); + assertEquals(55, twt4.getX(), 0); + assertEquals(65, twt4.getG(), 0); + assertEquals(75, twt4.getB(), 0); + assertEquals(25, twt4.getRatedU1(), 0); + assertEquals(35, twt4.getRatedU2(), 0); + assertEquals(15, twt4.getRatedS(), 0); + + TwoWindingsTransformer twt5 = getNetwork().getTwoWindingsTransformer(TWT_ID_5); + PhaseTapChanger phaseTapChanger5 = twt5.getPhaseTapChanger(); + assertNotNull(phaseTapChanger4); + assertEquals(2, phaseTapChanger5.getLowTapPosition()); + assertEquals(2, phaseTapChanger5.getTapPosition()); + assertEquals(50, twt5.getR(), 0); + assertEquals(80, twt5.getB(), 0); + assertEquals(40, twt5.getRatedU2(), 0); + + TwoWindingsTransformer twt6 = getNetwork().getTwoWindingsTransformer(TWT_ID_6); + PhaseTapChanger phaseTapChanger6 = twt6.getPhaseTapChanger(); + assertNotNull(phaseTapChanger4); + assertEquals(47, phaseTapChanger6.getRegulationValue(), 0); + assertEquals(36, phaseTapChanger6.getTargetDeadband(), 0); + assertEquals(65, twt6.getX(), 0); + assertEquals(75, twt6.getG(), 0); + } + + private void addRatioTapChangerSteps(RatioTapChangerAdder ratioTapChangerAdder) { + ratioTapChangerAdder.beginStep() + .setR(39.78473) + .setX(39.784725) + .setG(0.0) + .setB(0.0) + .setRho(15.0) + .endStep() + .beginStep() + .setR(39.78474) + .setX(39.784726) + .setG(0.0) + .setB(0.0) + .setRho(15.0) + .endStep() + .beginStep() + .setR(39.78473) + .setX(39.784725) + .setG(0.0) + .setB(0.0) + .setRho(15.0) + .endStep() + .beginStep() + .setR(39.78474) + .setX(39.784726) + .setG(0.0) + .setB(0.0) + .setRho(15.0) + .endStep() + .beginStep() + .setR(39.78473) + .setX(39.784725) + .setG(0.0) + .setB(0.0) + .setRho(5.0) + .endStep() + .beginStep() + .setR(39.78474) + .setX(39.784726) + .setG(0.0) + .setB(0.0) + .setRho(15.0) + .endStep() + .add(); + } + + private void addPhaseTapChangerSteps(PhaseTapChangerAdder phaseTapChangerAdder) { + phaseTapChangerAdder.beginStep() + .setR(39.78473) + .setX(39.784725) + .setG(0.0) + .setB(0.0) + .setRho(15.0) + .setAlpha(1.) + .endStep() + .beginStep() + .setR(39.78475) + .setX(39.784727) + .setG(0.0) + .setB(0.0) + .setRho(15.0) + .setAlpha(1.1) + .endStep() + .beginStep() + .setR(39.78473) + .setX(39.784725) + .setG(0.0) + .setB(0.0) + .setRho(15.0) + .setAlpha(1.) + .endStep() + .beginStep() + .setR(39.78475) + .setX(39.784727) + .setG(0.0) + .setB(0.0) + .setRho(15.0) + .setAlpha(1.1) + .endStep() + .beginStep() + .setR(39.78473) + .setX(39.784725) + .setG(0.0) + .setB(0.0) + .setRho(15.0) + .setAlpha(1.) + .endStep() + .beginStep() + .setR(39.78475) + .setX(39.784727) + .setG(0.0) + .setB(0.0) + .setRho(15.0) + .setAlpha(1.1) + .endStep() + .add(); + } +} diff --git a/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/VoltageLevelModificationByAssignmentTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/VoltageLevelModificationByAssignmentTest.java new file mode 100644 index 000000000..4e105be3c --- /dev/null +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/assignment/VoltageLevelModificationByAssignmentTest.java @@ -0,0 +1,225 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.modification.server.modifications.byfilter.assignment; + +import com.powsybl.iidm.network.IdentifiableType; +import com.powsybl.iidm.network.VoltageLevel; +import com.powsybl.iidm.network.extensions.IdentifiableShortCircuit; +import com.powsybl.iidm.network.extensions.IdentifiableShortCircuitAdder; +import org.gridsuite.filter.AbstractFilter; +import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter; +import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes; +import org.gridsuite.filter.utils.EquipmentType; +import org.gridsuite.modification.server.dto.byfilter.assignment.AssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.assignment.DoubleAssignmentInfos; +import org.gridsuite.modification.server.dto.byfilter.equipmentfield.VoltageLevelField; + +import java.util.Date; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Thang PHAM + */ +public class VoltageLevelModificationByAssignmentTest extends AbstractModificationByAssignmentTest { + private static final String VOLTAGE_LEVEL_ID_1 = "v1"; + private static final String VOLTAGE_LEVEL_ID_2 = "v2"; + private static final String VOLTAGE_LEVEL_ID_3 = "v3"; + private static final String VOLTAGE_LEVEL_ID_4 = "v4"; + private static final String VOLTAGE_LEVEL_ID_5 = "v5"; + private static final String VOLTAGE_LEVEL_ID_6 = "v6"; + + @Override + protected void createEquipments() { + getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_1).setNominalV(400) + .setHighVoltageLimit(200) + .setLowVoltageLimit(100) + .newExtension(IdentifiableShortCircuitAdder.class).withIpMin(10).withIpMax(120).add(); + + getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_2).setNominalV(150) + .setLowVoltageLimit(100) + .setHighVoltageLimit(1000) + .newExtension(IdentifiableShortCircuitAdder.class).withIpMin(10).withIpMax(120).add(); + + getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_3).setNominalV(70) + .setLowVoltageLimit(50) + .setHighVoltageLimit(250) + .newExtension(IdentifiableShortCircuitAdder.class).withIpMin(50).withIpMax(150).add(); + + getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_4).setNominalV(100) + .setLowVoltageLimit(70) + .setHighVoltageLimit(300) + .newExtension(IdentifiableShortCircuitAdder.class).withIpMin(10).withIpMax(100).add(); + + getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_5).setNominalV(210) + .setLowVoltageLimit(10) + .setHighVoltageLimit(500) + .newExtension(IdentifiableShortCircuitAdder.class).withIpMin(25).withIpMax(75).add(); + + getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_6).setNominalV(750) + .setHighVoltageLimit(1000) + .setLowVoltageLimit(90) + .newExtension(IdentifiableShortCircuitAdder.class).withIpMin(100).withIpMax(200).add(); + } + + @Override + protected List getTestFilters() { + IdentifierListFilter filter1 = IdentifierListFilter.builder().id(FILTER_ID_1).modificationDate(new Date()).equipmentType(EquipmentType.VOLTAGE_LEVEL) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(VOLTAGE_LEVEL_ID_1, 1.0), + new IdentifierListFilterEquipmentAttributes(VOLTAGE_LEVEL_ID_2, 2.0))) + .build(); + IdentifierListFilter filter2 = IdentifierListFilter.builder().id(FILTER_ID_2).modificationDate(new Date()).equipmentType(EquipmentType.VOLTAGE_LEVEL) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(VOLTAGE_LEVEL_ID_3, 2.0), + new IdentifierListFilterEquipmentAttributes(VOLTAGE_LEVEL_ID_4, 5.0))) + .build(); + IdentifierListFilter filter3 = IdentifierListFilter.builder().id(FILTER_ID_3).modificationDate(new Date()).equipmentType(EquipmentType.VOLTAGE_LEVEL) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(VOLTAGE_LEVEL_ID_5, 6.0), + new IdentifierListFilterEquipmentAttributes(VOLTAGE_LEVEL_ID_6, 7.0))) + .build(); + IdentifierListFilter filter4 = IdentifierListFilter.builder().id(FILTER_ID_4).modificationDate(new Date()).equipmentType(EquipmentType.VOLTAGE_LEVEL) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(VOLTAGE_LEVEL_ID_2, 2.0), + new IdentifierListFilterEquipmentAttributes(VOLTAGE_LEVEL_ID_5, 6.0))) + .build(); + IdentifierListFilter filter5 = IdentifierListFilter.builder().id(FILTER_ID_5).modificationDate(new Date()).equipmentType(EquipmentType.VOLTAGE_LEVEL) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(VOLTAGE_LEVEL_ID_4, 5.0), + new IdentifierListFilterEquipmentAttributes(VOLTAGE_LEVEL_ID_6, 7.0))) + .build(); + + return List.of(filter1, filter2, filter3, filter4, filter5); + } + + @Override + protected List> getAssignmentInfos() { + DoubleAssignmentInfos assignmentInfos1 = DoubleAssignmentInfos.builder() + .editedField(VoltageLevelField.LOW_VOLTAGE_LIMIT.name()) + .value(10.) + .filters(List.of(filter1, filter2)) + .build(); + + DoubleAssignmentInfos assignmentInfos2 = DoubleAssignmentInfos.builder() + .editedField(VoltageLevelField.HIGH_VOLTAGE_LIMIT.name()) + .value(120.) + .filters(List.of(filter3)) + .build(); + + DoubleAssignmentInfos assignmentInfos3 = DoubleAssignmentInfos.builder() + .editedField(VoltageLevelField.NOMINAL_VOLTAGE.name()) + .value(150.) + .filters(List.of(filter4)) + .build(); + + DoubleAssignmentInfos assignmentInfos4 = DoubleAssignmentInfos.builder() + .editedField(VoltageLevelField.LOW_SHORT_CIRCUIT_CURRENT_LIMIT.name()) + .value(2.) + .filters(List.of(filter5)) + .build(); + + DoubleAssignmentInfos assignmentInfos5 = DoubleAssignmentInfos.builder() + .editedField(VoltageLevelField.HIGH_SHORT_CIRCUIT_CURRENT_LIMIT.name()) + .value(5.) + .filters(List.of(filter4, filter5)) + .build(); + + return List.of(assignmentInfos1, assignmentInfos2, assignmentInfos3, assignmentInfos4, assignmentInfos5); + } + + @Override + protected List> getUpdatedAssignmentInfos() { + DoubleAssignmentInfos assignmentInfos1 = DoubleAssignmentInfos.builder() + .editedField(VoltageLevelField.LOW_VOLTAGE_LIMIT.name()) + .value(5.) + .filters(List.of(filter1, filter2)) + .build(); + + DoubleAssignmentInfos assignmentInfos2 = DoubleAssignmentInfos.builder() + .editedField(VoltageLevelField.HIGH_VOLTAGE_LIMIT.name()) + .value(1.5) + .filters(List.of(filter3)) + .build(); + + DoubleAssignmentInfos assignmentInfos3 = DoubleAssignmentInfos.builder() + .editedField(VoltageLevelField.NOMINAL_VOLTAGE.name()) + .value(150.) + .filters(List.of(filter4)) + .build(); + + List> infosList = super.getAssignmentInfos(); + infosList.addAll(List.of(assignmentInfos1, assignmentInfos2, assignmentInfos3)); + + return infosList; + } + + @Override + protected IdentifiableType getIdentifiableType() { + return IdentifiableType.VOLTAGE_LEVEL; + } + + @Override + protected EquipmentType getEquipmentType() { + return EquipmentType.VOLTAGE_LEVEL; + } + + @Override + protected void assertAfterNetworkModificationCreation() { + assertEquals(10, getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_1).getLowVoltageLimit(), 0); + assertEquals(10, getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_2).getLowVoltageLimit(), 0); + assertEquals(10, getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_3).getLowVoltageLimit(), 0); + + VoltageLevel voltageLevel4 = getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_4); + IdentifiableShortCircuit identifiableShortCircuit4 = voltageLevel4.getExtension(IdentifiableShortCircuit.class); + assertNotNull(identifiableShortCircuit4); + assertEquals(10, voltageLevel4.getLowVoltageLimit(), 0); + assertEquals(2, identifiableShortCircuit4.getIpMin(), 0); + assertEquals(5, identifiableShortCircuit4.getIpMax(), 0); + + VoltageLevel voltageLevel5 = getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_5); + IdentifiableShortCircuit identifiableShortCircuit5 = voltageLevel5.getExtension(IdentifiableShortCircuit.class); + assertNotNull(identifiableShortCircuit5); + assertEquals(120, voltageLevel5.getHighVoltageLimit(), 0); + assertEquals(150, voltageLevel5.getNominalV(), 0); + assertEquals(5, identifiableShortCircuit5.getIpMax(), 0); + + VoltageLevel voltageLevel6 = getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_6); + IdentifiableShortCircuit identifiableShortCircuit6 = voltageLevel6.getExtension(IdentifiableShortCircuit.class); + assertNotNull(identifiableShortCircuit6); + assertEquals(120, voltageLevel6.getHighVoltageLimit(), 0); + assertEquals(2, identifiableShortCircuit6.getIpMin(), 0); + assertEquals(5, identifiableShortCircuit6.getIpMax(), 0); + } + + @Override + protected void assertAfterNetworkModificationDeletion() { + assertEquals(100, getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_1).getLowVoltageLimit(), 0); + assertEquals(100, getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_2).getLowVoltageLimit(), 0); + assertEquals(250, getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_3).getHighVoltageLimit(), 0); + + VoltageLevel voltageLevel4 = getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_4); + IdentifiableShortCircuit identifiableShortCircuit4 = voltageLevel4.getExtension(IdentifiableShortCircuit.class); + assertNotNull(identifiableShortCircuit4); + assertEquals(300, voltageLevel4.getHighVoltageLimit(), 0); + assertEquals(10, identifiableShortCircuit4.getIpMin(), 0); + assertEquals(100, identifiableShortCircuit4.getIpMax(), 0); + + VoltageLevel voltageLevel5 = getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_5); + IdentifiableShortCircuit identifiableShortCircuit5 = voltageLevel5.getExtension(IdentifiableShortCircuit.class); + assertNotNull(identifiableShortCircuit5); + assertEquals(500, voltageLevel5.getHighVoltageLimit(), 0); + assertEquals(210, voltageLevel5.getNominalV(), 0); + assertEquals(75, identifiableShortCircuit5.getIpMax(), 0); + + VoltageLevel voltageLevel6 = getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_6); + IdentifiableShortCircuit identifiableShortCircuit6 = voltageLevel6.getExtension(IdentifiableShortCircuit.class); + assertNotNull(identifiableShortCircuit6); + assertEquals(1000, voltageLevel6.getHighVoltageLimit(), 0); + assertEquals(100, identifiableShortCircuit6.getIpMin(), 0); + assertEquals(200, identifiableShortCircuit6.getIpMax(), 0); + } + +} diff --git a/src/test/java/org/gridsuite/modification/server/modifications/AbstractByFormulaModificationTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/AbstractByFormulaModificationTest.java similarity index 96% rename from src/test/java/org/gridsuite/modification/server/modifications/AbstractByFormulaModificationTest.java rename to src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/AbstractByFormulaModificationTest.java index 650e80d9a..355ed6f17 100644 --- a/src/test/java/org/gridsuite/modification/server/modifications/AbstractByFormulaModificationTest.java +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/AbstractByFormulaModificationTest.java @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.gridsuite.modification.server.modifications; +package org.gridsuite.modification.server.modifications.byfilter.formula; import com.fasterxml.jackson.core.type.TypeReference; import com.github.tomakehurst.wiremock.client.WireMock; @@ -19,10 +19,11 @@ import org.gridsuite.modification.server.dto.ByFormulaModificationInfos; import org.gridsuite.modification.server.dto.FilterInfos; import org.gridsuite.modification.server.dto.NetworkModificationResult; -import org.gridsuite.modification.server.dto.formula.FormulaInfos; -import org.gridsuite.modification.server.dto.formula.Operator; -import org.gridsuite.modification.server.dto.formula.ReferenceFieldOrValue; +import org.gridsuite.modification.server.dto.byfilter.formula.FormulaInfos; +import org.gridsuite.modification.server.dto.byfilter.formula.Operator; +import org.gridsuite.modification.server.dto.byfilter.formula.ReferenceFieldOrValue; import org.gridsuite.modification.server.impacts.AbstractBaseImpact; +import org.gridsuite.modification.server.modifications.AbstractNetworkModificationTest; import org.gridsuite.modification.server.service.FilterService; import org.gridsuite.modification.server.utils.NetworkCreation; import org.junit.Before; @@ -264,8 +265,8 @@ Map handleQueryParams(List filterIds) { return Map.of("ids", WireMock.matching(filterIds.stream().map(uuid -> ".+").collect(Collectors.joining(",")))); } - String getPath(boolean isRegexPhat) { - if (isRegexPhat) { + String getPath(boolean isRegexPath) { + if (isRegexPath) { return "/v1/filters/metadata\\?ids="; } return "/v1/filters/metadata?ids="; diff --git a/src/test/java/org/gridsuite/modification/server/modifications/BatteryByFormulaModificationTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/BatteryByFormulaModificationTest.java similarity index 96% rename from src/test/java/org/gridsuite/modification/server/modifications/BatteryByFormulaModificationTest.java rename to src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/BatteryByFormulaModificationTest.java index c6f9d91f0..34eb4f325 100644 --- a/src/test/java/org/gridsuite/modification/server/modifications/BatteryByFormulaModificationTest.java +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/BatteryByFormulaModificationTest.java @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.gridsuite.modification.server.modifications; +package org.gridsuite.modification.server.modifications.byfilter.formula; import com.powsybl.iidm.network.IdentifiableType; import com.powsybl.iidm.network.extensions.ActivePowerControl; @@ -14,10 +14,10 @@ import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter; import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes; import org.gridsuite.filter.utils.EquipmentType; -import org.gridsuite.modification.server.dto.formula.FormulaInfos; -import org.gridsuite.modification.server.dto.formula.Operator; -import org.gridsuite.modification.server.dto.formula.ReferenceFieldOrValue; -import org.gridsuite.modification.server.dto.formula.equipmentfield.BatteryField; +import org.gridsuite.modification.server.dto.byfilter.formula.FormulaInfos; +import org.gridsuite.modification.server.dto.byfilter.formula.Operator; +import org.gridsuite.modification.server.dto.byfilter.formula.ReferenceFieldOrValue; +import org.gridsuite.modification.server.dto.byfilter.equipmentfield.BatteryField; import org.junit.Test; import java.util.Date; diff --git a/src/test/java/org/gridsuite/modification/server/modifications/GeneratorByFormulaModificationTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/GeneratorByFormulaModificationTest.java similarity index 98% rename from src/test/java/org/gridsuite/modification/server/modifications/GeneratorByFormulaModificationTest.java rename to src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/GeneratorByFormulaModificationTest.java index ae5b98b1b..d841030bc 100644 --- a/src/test/java/org/gridsuite/modification/server/modifications/GeneratorByFormulaModificationTest.java +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/GeneratorByFormulaModificationTest.java @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.gridsuite.modification.server.modifications; +package org.gridsuite.modification.server.modifications.byfilter.formula; import com.powsybl.iidm.network.Generator; import com.powsybl.iidm.network.IdentifiableType; @@ -23,10 +23,10 @@ import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes; import org.gridsuite.filter.utils.EquipmentType; import org.gridsuite.modification.server.dto.FilterInfos; -import org.gridsuite.modification.server.dto.formula.FormulaInfos; -import org.gridsuite.modification.server.dto.formula.Operator; -import org.gridsuite.modification.server.dto.formula.ReferenceFieldOrValue; -import org.gridsuite.modification.server.dto.formula.equipmentfield.GeneratorField; +import org.gridsuite.modification.server.dto.byfilter.formula.FormulaInfos; +import org.gridsuite.modification.server.dto.byfilter.formula.Operator; +import org.gridsuite.modification.server.dto.byfilter.formula.ReferenceFieldOrValue; +import org.gridsuite.modification.server.dto.byfilter.equipmentfield.GeneratorField; import org.junit.Test; import org.junit.jupiter.api.Tag; diff --git a/src/test/java/org/gridsuite/modification/server/modifications/LoadByFormulaModificationTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/LoadByFormulaModificationTest.java similarity index 85% rename from src/test/java/org/gridsuite/modification/server/modifications/LoadByFormulaModificationTest.java rename to src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/LoadByFormulaModificationTest.java index e765bf8eb..47e333d41 100644 --- a/src/test/java/org/gridsuite/modification/server/modifications/LoadByFormulaModificationTest.java +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/LoadByFormulaModificationTest.java @@ -5,22 +5,25 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.gridsuite.modification.server.modifications; +package org.gridsuite.modification.server.modifications.byfilter.formula; import com.powsybl.iidm.network.IdentifiableType; import org.gridsuite.filter.AbstractFilter; import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter; import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes; import org.gridsuite.filter.utils.EquipmentType; -import org.gridsuite.modification.server.dto.formula.FormulaInfos; -import org.gridsuite.modification.server.dto.formula.Operator; -import org.gridsuite.modification.server.dto.formula.ReferenceFieldOrValue; -import org.gridsuite.modification.server.dto.formula.equipmentfield.LoadField; +import org.gridsuite.modification.server.dto.byfilter.equipmentfield.LoadField; +import org.gridsuite.modification.server.dto.byfilter.formula.FormulaInfos; +import org.gridsuite.modification.server.dto.byfilter.formula.Operator; +import org.gridsuite.modification.server.dto.byfilter.formula.ReferenceFieldOrValue; import org.gridsuite.modification.server.impacts.AbstractBaseImpact; import java.util.Date; import java.util.List; +import java.util.Set; +import static org.assertj.core.api.Assertions.assertThat; +import static org.gridsuite.modification.server.Impacts.TestImpactUtils.createSubstationImpacts; import static org.gridsuite.modification.server.utils.NetworkUtil.createLoad; import static org.junit.Assert.assertEquals; @@ -114,6 +117,8 @@ protected void assertAfterNetworkModificationDeletion() { @Override protected void assertResultImpacts(List impacts) { - // TODO later + // NOTE: this assert is based on the return of NetworkStoreListener#reduceNetworkImpacts() + // since the test network has only 4 loads which are less than the collectionThreshold 5 + assertThat(impacts).containsAll(createSubstationImpacts(Set.of("s1", "s2"))); } } diff --git a/src/test/java/org/gridsuite/modification/server/modifications/ShuntCompensatorByFormulaModificationTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/ShuntCompensatorByFormulaModificationTest.java similarity index 96% rename from src/test/java/org/gridsuite/modification/server/modifications/ShuntCompensatorByFormulaModificationTest.java rename to src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/ShuntCompensatorByFormulaModificationTest.java index 641b98be0..215c528b6 100644 --- a/src/test/java/org/gridsuite/modification/server/modifications/ShuntCompensatorByFormulaModificationTest.java +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/ShuntCompensatorByFormulaModificationTest.java @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.gridsuite.modification.server.modifications; +package org.gridsuite.modification.server.modifications.byfilter.formula; import com.powsybl.iidm.network.IdentifiableType; import com.powsybl.iidm.network.ShuntCompensator; @@ -15,10 +15,10 @@ import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter; import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes; import org.gridsuite.filter.utils.EquipmentType; -import org.gridsuite.modification.server.dto.formula.FormulaInfos; -import org.gridsuite.modification.server.dto.formula.Operator; -import org.gridsuite.modification.server.dto.formula.ReferenceFieldOrValue; -import org.gridsuite.modification.server.dto.formula.equipmentfield.ShuntCompensatorField; +import org.gridsuite.modification.server.dto.byfilter.formula.FormulaInfos; +import org.gridsuite.modification.server.dto.byfilter.formula.Operator; +import org.gridsuite.modification.server.dto.byfilter.formula.ReferenceFieldOrValue; +import org.gridsuite.modification.server.dto.byfilter.equipmentfield.ShuntCompensatorField; import org.junit.Test; import java.util.Date; diff --git a/src/test/java/org/gridsuite/modification/server/modifications/TwoWindingsTransformerByFormulaModificationTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/TwoWindingsTransformerByFormulaModificationTest.java similarity index 98% rename from src/test/java/org/gridsuite/modification/server/modifications/TwoWindingsTransformerByFormulaModificationTest.java rename to src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/TwoWindingsTransformerByFormulaModificationTest.java index 633bf98ba..c6c1a84ec 100644 --- a/src/test/java/org/gridsuite/modification/server/modifications/TwoWindingsTransformerByFormulaModificationTest.java +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/TwoWindingsTransformerByFormulaModificationTest.java @@ -1,4 +1,4 @@ -package org.gridsuite.modification.server.modifications; +package org.gridsuite.modification.server.modifications.byfilter.formula; import com.github.tomakehurst.wiremock.client.WireMock; import com.powsybl.iidm.network.IdentifiableType; @@ -15,10 +15,10 @@ import org.gridsuite.filter.utils.EquipmentType; import org.gridsuite.modification.server.dto.ByFormulaModificationInfos; import org.gridsuite.modification.server.dto.NetworkModificationResult; -import org.gridsuite.modification.server.dto.formula.FormulaInfos; -import org.gridsuite.modification.server.dto.formula.Operator; -import org.gridsuite.modification.server.dto.formula.ReferenceFieldOrValue; -import org.gridsuite.modification.server.dto.formula.equipmentfield.TwoWindingsTransformerField; +import org.gridsuite.modification.server.dto.byfilter.formula.FormulaInfos; +import org.gridsuite.modification.server.dto.byfilter.formula.Operator; +import org.gridsuite.modification.server.dto.byfilter.formula.ReferenceFieldOrValue; +import org.gridsuite.modification.server.dto.byfilter.equipmentfield.TwoWindingsTransformerField; import org.junit.Test; import java.util.Date; diff --git a/src/test/java/org/gridsuite/modification/server/modifications/VoltageLevelByFormulaModificationTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/VoltageLevelByFormulaModificationTest.java similarity index 94% rename from src/test/java/org/gridsuite/modification/server/modifications/VoltageLevelByFormulaModificationTest.java rename to src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/VoltageLevelByFormulaModificationTest.java index 44146aba6..fd73c32fd 100644 --- a/src/test/java/org/gridsuite/modification/server/modifications/VoltageLevelByFormulaModificationTest.java +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilter/formula/VoltageLevelByFormulaModificationTest.java @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.gridsuite.modification.server.modifications; +package org.gridsuite.modification.server.modifications.byfilter.formula; import com.powsybl.iidm.network.IdentifiableType; import com.powsybl.iidm.network.TopologyKind; @@ -16,19 +16,18 @@ import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter; import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes; import org.gridsuite.filter.utils.EquipmentType; -import org.gridsuite.modification.server.dto.formula.FormulaInfos; -import org.gridsuite.modification.server.dto.formula.Operator; -import org.gridsuite.modification.server.dto.formula.ReferenceFieldOrValue; -import org.gridsuite.modification.server.dto.formula.equipmentfield.VoltageLevelField; +import org.gridsuite.modification.server.dto.byfilter.equipmentfield.VoltageLevelField; +import org.gridsuite.modification.server.dto.byfilter.formula.FormulaInfos; +import org.gridsuite.modification.server.dto.byfilter.formula.Operator; +import org.gridsuite.modification.server.dto.byfilter.formula.ReferenceFieldOrValue; import java.util.Date; import java.util.List; -import static org.gridsuite.modification.server.modifications.ByFormulaModification.EQUIPMENT_MODIFIED_REPORT_ERROR; +import static org.gridsuite.modification.server.modifications.byfilter.AbstractModificationByAssignment.REPORT_KEY_BY_FILTER_MODIFICATION_SOME; +import static org.gridsuite.modification.server.modifications.byfilter.ByFormulaModification.REPORT_KEY_EQUIPMENT_MODIFIED_ERROR; import static org.gridsuite.modification.server.utils.TestUtils.assertLogMessageWithoutRank; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; /** * @author Seddik Yengui @@ -242,8 +241,8 @@ protected void assertAfterNetworkModificationCreation() { assertTrue(Double.isNaN(getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_7).getLowVoltageLimit())); assertTrue(Double.isNaN(getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_7).getHighVoltageLimit())); - assertLogMessageWithoutRank("Cannot modify equipment v7 : At least one of the value or referenced field is null", EQUIPMENT_MODIFIED_REPORT_ERROR + "0", reportService); - assertLogMessageWithoutRank("Some of the equipment have been modified : 14 equipment(s) modified and 4 equipment(s) not modified", "byFormulaModificationSome", reportService); + assertLogMessageWithoutRank("Cannot modify equipment v7 : At least one of the value or referenced field is null", REPORT_KEY_EQUIPMENT_MODIFIED_ERROR, reportService); + assertLogMessageWithoutRank("Some of the equipment have been modified : 14 equipment(s) modified and 4 equipment(s) not modified", REPORT_KEY_BY_FILTER_MODIFICATION_SOME, reportService); } @Override