diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java index a13b5cd1f6a..2f6a272dba5 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java @@ -16,6 +16,7 @@ import com.powsybl.cgmes.extensions.CgmesTapChangers; import com.powsybl.cgmes.extensions.CgmesTapChangersAdder; import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.cgmes.model.WindingType; import com.powsybl.iidm.network.*; import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; @@ -111,10 +112,8 @@ protected CgmesRegulatingControlPhase setContextRegulatingDataPhase(TapChanger t @Override protected void addAliasesAndProperties(Identifiable identifiable) { super.addAliasesAndProperties(identifiable); - int end = 1; for (PropertyBag p : ps) { - identifiable.addAlias(p.getId("TransformerEnd"), Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TRANSFORMER_END + end); - end++; + identifiable.addAlias(p.getId("TransformerEnd"), Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TRANSFORMER_END + WindingType.endNumber(p)); } List ptcs = context.cgmes().phaseTapChangerListForPowerTransformer(identifiable.getId()); if (ptcs != null) { diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/AbstractCgmesModel.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/AbstractCgmesModel.java index 6006049b616..59b4095c8e3 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/AbstractCgmesModel.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/AbstractCgmesModel.java @@ -19,7 +19,6 @@ import java.io.IOException; import java.io.InputStream; import java.util.*; -import java.util.stream.Collectors; /** * @author Luma ZamarreƱo {@literal } @@ -206,10 +205,8 @@ private Map computeGroupedTransformerEnds() { .forEach(tends -> { PropertyBags tends1 = new PropertyBags( tends.getValue().stream() - .sorted(Comparator - .comparing(WindingType::fromTransformerEnd) - .thenComparing(end -> end.asInt(endNumber, -1))) - .collect(Collectors.toList())); + .sorted(Comparator.comparing(WindingType::endNumber)) + .toList()); tends.setValue(tends1); }); return gends; diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/WindingType.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/WindingType.java index 049302e5969..918ee5ef6ae 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/WindingType.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/WindingType.java @@ -17,13 +17,14 @@ public enum WindingType { PRIMARY, SECONDARY, TERTIARY; - public static WindingType fromTransformerEnd(PropertyBag end) { - // For CIM14 (CIM ENTSOE Profile1) primary is determined by windingType - // For CIM16 (CGMES) primary is defined by the corresponding terminal sequence number: - // "The Terminal.sequenceNumber distinguishes the terminals much as previously done by - // TransformerWinding.windingType:WindingType" - + /** + * Retrieve the WindingType for the given transformer winding/end. + * @param end A PropertyBag with the transformer winding/end properties. + * @return The WindingType (PRIMARY/SECONDARY/TERTIARY) corresponding to the given transformer winding/end. + */ + public static WindingType windingType(PropertyBag end) { if (end.containsKey("windingType")) { + // For CIM14 (CIM ENTSOE Profile1) primary is determined by TransformerWinding.windingType String wtype = end.getLocal("windingType"); if (wtype.endsWith("WindingType.primary")) { return WindingType.PRIMARY; @@ -32,10 +33,23 @@ public static WindingType fromTransformerEnd(PropertyBag end) { } else if (wtype.endsWith("WindingType.tertiary")) { return WindingType.TERTIARY; } - } else if (end.containsKey("terminalSequenceNumber")) { - // Terminal.sequenceNumber := 1, 2 ,3 ... - return WindingType.values()[end.asInt("terminalSequenceNumber") - 1]; + } else if (end.containsKey("endNumber")) { + // For CIM16 (CGMES 2.4.15) primary is defined by TransformerEnd.endNumber + try { + return WindingType.values()[end.asInt("endNumber") - 1]; + } catch (Exception e) { + return WindingType.PRIMARY; + } } return WindingType.PRIMARY; } + + /** + * Retrieve the endNumber for the given transformer winding/end. + * @param end A PropertyBag with the transformer winding/end properties. + * @return The endNumber value (1/2/3) corresponding to the given transformer winding/end. + */ + public static int endNumber(PropertyBag end) { + return windingType(end).ordinal() + 1; + } } diff --git a/cgmes/cgmes-model/src/test/java/com/powsybl/cgmes/model/WindingTypeTest.java b/cgmes/cgmes-model/src/test/java/com/powsybl/cgmes/model/WindingTypeTest.java new file mode 100644 index 00000000000..e613ad651a5 --- /dev/null +++ b/cgmes/cgmes-model/src/test/java/com/powsybl/cgmes/model/WindingTypeTest.java @@ -0,0 +1,75 @@ +/** + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.cgmes.model; + +import com.powsybl.triplestore.api.PropertyBag; +import org.junit.jupiter.api.Test; + +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Romain Courtier {@literal } + */ +class WindingTypeTest { + + PropertyBag end1; + PropertyBag end2; + PropertyBag end3; + PropertyBag end4; + + static final String WINDING_TYPE = "windingType"; + static final String END_NUMBER = "endNumber"; + + @Test + void cim14WindingTypeTest() { + end1 = new PropertyBag(Collections.singletonList(WINDING_TYPE), true); + end1.put(WINDING_TYPE, "http://iec.ch/TC57/2009/CIM-schema-cim14#WindingType.primary"); + assertEquals(WindingType.PRIMARY, WindingType.windingType(end1)); + assertEquals(1, WindingType.endNumber(end1)); + + end2 = new PropertyBag(Collections.singletonList(WINDING_TYPE), true); + end2.put(WINDING_TYPE, "http://iec.ch/TC57/2009/CIM-schema-cim14#WindingType.secondary"); + assertEquals(WindingType.SECONDARY, WindingType.windingType(end2)); + assertEquals(2, WindingType.endNumber(end2)); + + end3 = new PropertyBag(Collections.singletonList(WINDING_TYPE), true); + end3.put(WINDING_TYPE, "http://iec.ch/TC57/2009/CIM-schema-cim14#WindingType.tertiary"); + assertEquals(WindingType.TERTIARY, WindingType.windingType(end3)); + assertEquals(3, WindingType.endNumber(end3)); + + end4 = new PropertyBag(Collections.singletonList(WINDING_TYPE), true); + end4.put(WINDING_TYPE, "WindingType.quaternary"); + assertEquals(WindingType.PRIMARY, WindingType.windingType(end4)); + assertEquals(1, WindingType.endNumber(end4)); + } + + @Test + void cim16WindingTypeTest() { + end1 = new PropertyBag(Collections.singletonList(END_NUMBER), true); + end1.put(END_NUMBER, "1"); + assertEquals(WindingType.PRIMARY, WindingType.windingType(end1)); + assertEquals(1, WindingType.endNumber(end1)); + + end2 = new PropertyBag(Collections.singletonList(END_NUMBER), true); + end2.put(END_NUMBER, "2"); + assertEquals(WindingType.SECONDARY, WindingType.windingType(end2)); + assertEquals(2, WindingType.endNumber(end2)); + + end3 = new PropertyBag(Collections.singletonList(END_NUMBER), true); + end3.put(END_NUMBER, "3"); + assertEquals(WindingType.TERTIARY, WindingType.windingType(end3)); + assertEquals(3, WindingType.endNumber(end3)); + + end4 = new PropertyBag(Collections.singletonList(END_NUMBER), true); + end4.put(END_NUMBER, "4"); + assertEquals(WindingType.PRIMARY, WindingType.windingType(end4)); + assertEquals(1, WindingType.endNumber(end4)); + } +}