diff --git a/pom.xml b/pom.xml index 7359947bc..2d4f69a8a 100644 --- a/pom.xml +++ b/pom.xml @@ -221,7 +221,11 @@ powsybl-config-test test - + + com.powsybl + powsybl-commons-test + test + org.springframework.boot spring-boot-starter-test diff --git a/src/main/java/org/gridsuite/modification/server/RestTemplateConfig.java b/src/main/java/org/gridsuite/modification/server/RestTemplateConfig.java new file mode 100644 index 000000000..3d9392551 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/RestTemplateConfig.java @@ -0,0 +1,31 @@ +/** + * 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; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.gridsuite.modification.server.json.ModificationInfosJsonModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +/** + * @author Slimane Amar + */ +@Configuration +public class RestTemplateConfig { + private ObjectMapper createObjectMapper() { + var objectMapper = Jackson2ObjectMapperBuilder.json().build(); + objectMapper.registerModule(new ModificationInfosJsonModule()); + return objectMapper; + } + + @Bean + public ObjectMapper objectMapper() { + return createObjectMapper(); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/dto/HvdcLccDeletionInfos.java b/src/main/java/org/gridsuite/modification/server/dto/HvdcLccDeletionInfos.java index 22ac4cb1a..77a17f83a 100644 --- a/src/main/java/org/gridsuite/modification/server/dto/HvdcLccDeletionInfos.java +++ b/src/main/java/org/gridsuite/modification/server/dto/HvdcLccDeletionInfos.java @@ -12,6 +12,7 @@ import org.gridsuite.modification.server.entities.equipment.deletion.AbstractEquipmentDeletionEntity; import org.gridsuite.modification.server.entities.equipment.deletion.HvdcLccDeletionEntity; import org.gridsuite.modification.server.entities.equipment.deletion.ShuntCompensatorSelectionEmbeddable; + import java.util.List; import java.util.stream.Collectors; @@ -27,6 +28,8 @@ public class HvdcLccDeletionInfos extends AbstractEquipmentDeletionInfos { @Builder @Getter + @NoArgsConstructor + @AllArgsConstructor public static class ShuntCompensatorInfos { private String id; private boolean connectedToHvdc; 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 c47cbe181..c27cbf0b3 100644 --- a/src/main/java/org/gridsuite/modification/server/dto/ModificationInfos.java +++ b/src/main/java/org/gridsuite/modification/server/dto/ModificationInfos.java @@ -77,6 +77,8 @@ @ToString @Schema(description = "Modification attributes") public class ModificationInfos { + public static final String VERSION = "1.0"; + @Schema(description = "Modification id") private UUID uuid; diff --git a/src/main/java/org/gridsuite/modification/server/dto/NetworkModificationResult.java b/src/main/java/org/gridsuite/modification/server/dto/NetworkModificationResult.java index 664a11e9c..95fe8c051 100644 --- a/src/main/java/org/gridsuite/modification/server/dto/NetworkModificationResult.java +++ b/src/main/java/org/gridsuite/modification/server/dto/NetworkModificationResult.java @@ -7,8 +7,7 @@ package org.gridsuite.modification.server.dto; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Builder; -import lombok.Data; +import lombok.*; import org.gridsuite.modification.server.impacts.SimpleElementImpact; import java.util.List; @@ -20,7 +19,10 @@ * @author Slimane Amar */ @Builder -@Data +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor @Schema(description = "Network modification result") public class NetworkModificationResult { public enum ApplicationStatus { diff --git a/src/main/java/org/gridsuite/modification/server/json/AbstractBasicEquipmentModificationInfosDeserializer.java b/src/main/java/org/gridsuite/modification/server/json/AbstractBasicEquipmentModificationInfosDeserializer.java new file mode 100644 index 000000000..3194c85aa --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/AbstractBasicEquipmentModificationInfosDeserializer.java @@ -0,0 +1,35 @@ +/** + * 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.json; + +import com.fasterxml.jackson.core.JsonParser; +import org.gridsuite.modification.server.dto.BasicEquipmentModificationInfos; + +import java.io.IOException; + +/** + * @author Slimane Amar + */ +public abstract class AbstractBasicEquipmentModificationInfosDeserializer extends AbstractEquipmentModificationInfosDeserializer { + + protected transient AttributeModificationInfosDeserializer attributeModificationInfosDeserializer = new AttributeModificationInfosDeserializer(); + + protected AbstractBasicEquipmentModificationInfosDeserializer(final Class t) { + super(t); + } + + protected void deserializeAttribute(BasicEquipmentModificationInfos modificationInfos, JsonParser parser) throws IOException { + switch (parser.getCurrentName()) { + case "equipmentName": + modificationInfos.setEquipmentName(attributeModificationInfosDeserializer.deserialize(parser, String.class)); + break; + + default: + super.deserializeAttribute(modificationInfos, parser); + } + } +} diff --git a/src/main/java/org/gridsuite/modification/server/json/AbstractBasicEquipmentModificationInfosSerializer.java b/src/main/java/org/gridsuite/modification/server/json/AbstractBasicEquipmentModificationInfosSerializer.java new file mode 100644 index 000000000..0fee74283 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/AbstractBasicEquipmentModificationInfosSerializer.java @@ -0,0 +1,30 @@ +/** + * 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.json; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import org.gridsuite.modification.server.dto.BasicEquipmentModificationInfos; + +import java.io.IOException; + +/** + * @author Slimane Amar + */ +public abstract class AbstractBasicEquipmentModificationInfosSerializer extends AbstractEquipmentModificationInfosSerializer { + protected final transient AttributeModificationInfosSerializer attributeSerializer = new AttributeModificationInfosSerializer(); + + protected AbstractBasicEquipmentModificationInfosSerializer(final Class t) { + super(t); + } + + @Override + public void serialize(T modification, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + super.serialize(modification, jsonGenerator, serializerProvider); + attributeSerializer.serialize("equipmentName", modification.getEquipmentName(), jsonGenerator); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/json/AbstractEquipmentModificationInfosDeserializer.java b/src/main/java/org/gridsuite/modification/server/json/AbstractEquipmentModificationInfosDeserializer.java new file mode 100644 index 000000000..379756f9c --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/AbstractEquipmentModificationInfosDeserializer.java @@ -0,0 +1,33 @@ +/** + * 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.json; + +import com.fasterxml.jackson.core.JsonParser; +import org.gridsuite.modification.server.dto.EquipmentModificationInfos; + +import java.io.IOException; + +/** + * @author Slimane Amar + */ +public abstract class AbstractEquipmentModificationInfosDeserializer extends AbstractModificationInfosDeserializer { + protected AbstractEquipmentModificationInfosDeserializer(final Class t) { + super(t); + } + + protected void deserializeAttribute(EquipmentModificationInfos modificationInfos, JsonParser parser) throws IOException { + switch (parser.getCurrentName()) { + case "equipmentId": + parser.nextToken(); + modificationInfos.setEquipmentId(parser.getValueAsString()); + break; + + default: + super.deserializeAttribute(modificationInfos, parser); + } + } +} diff --git a/src/main/java/org/gridsuite/modification/server/json/AbstractEquipmentModificationInfosSerializer.java b/src/main/java/org/gridsuite/modification/server/json/AbstractEquipmentModificationInfosSerializer.java new file mode 100644 index 000000000..edcab360f --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/AbstractEquipmentModificationInfosSerializer.java @@ -0,0 +1,28 @@ +/** + * 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.json; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import org.gridsuite.modification.server.dto.EquipmentModificationInfos; + +import java.io.IOException; + +/** + * @author Slimane Amar + */ +public abstract class AbstractEquipmentModificationInfosSerializer extends AbstractModificationInfosSerializer { + AbstractEquipmentModificationInfosSerializer(final Class t) { + super(t); + } + + @Override + public void serialize(T modification, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + super.serialize(modification, jsonGenerator, serializerProvider); + jsonGenerator.writeStringField("equipmentId", modification.getEquipmentId()); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/json/AbstractInjectionModificationInfosDeserializer.java b/src/main/java/org/gridsuite/modification/server/json/AbstractInjectionModificationInfosDeserializer.java new file mode 100644 index 000000000..506986e07 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/AbstractInjectionModificationInfosDeserializer.java @@ -0,0 +1,36 @@ +/** + * 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.json; + +import com.fasterxml.jackson.core.JsonParser; +import org.gridsuite.modification.server.dto.InjectionModificationInfos; + +import java.io.IOException; + +/** + * @author Slimane Amar + */ +public abstract class AbstractInjectionModificationInfosDeserializer extends AbstractBasicEquipmentModificationInfosDeserializer { + protected AbstractInjectionModificationInfosDeserializer(final Class t) { + super(t); + } + + protected void deserializeAttribute(InjectionModificationInfos modificationInfos, JsonParser parser) throws IOException { + switch (parser.getCurrentName()) { + case "voltageLevelId": + modificationInfos.setVoltageLevelId(attributeModificationInfosDeserializer.deserialize(parser, String.class)); + break; + + case "busOrBusbarSectionId": + modificationInfos.setBusOrBusbarSectionId(attributeModificationInfosDeserializer.deserialize(parser, String.class)); + break; + + default: + super.deserializeAttribute(modificationInfos, parser); + } + } +} diff --git a/src/main/java/org/gridsuite/modification/server/json/AbstractInjectionModificationInfosSerializer.java b/src/main/java/org/gridsuite/modification/server/json/AbstractInjectionModificationInfosSerializer.java new file mode 100644 index 000000000..48b3bb741 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/AbstractInjectionModificationInfosSerializer.java @@ -0,0 +1,29 @@ +/** + * 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.json; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import org.gridsuite.modification.server.dto.InjectionModificationInfos; + +import java.io.IOException; + +/** + * @author Slimane Amar + */ +public abstract class AbstractInjectionModificationInfosSerializer extends AbstractBasicEquipmentModificationInfosSerializer { + protected AbstractInjectionModificationInfosSerializer(final Class t) { + super(t); + } + + @Override + public void serialize(T modification, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + super.serialize(modification, jsonGenerator, serializerProvider); + attributeSerializer.serialize("voltageLevelId", modification.getVoltageLevelId(), jsonGenerator); + attributeSerializer.serialize("busOrBusbarSectionId", modification.getBusOrBusbarSectionId(), jsonGenerator); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/json/AbstractModificationInfosDeserializer.java b/src/main/java/org/gridsuite/modification/server/json/AbstractModificationInfosDeserializer.java new file mode 100644 index 000000000..c0ea91675 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/AbstractModificationInfosDeserializer.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.json; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import org.gridsuite.modification.server.dto.ModificationInfos; + +import java.io.IOException; + +import static org.gridsuite.modification.server.modifications.ModificationUtils.toDateIfNotNull; +import static org.gridsuite.modification.server.modifications.ModificationUtils.toUuidIfNotNull; + +/** + * @author Slimane Amar + */ +public abstract class AbstractModificationInfosDeserializer extends StdDeserializer { + protected AbstractModificationInfosDeserializer(final Class t) { + super(t); + } + + protected void deserializeAttribute(ModificationInfos modificationInfos, JsonParser parser) throws IOException { + switch (parser.getCurrentName()) { + case "version", "type": + break; + case "uuid": + parser.nextToken(); + modificationInfos.setUuid(toUuidIfNotNull(parser.getValueAsString())); + break; + case "date": + parser.nextToken(); + modificationInfos.setDate(toDateIfNotNull(parser.getValueAsString())); + break; + case "stashed": + parser.nextToken(); + modificationInfos.setStashed(parser.getValueAsBoolean()); + break; + case "messageType": + parser.nextToken(); + modificationInfos.setMessageType(parser.getValueAsString()); + break; + case "messageValues": + parser.nextToken(); + modificationInfos.setMessageValues(parser.getValueAsString()); + break; + default: + throw new IllegalStateException("Unexpected field: " + parser.getCurrentName()); + } + } +} diff --git a/src/main/java/org/gridsuite/modification/server/json/AbstractModificationInfosSerializer.java b/src/main/java/org/gridsuite/modification/server/json/AbstractModificationInfosSerializer.java new file mode 100644 index 000000000..3ea5cc91c --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/AbstractModificationInfosSerializer.java @@ -0,0 +1,53 @@ +/** + * 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.json; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.type.WritableTypeId; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.jsontype.TypeSerializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import org.gridsuite.modification.server.dto.ModificationInfos; + +import java.io.IOException; + +import static com.fasterxml.jackson.core.JsonToken.START_OBJECT; +import static org.gridsuite.modification.server.modifications.ModificationUtils.toStringIfNotNull; + +/** + * @author Slimane Amar + */ +public abstract class AbstractModificationInfosSerializer extends StdSerializer { + + protected AbstractModificationInfosSerializer(final Class t) { + super(t); + } + + @Override + public void serialize(final T modification, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeStringField("version", ModificationInfos.VERSION); + jsonGenerator.writeStringField("type", modification.getType().name()); + jsonGenerator.writeStringField("uuid", toStringIfNotNull(modification.getUuid())); + jsonGenerator.writeStringField("date", modification.getDate() == null ? null : modification.getDate().toString()); + jsonGenerator.writeBooleanField("stashed", modification.getStashed()); + if (modification.getMessageType() != null) { + jsonGenerator.writeStringField("messageType", modification.getMessageType()); + } + if (modification.getMessageValues() != null) { + jsonGenerator.writeStringField("messageValues", modification.getMessageValues()); + } + } + + @Override + public void serializeWithType(T modification, JsonGenerator gen, + SerializerProvider provider, TypeSerializer typeSer) throws IOException { + WritableTypeId typeId = typeSer.typeId(modification, START_OBJECT); + typeSer.writeTypePrefix(gen, typeId); + serialize(modification, gen, provider); + typeSer.writeTypeSuffix(gen, typeId); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/json/AttributeModificationInfosDeserializer.java b/src/main/java/org/gridsuite/modification/server/json/AttributeModificationInfosDeserializer.java new file mode 100644 index 000000000..357bd9a15 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/AttributeModificationInfosDeserializer.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.json; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import org.gridsuite.modification.server.dto.AttributeModification; +import org.gridsuite.modification.server.dto.OperationType; + +import java.io.IOException; + +/** + * @author Slimane Amar + */ +public class AttributeModificationInfosDeserializer { + + public AttributeModification deserialize(JsonParser parser, Class type) throws IOException { + if (parser.nextToken() == JsonToken.VALUE_NULL) { + return null; + } + T value = null; + OperationType op = null; + while (parser.nextToken() != JsonToken.END_OBJECT) { + switch (parser.getCurrentName()) { + case "op": + parser.nextToken(); + op = parser.readValueAs(OperationType.class); + break; + + case "value": + parser.nextToken(); + value = parser.readValueAs(type); + break; + + default: + throw new IllegalStateException("Unexpected field: " + parser.getCurrentName()); + } + } + + return AttributeModification.toAttributeModification(value, op); + } +} + diff --git a/src/main/java/org/gridsuite/modification/server/json/AttributeModificationInfosSerializer.java b/src/main/java/org/gridsuite/modification/server/json/AttributeModificationInfosSerializer.java new file mode 100644 index 000000000..23908bff8 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/AttributeModificationInfosSerializer.java @@ -0,0 +1,28 @@ +/** + * 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.json; + +import com.fasterxml.jackson.core.JsonGenerator; +import org.gridsuite.modification.server.dto.AttributeModification; + +import java.io.IOException; + +/** + * @author Slimane Amar + */ +public class AttributeModificationInfosSerializer { + public void serialize(String fieldName, AttributeModification modification, JsonGenerator jsonGenerator) throws IOException { + if (modification == null) { + return; + } + jsonGenerator.writeFieldName(fieldName); + jsonGenerator.writeStartObject(); + jsonGenerator.writeObjectField("value", modification.getValue()); + jsonGenerator.writeStringField("op", modification.getOp().name()); + jsonGenerator.writeEndObject(); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/json/LoadModificationInfosDeserializer.java b/src/main/java/org/gridsuite/modification/server/json/LoadModificationInfosDeserializer.java new file mode 100644 index 000000000..18886aa4b --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/LoadModificationInfosDeserializer.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.json; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.powsybl.iidm.network.LoadType; +import org.gridsuite.modification.server.dto.LoadModificationInfos; + +import java.io.IOException; + +/** + * @author Slimane Amar + */ +public class LoadModificationInfosDeserializer extends AbstractInjectionModificationInfosDeserializer { + LoadModificationInfosDeserializer() { + super(LoadModificationInfos.class); + } + + @Override + public LoadModificationInfos deserialize(JsonParser parser, DeserializationContext ctx) throws IOException { + LoadModificationInfos modificationInfos = new LoadModificationInfos(); + while (parser.nextToken() != JsonToken.END_OBJECT) { + switch (parser.getCurrentName()) { + case "loadType": + modificationInfos.setLoadType(attributeModificationInfosDeserializer.deserialize(parser, LoadType.class)); + break; + case "constantActivePower": + modificationInfos.setConstantActivePower(attributeModificationInfosDeserializer.deserialize(parser, Double.class)); + break; + case "constantReactivePower": + modificationInfos.setConstantReactivePower(attributeModificationInfosDeserializer.deserialize(parser, Double.class)); + break; + + default: + super.deserializeAttribute(modificationInfos, parser); + } + } + + return modificationInfos; + } +} diff --git a/src/main/java/org/gridsuite/modification/server/json/LoadModificationInfosSerializer.java b/src/main/java/org/gridsuite/modification/server/json/LoadModificationInfosSerializer.java new file mode 100644 index 000000000..c15df2dff --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/LoadModificationInfosSerializer.java @@ -0,0 +1,31 @@ +/** + * 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.json; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import org.gridsuite.modification.server.dto.LoadModificationInfos; + +import java.io.IOException; + +/** + * @author Slimane Amar + */ +public class LoadModificationInfosSerializer extends AbstractInjectionModificationInfosSerializer { + + LoadModificationInfosSerializer() { + super(LoadModificationInfos.class); + } + + @Override + public void serialize(LoadModificationInfos modification, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + super.serialize(modification, jsonGenerator, serializerProvider); + attributeSerializer.serialize("loadType", modification.getLoadType(), jsonGenerator); + attributeSerializer.serialize("constantActivePower", modification.getConstantActivePower(), jsonGenerator); + attributeSerializer.serialize("constantReactivePower", modification.getConstantReactivePower(), jsonGenerator); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/json/ModificationInfosJsonModule.java b/src/main/java/org/gridsuite/modification/server/json/ModificationInfosJsonModule.java new file mode 100644 index 000000000..d6b515977 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/ModificationInfosJsonModule.java @@ -0,0 +1,21 @@ +/** + * 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.json; + +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.gridsuite.modification.server.dto.LoadModificationInfos; + +/** + * @author Slimane Amar + */ +public class ModificationInfosJsonModule extends SimpleModule { + public ModificationInfosJsonModule() { + this.addSerializer(LoadModificationInfos.class, new LoadModificationInfosSerializer()); + this.addDeserializer(LoadModificationInfos.class, new LoadModificationInfosDeserializer()); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/json/TabularModificationInfosDeserializer.java b/src/main/java/org/gridsuite/modification/server/json/TabularModificationInfosDeserializer.java new file mode 100644 index 000000000..0425b01ad --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/TabularModificationInfosDeserializer.java @@ -0,0 +1,57 @@ +/** + * 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.json; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import org.gridsuite.modification.server.dto.ModificationInfos; +import org.gridsuite.modification.server.dto.TabularModificationInfos; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Slimane Amar + */ +public class TabularModificationInfosDeserializer extends AbstractModificationInfosDeserializer { + TabularModificationInfosDeserializer() { + super(TabularModificationInfos.class); + } + + @Override + public TabularModificationInfos deserialize(JsonParser parser, DeserializationContext ctx) throws IOException { + TabularModificationInfos modificationInfos = new TabularModificationInfos(); + while (parser.nextToken() != JsonToken.END_OBJECT) { + switch (parser.getCurrentName()) { + case "modificationType": + parser.nextToken(); + modificationInfos.setModificationType(parser.getValueAsString()); + break; + + case "modifications": + parser.nextToken(); + modificationInfos.setModifications(deserializeModifications(parser, ctx)); + break; + + default: + super.deserializeAttribute(modificationInfos, parser); + } + } + + return modificationInfos; + } + + public List deserializeModifications(JsonParser parser, DeserializationContext ctx) throws IOException { + List modifications = new ArrayList<>(); + while (parser.nextToken() != JsonToken.END_ARRAY) { + modifications.add(new LoadModificationInfosDeserializer().deserialize(parser, ctx)); + } + return modifications; + } +} diff --git a/src/main/java/org/gridsuite/modification/server/json/TabularModificationInfosSerializer.java b/src/main/java/org/gridsuite/modification/server/json/TabularModificationInfosSerializer.java new file mode 100644 index 000000000..f9e957474 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/json/TabularModificationInfosSerializer.java @@ -0,0 +1,36 @@ +/** + * 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.json; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import org.gridsuite.modification.server.dto.ModificationInfos; +import org.gridsuite.modification.server.dto.TabularModificationInfos; + +import java.io.IOException; + +/** + * @author Slimane Amar + */ +public class TabularModificationInfosSerializer extends AbstractModificationInfosSerializer { + + TabularModificationInfosSerializer() { + super(TabularModificationInfos.class); + } + + @Override + public void serialize(TabularModificationInfos modification, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + super.serialize(modification, jsonGenerator, serializerProvider); + jsonGenerator.writeStringField("modificationType", modification.getModificationType()); + jsonGenerator.writeFieldName("modifications"); + jsonGenerator.writeStartArray(); + for (ModificationInfos m : modification.getModifications()) { + jsonGenerator.writeObject(m); + } + jsonGenerator.writeEndArray(); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/modifications/ModificationUtils.java b/src/main/java/org/gridsuite/modification/server/modifications/ModificationUtils.java index 53bdc9410..c6ac02748 100644 --- a/src/main/java/org/gridsuite/modification/server/modifications/ModificationUtils.java +++ b/src/main/java/org/gridsuite/modification/server/modifications/ModificationUtils.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable; import org.springframework.util.CollectionUtils; +import java.time.ZonedDateTime; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; @@ -66,6 +67,18 @@ public static Double nanIfNull(Double d) { return d == null ? Double.NaN : d; } + public static String toStringIfNotNull(Object o) { + return o == null ? null : o.toString(); + } + + public static ZonedDateTime toDateIfNotNull(String date) { + return date == null ? null : ZonedDateTime.parse(date); + } + + public static UUID toUuidIfNotNull(String uuid) { + return uuid == null ? null : UUID.fromString(uuid); + } + public VoltageLevel getVoltageLevel(Network network, String voltageLevelId) { VoltageLevel voltageLevel = network.getVoltageLevel(voltageLevelId); if (voltageLevel == null) { diff --git a/src/test/java/org/gridsuite/modification/server/json/LoadModificationInfosJsonTest.java b/src/test/java/org/gridsuite/modification/server/json/LoadModificationInfosJsonTest.java new file mode 100644 index 000000000..2e05572dd --- /dev/null +++ b/src/test/java/org/gridsuite/modification/server/json/LoadModificationInfosJsonTest.java @@ -0,0 +1,84 @@ +/** + * 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.json; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.powsybl.commons.json.JsonUtil; +import com.powsybl.commons.test.AbstractConverterTest; +import com.powsybl.iidm.network.LoadType; +import org.gridsuite.modification.server.dto.AttributeModification; +import org.gridsuite.modification.server.dto.LoadModificationInfos; +import org.gridsuite.modification.server.dto.OperationType; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.ZonedDateTime; +import java.util.Objects; +import java.util.UUID; + +/** + * @author Slimane Amar + */ +public class LoadModificationInfosJsonTest extends AbstractConverterTest { + + private static LoadModificationInfos createVersion1() { + return LoadModificationInfos.builder() + .uuid(UUID.fromString("d0f3efc0-1e41-4669-98ab-34167641578e")) + .date(ZonedDateTime.parse("2023-12-29T11:29:24.089680Z")) + .stashed(false) + .equipmentId("l1") + .equipmentName(AttributeModification.toAttributeModification("l1_name", OperationType.SET)) + .voltageLevelId(AttributeModification.toAttributeModification("vl1", OperationType.SET)) + .busOrBusbarSectionId(AttributeModification.toAttributeModification("vl1_b11", OperationType.SET)) + .loadType(AttributeModification.toAttributeModification(LoadType.FICTITIOUS, OperationType.SET)) + .constantActivePower(AttributeModification.toAttributeModification(10.0, OperationType.SET)) + .constantReactivePower(AttributeModification.toAttributeModification(10.0, OperationType.SET)) + .build(); + } + + public static void write(LoadModificationInfos modification, Path jsonFile) { + Objects.requireNonNull(modification); + Objects.requireNonNull(jsonFile); + + try (OutputStream os = Files.newOutputStream(jsonFile)) { + ObjectMapper objectMapper = JsonUtil.createObjectMapper(); + objectMapper.registerModule(new ModificationInfosJsonModule()); + ObjectWriter writer = objectMapper.writerWithDefaultPrettyPrinter(); + writer.writeValue(os, modification); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private static LoadModificationInfos read(InputStream is) throws IOException { + Objects.requireNonNull(is); + ObjectMapper objectMapper = JsonUtil.createObjectMapper(); + objectMapper.registerModule(new ModificationInfosJsonModule()); + return objectMapper.readValue(is, LoadModificationInfos.class); + } + + public static LoadModificationInfos read(Path jsonFile) { + Objects.requireNonNull(jsonFile); + try (InputStream is = Files.newInputStream(jsonFile)) { + return read(is); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Test + void roundTripVersion1Test() throws IOException { + roundTripTest(createVersion1(), LoadModificationInfosJsonTest::write, LoadModificationInfosJsonTest::read, "/json/LoadModificationInfosVersion1.json"); + } + +} diff --git a/src/test/java/org/gridsuite/modification/server/json/TabularModificationInfosJsonTest.java b/src/test/java/org/gridsuite/modification/server/json/TabularModificationInfosJsonTest.java new file mode 100644 index 000000000..116821a92 --- /dev/null +++ b/src/test/java/org/gridsuite/modification/server/json/TabularModificationInfosJsonTest.java @@ -0,0 +1,93 @@ +/** + * 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.json; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.powsybl.commons.json.JsonUtil; +import com.powsybl.commons.test.AbstractConverterTest; +import com.powsybl.iidm.network.LoadType; +import org.gridsuite.modification.server.ModificationType; +import org.gridsuite.modification.server.dto.AttributeModification; +import org.gridsuite.modification.server.dto.LoadModificationInfos; +import org.gridsuite.modification.server.dto.OperationType; +import org.gridsuite.modification.server.dto.TabularModificationInfos; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.ZonedDateTime; +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +/** + * @author Slimane Amar + */ +public class TabularModificationInfosJsonTest extends AbstractConverterTest { + + private static TabularModificationInfos createVersion1() { + return TabularModificationInfos.builder() + .uuid(UUID.fromString("38f23335-32db-4920-ad6f-be13b673b72a")) + .date(ZonedDateTime.parse("2023-12-29T11:29:24.089680Z")) + .stashed(false) + .messageType(ModificationType.TABULAR_MODIFICATION.name()) + .messageValues("{\"tabularModificationType\":\"LOAD_MODIFICATION\"}") + .modificationType("LOAD_MODIFICATION") + .modifications(List.of( + LoadModificationInfos.builder() + .uuid(UUID.fromString("d0f3efc0-1e41-4669-98ab-34167641578e")) + .date(ZonedDateTime.parse("2023-12-29T11:29:24.089680Z")) + .stashed(false) + .equipmentId("l1") + .loadType(AttributeModification.toAttributeModification(LoadType.FICTITIOUS, OperationType.SET)) + .constantActivePower(AttributeModification.toAttributeModification(10.0, OperationType.SET)) + .constantReactivePower(AttributeModification.toAttributeModification(10.0, OperationType.SET)) + .build() + )) + .build(); + } + + public static void write(TabularModificationInfos modification, Path jsonFile) { + Objects.requireNonNull(modification); + Objects.requireNonNull(jsonFile); + + try (OutputStream os = Files.newOutputStream(jsonFile)) { + ObjectMapper objectMapper = JsonUtil.createObjectMapper(); + objectMapper.registerModule(new ModificationInfosJsonModule()); + ObjectWriter writer = objectMapper.writerWithDefaultPrettyPrinter(); + writer.writeValue(os, modification); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private static TabularModificationInfos read(InputStream is) throws IOException { + Objects.requireNonNull(is); + ObjectMapper objectMapper = JsonUtil.createObjectMapper(); + objectMapper.registerModule(new ModificationInfosJsonModule()); + return objectMapper.readValue(is, TabularModificationInfos.class); + } + + public static TabularModificationInfos read(Path jsonFile) { + Objects.requireNonNull(jsonFile); + try (InputStream is = Files.newInputStream(jsonFile)) { + return read(is); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + //@Test + void roundTripVersion1Test() throws IOException { + roundTripTest(createVersion1(), TabularModificationInfosJsonTest::write, TabularModificationInfosJsonTest::read, "/json/TabularModificationInfosVersion1.json"); + } + +} diff --git a/src/test/java/org/gridsuite/modification/server/modifications/AbstractNetworkModificationTest.java b/src/test/java/org/gridsuite/modification/server/modifications/AbstractNetworkModificationTest.java index 0ad295977..7aadb549d 100644 --- a/src/test/java/org/gridsuite/modification/server/modifications/AbstractNetworkModificationTest.java +++ b/src/test/java/org/gridsuite/modification/server/modifications/AbstractNetworkModificationTest.java @@ -46,7 +46,7 @@ import java.util.UUID; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static org.gridsuite.modification.server.utils.assertions.Assertions.*; +import static org.gridsuite.modification.server.utils.assertions.Assertions.assertThat; import static org.junit.Assert.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -239,7 +239,7 @@ protected void testNetworkModificationsCount(UUID groupUuid, int actualSize) thr mvcResult = mockMvc.perform(get("/v1/groups/{groupUuid}/network-modifications?onlyMetadata=true", groupUuid).contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()).andReturn(); resultAsString = mvcResult.getResponse().getContentAsString(); - List modificationsTestGroupId = mapper.readValue(resultAsString, new TypeReference<>() { }); + List modificationsTestGroupId = mapper.readValue(resultAsString, List.class); assertEquals(actualSize, modificationsTestGroupId.size()); } diff --git a/src/test/resources/json/LoadModificationInfosVersion1.json b/src/test/resources/json/LoadModificationInfosVersion1.json new file mode 100644 index 000000000..1b303b75e --- /dev/null +++ b/src/test/resources/json/LoadModificationInfosVersion1.json @@ -0,0 +1,32 @@ +{ + "version" : "1.0", + "type" : "LOAD_MODIFICATION", + "uuid" : "d0f3efc0-1e41-4669-98ab-34167641578e", + "date" : "2023-12-29T11:29:24.089680Z", + "stashed" : false, + "equipmentId" : "l1", + "equipmentName" : { + "value" : "l1_name", + "op" : "SET" + }, + "voltageLevelId" : { + "value" : "vl1", + "op" : "SET" + }, + "busOrBusbarSectionId" : { + "value" : "vl1_b11", + "op" : "SET" + }, + "loadType" : { + "value" : "FICTITIOUS", + "op" : "SET" + }, + "constantActivePower" : { + "value" : 10.0, + "op" : "SET" + }, + "constantReactivePower" : { + "value" : 10.0, + "op" : "SET" + } +} \ No newline at end of file diff --git a/src/test/resources/json/TabularModificationInfosVersion1.json b/src/test/resources/json/TabularModificationInfosVersion1.json new file mode 100644 index 000000000..e5cec4150 --- /dev/null +++ b/src/test/resources/json/TabularModificationInfosVersion1.json @@ -0,0 +1,30 @@ +{ + "version" : "1.0", + "type" : "TABULAR_MODIFICATION", + "uuid" : "38f23335-32db-4920-ad6f-be13b673b72a", + "date" : "2023-12-29T11:29:24.089680Z", + "stashed" : false, + "messageType" : "TABULAR_MODIFICATION", + "messageValues" : "{\"tabularModificationType\":\"LOAD_MODIFICATION\"}", + "modificationType" : "LOAD_MODIFICATION", + "modifications" : [ { + "version" : "1.0", + "type" : "LOAD_MODIFICATION", + "uuid" : "d0f3efc0-1e41-4669-98ab-34167641578e", + "date" : "2023-12-29T11:29:24.089680Z", + "stashed" : false, + "equipmentId" : "l1", + "loadType" : { + "value" : "FICTITIOUS", + "op" : "SET" + }, + "constantActivePower" : { + "value" : 10.0, + "op" : "SET" + }, + "constantReactivePower" : { + "value" : 10.0, + "op" : "SET" + } + } ] +} \ No newline at end of file