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 55d426231..9ee47239c 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 @@ -4,6 +4,7 @@ package org.lfenergy.compas.sct.commons; +import lombok.Getter; import lombok.RequiredArgsConstructor; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.api.ExtRefEditor; @@ -15,6 +16,7 @@ import org.lfenergy.compas.sct.commons.model.epf.TCBScopeType; import org.lfenergy.compas.sct.commons.model.epf.TChannel; import org.lfenergy.compas.sct.commons.model.epf.TChannelType; +import org.lfenergy.compas.sct.commons.model.epf.TChannelLevMod; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter; import org.lfenergy.compas.sct.commons.scl.ldevice.LDeviceAdapter; @@ -34,12 +36,21 @@ @RequiredArgsConstructor public class ExtRefEditorService implements ExtRefEditor { private static final String INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO = "Invalid or missing attributes in ExtRef binding info"; + private static final List DO_DA_MAPPINGS = List.of( + new DoNameAndDaName(CHNUM1_DO_NAME, DU_DA_NAME), + new DoNameAndDaName(LEVMOD_DO_NAME, SETVAL_DA_NAME), + new DoNameAndDaName(MOD_DO_NAME, STVAL_DA_NAME), + new DoNameAndDaName(SRCREF_DO_NAME, SETSRCREF_DA_NAME) + ); private final IedService iedService; private final LdeviceService ldeviceService; private final LnEditor lnEditor; private final DataTypeTemplatesService dataTypeTemplatesService; + @Getter + private final List errorHandler = new ArrayList<>(); + /** * Provides valid IED sources according to EPF configuration.
* EPF verification include:
@@ -76,17 +87,16 @@ private List getIedSources(SclRootAdapter sclRootAdapter, TCompasBay compa * - The location of ExtRef should be in LDevice (inst=LDEPF)
* - ExtRef that lacks Bay or ICDHeader Private is not returned
* - * @param sclReportItems List of SclReportItem * @return list of ExtRef and associated Bay */ - private List getExtRefWithBayReferenceInLDEPF(TDataTypeTemplates dataTypeTemplates, TIED tied, final TLDevice tlDevice, final List sclReportItems) { + private List getExtRefWithBayReferenceInLDEPF(TDataTypeTemplates dataTypeTemplates, TIED tied, final TLDevice tlDevice) { List extRefBayReferenceList = new ArrayList<>(); String lDevicePath = "SCL/IED[@name=\"" + tied.getName() + "\"]/AccessPoint/Server/LDevice[@inst=\"" + tlDevice.getInst() + "\"]"; Optional tCompasBay = PrivateUtils.extractCompasPrivate(tied, TCompasBay.class); if (tCompasBay.isEmpty()) { - sclReportItems.add(SclReportItem.error(lDevicePath, "The IED has no Private Bay")); + errorHandler.add(SclReportItem.error(lDevicePath, "The IED has no Private Bay")); if (PrivateUtils.extractCompasPrivate(tied, TCompasICDHeader.class).isEmpty()) { - sclReportItems.add(SclReportItem.error(lDevicePath, "The IED has no Private compas:ICDHeader")); + errorHandler.add(SclReportItem.error(lDevicePath, "The IED has no Private compas:ICDHeader")); } return Collections.emptyList(); } @@ -97,7 +107,7 @@ private List getExtRefWithBayReferenceInLDEPF .getExtRef().stream() .map(extRef -> new ExtRefInfo.ExtRefWithBayReference(tied.getName(), tCompasBay.get(), extRef)).toList()); } else { - sclReportItems.add(SclReportItem.error(lDevicePath, "DO@name=Mod/DA@name=stVal not found in DataTypeTemplate")); + errorHandler.add(SclReportItem.error(lDevicePath, "DO@name=Mod/DA@name=stVal not found in DataTypeTemplate")); } return extRefBayReferenceList; } @@ -114,7 +124,7 @@ private static Boolean doesExtRefMatchLDEPFChannel(TExtRef extRef, TChannel tCha && extRef.getDesc().startsWith("DYN_LDEPF_ANALOG CHANNEL " + tChannel.getChannelNum() + "_1_AnalogueValue") && extRef.getDesc().endsWith("_" + tChannel.getDAName() + "_1"); Boolean doesExtRefDescMatchDigitalChannel = tChannel.getChannelType().equals(TChannelType.DIGITAL) - && extRef.getDesc().startsWith("DYN_LDEPF_DIGITAL CHANNEL " + tChannel.getChannelNum() + "_1_BOOLEEN") + && extRef.getDesc().startsWith("DYN_LDEPF_DIGITAL CHANNEL " + tChannel.getChannelNum() + "_1_BOOLEAN") && extRef.getDesc().endsWith("_" + tChannel.getDAName() + "_1"); return extRef.isSetDesc() && (doesExtRefDescMatchAnalogChannel || doesExtRefDescMatchDigitalChannel) && extRef.isSetPLN() && Utils.lnClassEquals(extRef.getPLN(), tChannel.getLNClass()) @@ -263,29 +273,29 @@ public TExtRef updateExtRefSource(SCL scd, ExtRefInfo extRefInfo) throws ScdExce @Override public List manageBindingForLDEPF(SCL scd, EPF epf) { - List sclReportItems = new ArrayList<>(); + errorHandler.clear(); SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - if (!epf.isSetChannels()) return sclReportItems; + if (!epf.isSetChannels()) return errorHandler; iedService.getFilteredIeds(scd, ied -> !ied.getName().contains("TEST")) .forEach(tied -> ldeviceService.findLdevice(tied, LDEVICE_LDEPF) - .ifPresent(tlDevice -> getExtRefWithBayReferenceInLDEPF(scd.getDataTypeTemplates(), tied, tlDevice, sclReportItems) + .ifPresent(tlDevice -> getExtRefWithBayReferenceInLDEPF(scd.getDataTypeTemplates(), tied, tlDevice) .forEach(extRefBayRef -> epf.getChannels().getChannel().stream().filter(tChannel -> doesExtRefMatchLDEPFChannel(extRefBayRef.extRef(), tChannel)) .findFirst().ifPresent(channel -> { List iedSources = getIedSources(sclRootAdapter, extRefBayRef.compasBay(), channel); if (iedSources.size() == 1) { updateLDEPFExtRefBinding(extRefBayRef.extRef(), iedSources.getFirst(), channel); LDeviceAdapter lDeviceAdapter = new LDeviceAdapter(new IEDAdapter(sclRootAdapter, tied.getName()), tlDevice); - sclReportItems.addAll(updateLDEPFDos(lDeviceAdapter, extRefBayRef.extRef(), channel)); + updateLDEPFDos(lDeviceAdapter, extRefBayRef.extRef(), channel); } else { if (iedSources.size() > 1) { - sclReportItems.add(SclReportItem.warning(null, "There is more than one IED source to bind the signal " + + errorHandler.add(SclReportItem.warning(null, "There is more than one IED source to bind the signal " + "/IED@name=" + extRefBayRef.iedName() + "/LDevice@inst=LDEPF/LN0" + "/ExtRef@desc=" + extRefBayRef.extRef().getDesc())); } // If the source IED is not found, there will be no update or report message. } })))); - return sclReportItems; + return errorHandler; } @Override @@ -332,44 +342,44 @@ private void updateLDEPFExtRefBinding(TExtRef extRef, TIED iedSource, TChannel s extRef.setDoName(doName); } - private List updateLDEPFDos(LDeviceAdapter lDeviceAdapter, TExtRef extRef, TChannel setting) { - List sclReportItems = new ArrayList<>(); - List doNameAndDaNameList = List.of( - new DoNameAndDaName(CHNUM1_DO_NAME, DU_DA_NAME), - new DoNameAndDaName(LEVMOD_DO_NAME, SETVAL_DA_NAME), - new DoNameAndDaName(MOD_DO_NAME, STVAL_DA_NAME), - new DoNameAndDaName(SRCREF_DO_NAME, SETSRCREF_DA_NAME) - ); + private void updateLDEPFDos(LDeviceAdapter lDeviceAdapter, TExtRef extRef, TChannel setting) { if (setting.getChannelType().equals(TChannelType.DIGITAL)) { //digital lDeviceAdapter.findLnAdapter(LN_RBDR, setting.getChannelNum(), null) - .ifPresent(lnAdapter -> doNameAndDaNameList.forEach(doNameAndDaName -> updateVal(lnAdapter, doNameAndDaName.doName, doNameAndDaName.daName, extRef, setting).ifPresent(sclReportItems::add))); + .ifPresent(lnAdapter -> DO_DA_MAPPINGS.forEach(doNameAndDaName -> updateVal(lnAdapter, doNameAndDaName, extRef, setting))); lDeviceAdapter.findLnAdapter(LN_RBDR, setting.getChannelNum(), LN_PREFIX_B) - .ifPresent(lnAdapter -> doNameAndDaNameList.forEach(doNameAndDaName -> updateVal(lnAdapter, doNameAndDaName.doName, doNameAndDaName.daName, extRef, setting).ifPresent(sclReportItems::add))); + .ifPresent(lnAdapter -> DO_DA_MAPPINGS.forEach(doNameAndDaName -> updateVal(lnAdapter, doNameAndDaName, extRef, setting))); } if (setting.getChannelType().equals(TChannelType.ANALOG)) { //analog lDeviceAdapter.findLnAdapter(LN_RADR, setting.getChannelNum(), null) - .ifPresent(lnAdapter -> doNameAndDaNameList.forEach(doNameAndDaName -> updateVal(lnAdapter, doNameAndDaName.doName, doNameAndDaName.daName, extRef, setting).ifPresent(sclReportItems::add))); + .ifPresent(lnAdapter -> DO_DA_MAPPINGS.forEach(doNameAndDaName -> updateVal(lnAdapter, doNameAndDaName, extRef, setting))); lDeviceAdapter.findLnAdapter(LN_RADR, setting.getChannelNum(), LN_PREFIX_A) - .ifPresent(lnAdapter -> doNameAndDaNameList.forEach(doNameAndDaName -> updateVal(lnAdapter, doNameAndDaName.doName, doNameAndDaName.daName, extRef, setting).ifPresent(sclReportItems::add))); + .ifPresent(lnAdapter -> DO_DA_MAPPINGS.forEach(doNameAndDaName -> updateVal(lnAdapter, doNameAndDaName, extRef, setting))); } - return sclReportItems; } - private Optional updateVal(AbstractLNAdapter lnAdapter, String doName, String daName, TExtRef extRef, TChannel setting) { - String value = switch (daName) { - case DU_DA_NAME -> setting.getChannelShortLabel(); - case SETVAL_DA_NAME -> LN_PREFIX_B.equals(lnAdapter.getPrefix()) || LN_PREFIX_A.equals(lnAdapter.getPrefix()) ? setting.getChannelLevModQ().value() : setting.getChannelLevMod().value(); - case STVAL_DA_NAME -> ActiveStatus.ON.getValue(); - case SETSRCREF_DA_NAME -> computeDaiValue(lnAdapter, extRef, setting.getDAName()); - default -> null; + private void updateVal(AbstractLNAdapter lnAdapter, DoNameAndDaName doDaName, TExtRef extRef, TChannel setting) { + String lnPrefix = lnAdapter.getPrefix(); + Optional sclReportItem = switch (doDaName.daName) { + case DU_DA_NAME -> setting.isSetChannelShortLabel() ? lnAdapter.getDOIAdapterByName(doDaName.doName).updateDAI(doDaName.daName, setting.getChannelShortLabel()) : + Optional.empty(); + case SETVAL_DA_NAME -> { + if (LN_PREFIX_B.equals(lnPrefix) || LN_PREFIX_A.equals(lnPrefix)) { + yield setting.isSetChannelLevModQ() && !setting.getChannelLevModQ().equals(TChannelLevMod.NA) ? lnAdapter.getDOIAdapterByName(doDaName.doName).updateDAI(doDaName.daName, setting.getChannelLevModQ().value()) : Optional.empty(); + } else { + yield setting.isSetChannelLevMod() && !setting.getChannelLevMod().equals(TChannelLevMod.NA) ? lnAdapter.getDOIAdapterByName(doDaName.doName).updateDAI(doDaName.daName, setting.getChannelLevMod().value()) : Optional.empty(); + } + } + case STVAL_DA_NAME -> lnAdapter.getDOIAdapterByName(doDaName.doName).updateDAI(doDaName.daName, ActiveStatus.ON.getValue()); + case SETSRCREF_DA_NAME -> lnAdapter.getDOIAdapterByName(doDaName.doName).updateDAI(doDaName.daName, computeDaiValue(lnPrefix, extRef, setting.getDAName())); + default -> throw new IllegalStateException("Unexpected value: " + doDaName.daName); }; - return lnAdapter.getDOIAdapterByName(doName).updateDAI(daName, value); + sclReportItem.ifPresent(errorHandler::add); } - private String computeDaiValue(AbstractLNAdapter lnAdapter, TExtRef extRef, String daName) { - if (LN_PREFIX_B.equals(lnAdapter.getPrefix()) || LN_PREFIX_A.equals(lnAdapter.getPrefix())) { + private String computeDaiValue(String lnPrefix, TExtRef extRef, String daName) { + if (LN_PREFIX_B.equals(lnPrefix) || LN_PREFIX_A.equals(lnPrefix)) { return extRef.getIedName() + extRef.getLdInst() + "/" + trimToEmpty(extRef.getPrefix()) + 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 204c40a9f..47a00a872 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 @@ -11,6 +11,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.MethodSource; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.dto.*; @@ -68,11 +69,11 @@ void manageBindingForLDEPF_whenFlowKindIsInternalAndAllExtRefInSameBay_should_re List sclReportItems = extRefEditorService.manageBindingForLDEPF(scd, epf); // Then assertThat(sclReportItems).isEmpty(); - TExtRef extRef1 = findExtRef(scd, "IED_NAME1", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1"); + TExtRef extRef1 = findExtRef(scd, "IED_NAME1", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"); assertThat(extRef1.getIedName()).isEqualTo("IED_NAME1"); - TExtRef extRef2 = findExtRef(scd, "IED_NAME2", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1"); + TExtRef extRef2 = findExtRef(scd, "IED_NAME2", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"); assertThat(extRef2.getIedName()).isEqualTo("IED_NAME2"); - TExtRef extRef3 = findExtRef(scd, "IED_NAME3", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1"); + TExtRef extRef3 = findExtRef(scd, "IED_NAME3", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"); assertThat(extRef3.getIedName()).isEqualTo("IED_NAME1"); assertExtRefIsBoundAccordingTOLDEPF(extRef1, channel); @@ -138,7 +139,7 @@ void manageBindingForLDEPF_when_internalBindingMatchEPFChannel_should_update_suc // Then assertThat(sclReportItems).isEmpty(); SclTestMarshaller.assertIsMarshallable(new SclRootAdapter(scd).getCurrentElem()); - TExtRef extRef1 = findExtRef(scd, "IED_NAME1", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1"); + TExtRef extRef1 = findExtRef(scd, "IED_NAME1", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"); assertThat(extRef1.getIedName()).isEqualTo("IED_NAME1"); assertExtRefIsBoundAccordingTOLDEPF(extRef1, channel); @@ -201,13 +202,13 @@ void manageBindingForLDEPF_when_manyIedSourceFound_should_return_reportMassages( // Then assertThat(sclReportItems).hasSize(2) .extracting(SclReportItem::message) - .isEqualTo(List.of("There is more than one IED source to bind the signal /IED@name=IED_NAME2/LDevice@inst=LDEPF/LN0/ExtRef@desc=DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1", - "There is more than one IED source to bind the signal /IED@name=IED_NAME3/LDevice@inst=LDEPF/LN0/ExtRef@desc=DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1")); - TExtRef extRef1 = findExtRef(scd, "IED_NAME1", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1"); + .isEqualTo(List.of("There is more than one IED source to bind the signal /IED@name=IED_NAME2/LDevice@inst=LDEPF/LN0/ExtRef@desc=DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1", + "There is more than one IED source to bind the signal /IED@name=IED_NAME3/LDevice@inst=LDEPF/LN0/ExtRef@desc=DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1")); + TExtRef extRef1 = findExtRef(scd, "IED_NAME1", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"); assertThat(extRef1.isSetIedName()).isTrue(); - TExtRef extRef2 = findExtRef(scd, "IED_NAME2", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1"); + TExtRef extRef2 = findExtRef(scd, "IED_NAME2", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"); assertThat(extRef2.isSetIedName()).isFalse(); - TExtRef extRef3 = findExtRef(scd, "IED_NAME3", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1"); + TExtRef extRef3 = findExtRef(scd, "IED_NAME3", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"); assertThat(extRef3.isSetIedName()).isFalse(); AbstractLNAdapter lnRbdr = findLn(scd, "IED_NAME2", "LDEPF", "RBDR", "1", ""); @@ -241,8 +242,8 @@ void manageBindingForLDEPF_when_extRefMatchFlowKindInternalOrExternal_should_upd analogueChannel1WithBayInternalScope.setChannelType(TChannelType.ANALOG); analogueChannel1WithBayInternalScope.setChannelNum("1"); analogueChannel1WithBayInternalScope.setChannelShortLabel("V0"); - analogueChannel1WithBayInternalScope.setChannelLevMod(TChannelLevMod.NA); - analogueChannel1WithBayInternalScope.setChannelLevModQ(TChannelLevMod.NA); + analogueChannel1WithBayInternalScope.setChannelLevMod(TChannelLevMod.POSITIVE_OR_RISING); + analogueChannel1WithBayInternalScope.setChannelLevModQ(TChannelLevMod.OTHER); analogueChannel1WithBayInternalScope.setBAPVariant("8"); analogueChannel1WithBayInternalScope.setBAPIgnoredValue("N/A"); analogueChannel1WithBayInternalScope.setIEDType("SAMU"); @@ -262,8 +263,8 @@ void manageBindingForLDEPF_when_extRefMatchFlowKindInternalOrExternal_should_upd analogueChannel10WithBayExternalBayScope.setChannelType(TChannelType.ANALOG); analogueChannel10WithBayExternalBayScope.setChannelNum("10"); analogueChannel10WithBayExternalBayScope.setChannelShortLabel("U101"); - analogueChannel10WithBayExternalBayScope.setChannelLevMod(TChannelLevMod.NA); - analogueChannel10WithBayExternalBayScope.setChannelLevModQ(TChannelLevMod.NA); + analogueChannel10WithBayExternalBayScope.setChannelLevMod(TChannelLevMod.POSITIVE_OR_RISING); + analogueChannel10WithBayExternalBayScope.setChannelLevModQ(TChannelLevMod.OTHER); analogueChannel10WithBayExternalBayScope.setBAPVariant("8"); analogueChannel10WithBayExternalBayScope.setBAPIgnoredValue("N/A"); analogueChannel10WithBayExternalBayScope.setIEDType("SAMU"); @@ -299,7 +300,7 @@ void manageBindingForLDEPF_when_extRefMatchFlowKindInternalOrExternal_should_upd .isEqualTo("V0"); assertThat(getDaiValue(lnRadr, LEVMOD_DO_NAME, SETVAL_DA_NAME)) .isNotEqualTo("setVal_old_val") - .isEqualTo("NA"); + .isEqualTo("Positive or Rising"); assertThat(getDaiValue(lnRadr, MOD_DO_NAME, STVAL_DA_NAME)) .isNotEqualTo("off") .isEqualTo("on"); @@ -313,7 +314,7 @@ void manageBindingForLDEPF_when_extRefMatchFlowKindInternalOrExternal_should_upd .isEqualTo("V0"); assertThat(getDaiValue(lnAradr, LEVMOD_DO_NAME, SETVAL_DA_NAME)) .isNotEqualTo("setVal_old_val") - .isEqualTo("NA"); + .isEqualTo("Other"); assertThat(getDaiValue(lnAradr, MOD_DO_NAME, STVAL_DA_NAME)) .isNotEqualTo("off") .isEqualTo("on"); @@ -355,11 +356,11 @@ void manageBindingForLDEPF_when_DOI_Mod_and_DAI_stVal_notExists_should_precede() List sclReportItems = extRefEditorService.manageBindingForLDEPF(scd, epf); // Then assertThat(sclReportItems).isEmpty(); - TExtRef extRef1 = findExtRef(scd, "IED_NAME1", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1"); + TExtRef extRef1 = findExtRef(scd, "IED_NAME1", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"); assertThat(extRef1.getIedName()).isEqualTo("IED_NAME1"); - TExtRef extRef2 = findExtRef(scd, "IED_NAME2", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1"); + TExtRef extRef2 = findExtRef(scd, "IED_NAME2", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"); assertThat(extRef2.getIedName()).isEqualTo("IED_NAME2"); - TExtRef extRef3 = findExtRef(scd, "IED_NAME3", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1"); + TExtRef extRef3 = findExtRef(scd, "IED_NAME3", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"); assertThat(extRef3.getIedName()).isEqualTo("IED_NAME1"); assertExtRefIsBoundAccordingTOLDEPF(extRef1, channel); @@ -396,11 +397,11 @@ void manageBindingForLDEPF_when_LDEPF_NotActive_should_precede() { List sclReportItems = extRefEditorService.manageBindingForLDEPF(scd, epf); // Then assertThat(sclReportItems).isEmpty(); - TExtRef extRef1 = findExtRef(scd, "IED_NAME1", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1"); + TExtRef extRef1 = findExtRef(scd, "IED_NAME1", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"); assertThat(extRef1.getIedName()).isEqualTo("IED_NAME1"); - TExtRef extRef2 = findExtRef(scd, "IED_NAME2", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1"); + TExtRef extRef2 = findExtRef(scd, "IED_NAME2", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"); assertThat(extRef2.getIedName()).isEqualTo("IED_NAME2"); - TExtRef extRef3 = findExtRef(scd, "IED_NAME3", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1"); + TExtRef extRef3 = findExtRef(scd, "IED_NAME3", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"); assertThat(extRef3.getIedName()).isEqualTo("IED_NAME1"); assertExtRefIsBoundAccordingTOLDEPF(extRef1, channel); @@ -709,4 +710,106 @@ void epfPostProcessing_when_exist_unused_channel_should_update_setSrcRef() { softly.assertThat(setSrcRefInInRef4.get().getVal().getFirst().getValue()).isEqualTo("IED_NAME1LDEPF/LPHD0.Proxy"); softly.assertAll(); } + + @ParameterizedTest() + @CsvSource({"'',''", "NA,NA"}) + void manageBindingForLDEPF_should_not_update_dai_setVal_when_channelLevMod_or_channelLevModq_are_empty_or_NA(String channelLevMod, String channelLevModq) { + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ldepf/scd_ldepf_processing_bind_dai_update.xml"); + TChannel digitalChannel = new TChannel(); + digitalChannel.setBayScope(TCBScopeType.BAY_INTERNAL); + digitalChannel.setChannelType(TChannelType.DIGITAL); + digitalChannel.setChannelNum("1"); + digitalChannel.setChannelShortLabel("MR.PX1"); + if(!channelLevMod.isEmpty()){ + digitalChannel.setChannelLevMod(TChannelLevMod.valueOf(channelLevMod)); + } + if(!channelLevModq.isEmpty()){ + digitalChannel.setChannelLevModQ(TChannelLevMod.valueOf(channelLevModq)); + } + digitalChannel.setIEDType("BCU"); + digitalChannel.setIEDRedundancy(TIEDredundancy.NONE); + digitalChannel.setIEDSystemVersionInstance("1"); + digitalChannel.setLDInst("LDPX"); + digitalChannel.setLNClass("PTRC"); + digitalChannel.setLNInst("0"); + digitalChannel.setDOName("Str"); + digitalChannel.setDOInst("0"); + digitalChannel.setDAName("general"); + + TChannel analogChannel = new TChannel(); + analogChannel.setBayScope(TCBScopeType.BAY_INTERNAL); + analogChannel.setChannelType(TChannelType.ANALOG); + analogChannel.setChannelNum("1"); + analogChannel.setChannelShortLabel("MR.PX1"); + if(!channelLevMod.isEmpty()){ + analogChannel.setChannelLevMod(TChannelLevMod.valueOf(channelLevMod)); + } + if(!channelLevModq.isEmpty()){ + analogChannel.setChannelLevModQ(TChannelLevMod.valueOf(channelLevModq)); + } + analogChannel.setIEDType("BCU"); + analogChannel.setIEDRedundancy(TIEDredundancy.NONE); + analogChannel.setIEDSystemVersionInstance("1"); + analogChannel.setLDInst("LDPX"); + analogChannel.setLNClass("PTRC"); + analogChannel.setLNInst("0"); + analogChannel.setDOName("Str"); + analogChannel.setDOInst("0"); + analogChannel.setDAName("general"); + + EPF epf = new EPF(); + Channels channels = new Channels(); + channels.getChannel().addAll(List.of(digitalChannel, analogChannel)); + epf.setChannels(channels); + // When + List sclReportItems = extRefEditorService.manageBindingForLDEPF(scd, epf); + // Then + assertThat(sclReportItems).isEmpty(); + assertThat(scd.getIED()) + .filteredOn(tied -> tied.getName().equals("IED_NAME1")) + .flatExtracting(TIED::getAccessPoint) + .extracting(TAccessPoint::getServer) + .flatExtracting(TServer::getLDevice) + .filteredOn(tlDevice -> tlDevice.getInst().equals(LDEVICE_LDEPF)) + //LN class RBDR: with and without prefix 'b' + .allSatisfy(tlDevice -> { + assertThat(tlDevice.getLN()) + .filteredOn(tln -> tln.getLnClass().contains("RBDR") && tln.getInst().equals("1") && !tln.isSetPrefix()) + .allSatisfy(tln -> { + assertThat(getDaiValue(tln, CHNUM1_DO_NAME, DU_DA_NAME)).isEqualTo("MR.PX1"); + assertThat(getDaiValue(tln, MOD_DO_NAME, STVAL_DA_NAME)).isEqualTo("on"); + assertThat(getDaiValue(tln, LEVMOD_DO_NAME, SETVAL_DA_NAME)).isEqualTo("ADF"); + assertThat(getDaiValue(tln, SRCREF_DO_NAME, SETSRCREF_DA_NAME)).isEqualTo("IED_NAME1LDPX/PTRC0.Str.general"); + }); + assertThat(tlDevice.getLN()) + .filteredOn(tln -> tln.getLnClass().contains("RBDR") && tln.getInst().equals("1") && tln.getPrefix().equals("b")) + .allSatisfy(tln -> { + assertThat(getDaiValue(tln, CHNUM1_DO_NAME, DU_DA_NAME)).isEqualTo("MR.PX1"); + assertThat(getDaiValue(tln, MOD_DO_NAME, STVAL_DA_NAME)).isEqualTo("on"); + assertThat(getDaiValue(tln, LEVMOD_DO_NAME, SETVAL_DA_NAME)).isEqualTo("ADF"); + assertThat(getDaiValue(tln, SRCREF_DO_NAME, SETSRCREF_DA_NAME)).isEqualTo("IED_NAME1LDPX/PTRC0.Str.q"); + }); + }) + //LN class RADR: with and without prefix 'a' + .allSatisfy(tlDevice -> { + assertThat(tlDevice.getLN()) + .filteredOn(tln -> tln.getLnClass().contains("RADR") && tln.getInst().equals("1") && !tln.isSetPrefix()) + .allSatisfy(tln -> { + assertThat(getDaiValue(tln, CHNUM1_DO_NAME, DU_DA_NAME)).isEqualTo("MR.PX1"); + assertThat(getDaiValue(tln, MOD_DO_NAME, STVAL_DA_NAME)).isEqualTo("on"); + assertThat(getDaiValue(tln, LEVMOD_DO_NAME, SETVAL_DA_NAME)).isEqualTo("ADF"); + assertThat(getDaiValue(tln, SRCREF_DO_NAME, SETSRCREF_DA_NAME)).isEqualTo("IED_NAME1LDPX/PTRC0.Str.general"); + }); + assertThat(tlDevice.getLN()) + .filteredOn(tln -> tln.getLnClass().contains("RBDR") && tln.getInst().equals("1") && tln.getPrefix().equals("a")) + .allSatisfy(tln -> { + assertThat(getDaiValue(tln, CHNUM1_DO_NAME, DU_DA_NAME)).isEqualTo("MR.PX1"); + assertThat(getDaiValue(tln, MOD_DO_NAME, STVAL_DA_NAME)).isEqualTo("on"); + assertThat(getDaiValue(tln, LEVMOD_DO_NAME, SETVAL_DA_NAME)).isEqualTo("ADF"); + assertThat(getDaiValue(tln, SRCREF_DO_NAME, SETSRCREF_DA_NAME)).isEqualTo("IED_NAME1LDPX/PTRC0.Str.q"); + }); + }); + } + } 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 6ca8329cb..dea68e04c 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 @@ -233,17 +233,18 @@ public static String getDaiValue(AbstractLNAdapter ln, String doiName, String return ln.getDOIAdapterByName(doiName).getDataAdapterByName(daiName).getCurrentElem().getVal().getFirst().getValue(); } - public static Stream streamAllConnectedApGseP(SCL scd, String pType) { - return scd.getCommunication().getSubNetwork().stream() - .map(TSubNetwork::getConnectedAP) - .flatMap(List::stream) - .map(TConnectedAP::getGSE) - .flatMap(List::stream) - .map(TControlBlock::getAddress) - .map(TAddress::getP) - .flatMap(List::stream) - .filter(tp -> pType.equals(tp.getType())) - .map(TP::getValue); + public static Stream getDai(TAnyLN tAnyLN, String doiName, String daiName) { + return tAnyLN.getDOI().stream().filter(tdoi -> tdoi.getName().equals(doiName)) + .flatMap(tdoi -> tdoi.getSDIOrDAI().stream()) + .filter(TDAI.class::isInstance) + .map(TDAI.class::cast) + .filter(tdai -> daiName.equals(tdai.getName())); + } + + public static String getDaiValue(TAnyLN tAnyLN, String doiName, String daiName) { + TDAI tdai = getDai(tAnyLN, doiName, daiName).findFirst() + .orElseThrow(() -> new AssertionFailedError(String.format("DAI %s.%s not found in LN", doiName, daiName))); + return getValue(tdai); } public static SclRootAdapter createSclRootAdapterWithIed(String iedName) { diff --git a/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_extref_with_IedType_BCU.xml b/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_extref_with_IedType_BCU.xml index 63a3ce64d..fcc4e3fc9 100644 --- a/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_extref_with_IedType_BCU.xml +++ b/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_extref_with_IedType_BCU.xml @@ -31,19 +31,19 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_iedSources_in_different_bay.xml b/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_iedSources_in_different_bay.xml index 91f433303..5f336a57c 100644 --- a/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_iedSources_in_different_bay.xml +++ b/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_iedSources_in_different_bay.xml @@ -31,7 +31,7 @@ + desc="DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"/> @@ -146,7 +146,7 @@ - + @@ -190,7 +190,7 @@ - + diff --git a/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_manyIedSources_in_same_bay.xml b/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_manyIedSources_in_same_bay.xml index a4b0d299b..bc2ea5083 100644 --- a/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_manyIedSources_in_same_bay.xml +++ b/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_manyIedSources_in_same_bay.xml @@ -31,7 +31,7 @@ + desc="DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"/> @@ -71,7 +71,7 @@ + desc="DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"/> @@ -154,7 +154,7 @@ - + diff --git a/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_processing_bind_dai_update.xml b/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_processing_bind_dai_update.xml new file mode 100644 index 000000000..9ea6a685e --- /dev/null +++ b/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_processing_bind_dai_update.xml @@ -0,0 +1,223 @@ + + + + + + + SCD + +
+ + + + + + + + + + + + + + + + + + on + + + + + + + + + + + + ADF + + + + + + ADF + + + + + + off + + + + + + ADF + + + + + + + + ADF + + + + + + ADF + + + + + + off + + + + + + ADF + + + + + + + + + ADF + + + + + ADF + + + Source reference of the channel among LDEPF input signals + + + + + ADF + + + + + ADF + + + + + + + ADF + + + + + ADF + + + Source reference of the channel among LDEPF input signals + + + + + ADF + + + + + ADF + + + + + + + + + on + + + + + + + + + off + + + + + + + + + off + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + on + off + blocked + test + test/blocked + + + \ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_withoutModStValInDataTypeTemplate.xml b/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_withoutModStValInDataTypeTemplate.xml index befdc3bb3..3a2a713c1 100644 --- a/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_withoutModStValInDataTypeTemplate.xml +++ b/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_withoutModStValInDataTypeTemplate.xml @@ -31,7 +31,7 @@ + desc="DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"/> @@ -87,7 +87,7 @@ - + @@ -125,7 +125,7 @@ - + diff --git a/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_withoutModStValInLN0.xml b/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_withoutModStValInLN0.xml index 8913663fb..8391441ed 100644 --- a/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_withoutModStValInLN0.xml +++ b/sct-commons/src/test/resources/scd-ldepf/scd_ldepf_withoutModStValInLN0.xml @@ -26,7 +26,7 @@ + desc="DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"/> @@ -77,7 +77,7 @@ - + @@ -110,7 +110,7 @@ - + diff --git a/sct-commons/src/test/resources/scd-ldepf/scd_with_inactive_ldevice_ldepf.xml b/sct-commons/src/test/resources/scd-ldepf/scd_with_inactive_ldevice_ldepf.xml index f85ff6180..598e8f845 100644 --- a/sct-commons/src/test/resources/scd-ldepf/scd_with_inactive_ldevice_ldepf.xml +++ b/sct-commons/src/test/resources/scd-ldepf/scd_with_inactive_ldevice_ldepf.xml @@ -31,7 +31,7 @@ + desc="DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1"/> @@ -87,7 +87,7 @@ - + @@ -125,7 +125,7 @@ - +