diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefEditorService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefEditorService.java index 7d6aeb621..538c93e65 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefEditorService.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefEditorService.java @@ -7,6 +7,8 @@ import lombok.RequiredArgsConstructor; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.api.ExtRefEditor; +import org.lfenergy.compas.sct.commons.api.LnEditor; +import org.lfenergy.compas.sct.commons.domain.*; import org.lfenergy.compas.sct.commons.dto.*; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.model.epf.EPF; @@ -46,6 +48,7 @@ public class ExtRefEditorService implements ExtRefEditor { private final IedService iedService; private final LdeviceService ldeviceService; + private final LnEditor lnEditor; private final ExtRefService extRefService; private final DataTypeTemplatesService dataTypeTemplatesService; @@ -323,6 +326,44 @@ public List manageBindingForLDEPF(SCL scd, EPF epf) { return sclReportItems; } + @Override + public void epfPostProcessing(SCL scd) { + iedService.getFilteredIeds(scd, ied -> !ied.getName().contains("TEST")) + .forEach(tied -> ldeviceService.findLdevice(tied, tlDevice -> LDEVICE_LDEPF.equals(tlDevice.getInst())) + .ifPresent(tlDevice -> { + List tdoiList = tlDevice.getLN0().getDOI() + .stream().filter(tdoi -> tdoi.getName().startsWith("InRef")) + .toList(); + for (TDOI tdoi: tdoiList){ + DoLinkedToDaFilter doLinkedToSetSrcRef = new DoLinkedToDaFilter(tdoi.getName(), List.of(), SETSRCREF_DA_NAME, List.of()); + Optional setSrcRefDAI = lnEditor.getDOAndDAInstances(tlDevice.getLN0(), doLinkedToSetSrcRef); + DoLinkedToDaFilter doLinkedPurPose = new DoLinkedToDaFilter(tdoi.getName(), List.of(), PURPOSE_DA_NAME, List.of()); + Optional purPoseDAI = lnEditor.getDOAndDAInstances(tlDevice.getLN0(), doLinkedPurPose); + + boolean isSetSrcRefExistAndEmpty = setSrcRefDAI.isPresent() + && (!setSrcRefDAI.get().isSetVal() + || (setSrcRefDAI.get().isSetVal() + && setSrcRefDAI.get().getVal().getFirst().getValue().isEmpty())); + boolean isPurposeExistAndMatchChannel = purPoseDAI.isPresent() + && purPoseDAI.get().isSetVal() + && (purPoseDAI.get().getVal().getFirst().getValue().startsWith("DYN_LDEPF_DIGITAL CHANNEL") + || purPoseDAI.get().getVal().getFirst().getValue().startsWith("DYN_LDEPF_ANALOG CHANNEL")); + if(isSetSrcRefExistAndEmpty && isPurposeExistAndMatchChannel) { + + DoLinkedToDa doLinkedToDa = new DoLinkedToDa(); + DataObject dataObject = new DataObject(); + dataObject.setDoName(tdoi.getName()); + doLinkedToDa.setDataObject(dataObject); + DataAttribute dataAttribute = new DataAttribute(); + dataAttribute.setDaName(SETSRCREF_DA_NAME); + dataAttribute.setDaiValues(List.of(new DaVal(null, tied.getName()+tlDevice.getInst()+"/LPHD0.Proxy"))); + doLinkedToDa.setDataAttribute(dataAttribute); + lnEditor.updateOrCreateDOAndDAInstances(tlDevice.getLN0(), doLinkedToDa); + } + } + })); + } + private List validateIed(SclRootAdapter sclRootAdapter) { List iedErrors = new ArrayList<>(checkIedCompasIcdHeaderAttributes(sclRootAdapter)); iedErrors.addAll(checkIedUnityOfIcdSystemVersionUuid(sclRootAdapter)); diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/ExtRefEditor.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/ExtRefEditor.java index f083a5a34..f817f382b 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/ExtRefEditor.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/ExtRefEditor.java @@ -63,6 +63,14 @@ public interface ExtRefEditor { */ List manageBindingForLDEPF(SCL scd, EPF epf); + /** + * Pointing an unused channel to an existing object LPHD0.Proxy of the concerned IED. + * An unused channel is characterized by the value DAI name ="setSrcRef"/Val (should be empty) in InRef** + * that have a purpose beginning by DYN_LDEPF_DIGITAL CHANNEL or DYN_LDEPF_ANALOG CHANNEL + * @param scd SCL + */ + void epfPostProcessing(SCL scd); + /** * Debinding of Private CompasFlows and ExtRef signals based on voltageLevel * diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/CommonConstants.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/CommonConstants.java index 145c01d93..bb2add76b 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/CommonConstants.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/CommonConstants.java @@ -36,6 +36,7 @@ public final class CommonConstants { public static final String SETSRCCB_DA_NAME = "setSrcCB"; public static final String SETTSTREF_DA_NAME = "setTstRef"; public static final String SETTSTCB_DA_NAME = "setTstCB"; + public static final String PURPOSE_DA_NAME = "purpose"; public static final String Q_DA_NAME = "q"; public static final String IED_TEST_NAME = "IEDTEST"; diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ExtRefEditorServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ExtRefEditorServiceTest.java index 66f997e98..098c92533 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ExtRefEditorServiceTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ExtRefEditorServiceTest.java @@ -5,6 +5,7 @@ package org.lfenergy.compas.sct.commons; import org.assertj.core.api.Assertions; +import org.assertj.core.api.SoftAssertions; import org.assertj.core.groups.Tuple; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Tag; @@ -39,7 +40,7 @@ class ExtRefEditorServiceTest { @BeforeEach void init() { - extRefEditorService = new ExtRefEditorService(new IedService(), new LdeviceService(), new ExtRefService(), new DataTypeTemplatesService()); + extRefEditorService = new ExtRefEditorService(new IedService(), new LdeviceService(), new LnService(), new ExtRefService(), new DataTypeTemplatesService()); } @Test @@ -955,4 +956,44 @@ void updateIedNameBasedOnLnode_when_no_Compas_ICD_Header_should_return_an_error( .containsExactly(Tuple.tuple(true, "The substation LNode with following attributes : IedName:IED_NAME2 / LdInst:LD_INST21 / LnClass:ANCR / LnInst:1 does not contain the needed (COMPAS - ICDHeader) private")); } + + @Test + void epfPostProcessing_when_exist_unused_channel_should_update_setSrcRef() { + // Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ldepf/scd_ldepf_postProcessing.xml"); + // When + extRefEditorService.epfPostProcessing(scd); + // Then + SoftAssertions softly = new SoftAssertions(); + + Optional setSrcRefInInRef1 = findDai(scd, "IED_NAME1", "LDEPF", "InRef1", "setSrcRef"); + Optional purposeInInRef1 = findDai(scd, "IED_NAME1", "LDEPF", "InRef1", "purpose"); + assertThat(purposeInInRef1).isPresent(); + softly.assertThat(purposeInInRef1.get().getVal().getFirst().getValue()).doesNotStartWith("DYN_LDEPF_DIGITAL CHANNEL"); + softly.assertThat(purposeInInRef1.get().getVal().getFirst().getValue()).doesNotStartWith("DYN_LDEPF_ANALOG CHANNEL"); + assertThat(setSrcRefInInRef1).isPresent(); + softly.assertThat(setSrcRefInInRef1.get().isSetVal()).isFalse(); + + Optional setSrcRefInInRef2 = findDai(scd, "IED_NAME1", "LDEPF", "InRef2", "setSrcRef"); + Optional purposeInInRef2 = findDai(scd, "IED_NAME1", "LDEPF", "InRef2", "purpose"); + assertThat(purposeInInRef2).isPresent(); + softly.assertThat(purposeInInRef2.get().getVal().getFirst().getValue()).startsWith("DYN_LDEPF_DIGITAL CHANNEL"); + assertThat(setSrcRefInInRef2).isPresent(); + softly.assertThat(setSrcRefInInRef2.get().getVal().getFirst().getValue()).isEqualTo("IED_NAME1LDEPF/LPHD0.Proxy"); + + Optional setSrcRefInInRef3 = findDai(scd, "IED_NAME1", "LDEPF", "InRef3", "setSrcRef"); + Optional purposeInInRef3 = findDai(scd, "IED_NAME1", "LDEPF", "InRef3", "purpose"); + assertThat(purposeInInRef3).isPresent(); + softly.assertThat(purposeInInRef3.get().getVal().getFirst().getValue()).startsWith("DYN_LDEPF_DIGITAL CHANNEL"); + assertThat(setSrcRefInInRef3).isPresent(); + softly.assertThat(setSrcRefInInRef3.get().getVal().getFirst().getValue()).isEqualTo("IED_NAME1LDEPF/LPHD0.Proxy"); + + Optional setSrcRefInInRef4 = findDai(scd, "IED_NAME1", "LDEPF", "InRef4", "setSrcRef"); + Optional purposeInInRef4 = findDai(scd, "IED_NAME1", "LDEPF", "InRef4", "purpose"); + assertThat(purposeInInRef4).isPresent(); + softly.assertThat(purposeInInRef4.get().getVal().getFirst().getValue()).startsWith("DYN_LDEPF_ANALOG CHANNEL"); + assertThat(setSrcRefInInRef4).isPresent(); + softly.assertThat(setSrcRefInInRef4.get().getVal().getFirst().getValue()).isEqualTo("IED_NAME1LDEPF/LPHD0.Proxy"); + softly.assertAll(); + } } diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclHelper.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclHelper.java index 89987741d..f006c370f 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclHelper.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclHelper.java @@ -19,6 +19,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; @@ -118,6 +119,18 @@ public static IDataParentAdapter findDoiOrSdi(AbstractLNAdapter lnAdapter, St return parentAdapter; } + public static Optional findDai(SCL scl, String iedName, String ldInst, String doiName, String daiName) { + return scl.getIED().stream().filter(tied -> tied.getName().equals(iedName)) + .flatMap(tied -> tied.getAccessPoint().stream()) + .flatMap(tAccessPoint -> tAccessPoint.getServer().getLDevice().stream()) + .filter(tlDevice -> tlDevice.getInst().equals(ldInst)) + .flatMap(tlDevice -> tlDevice.getLN0().getDOI().stream()) + .filter(tdoi -> tdoi.getName().equals(doiName)) + .flatMap(tdoi -> tdoi.getSDIOrDAI().stream().map(tUnNaming -> (TDAI)tUnNaming)) + .filter(tdai -> tdai.getName().equals(daiName)) + .findFirst(); + } + public static AbstractDAIAdapter findDai(AbstractLNAdapter lnAdapter, String dataTypeRef) { String[] names = dataTypeRef.split("\\."); if (names.length < 2) { diff --git a/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_postProcessing.xml b/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_postProcessing.xml new file mode 100644 index 000000000..f54474b67 --- /dev/null +++ b/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_postProcessing.xml @@ -0,0 +1,104 @@ + + + + + + + SCD + +
+ + + + + + + + + + + + + + + + + + on + + + + + DYN_LDAGSA2_Circuit I phase A amplitude_1_Vector + + + + + + DYN_LDEPF_DIGITAL CHANNEL 11 ADF + + + + + + DYN_LDEPF_DIGITAL CHANNEL 12 ADF + + + + + + + + DYN_LDEPF_ANALOG CHANNEL 11 ADF + + + + + + + + + + + + + on + + + + + DYN_LDAGSA2_Circuit I phase A amplitude_1_Vector + + + + + + + + + + + + + + + + + + + + + + + + + + + on + off + blocked + test + test/blocked + + + \ No newline at end of file