Skip to content

Commit 1589a2d

Browse files
committed
feat: LDEPF should not be configured when inactive, closes #501
Signed-off-by: Samir Romdhani <[email protected]>
1 parent fb08a20 commit 1589a2d

10 files changed

+304
-486
lines changed

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefEditorService.java

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
@RequiredArgsConstructor
3737
public class ExtRefEditorService implements ExtRefEditor {
3838
private static final String INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO = "Invalid or missing attributes in ExtRef binding info";
39+
private static final String COMPAS_LNODE_STATUS = "COMPAS-LNodeStatus";
3940
private static final List<DoNameAndDaName> DO_DA_MAPPINGS = List.of(
4041
new DoNameAndDaName(CHNUM1_DO_NAME, DU_DA_NAME),
4142
new DoNameAndDaName(LEVMOD_DO_NAME, SETVAL_DA_NAME),
@@ -46,7 +47,6 @@ public class ExtRefEditorService implements ExtRefEditor {
4647
private final IedService iedService;
4748
private final LdeviceService ldeviceService;
4849
private final LnEditor lnEditor;
49-
private final DataTypeTemplatesService dataTypeTemplatesService;
5050

5151
@Getter
5252
private final List<SclReportItem> errorHandler = new ArrayList<>();
@@ -89,8 +89,7 @@ private List<TIED> getIedSources(SclRootAdapter sclRootAdapter, TCompasBay compa
8989
*
9090
* @return list of ExtRef and associated Bay
9191
*/
92-
private List<ExtRefInfo.ExtRefWithBayReference> getExtRefWithBayReferenceInLDEPF(TDataTypeTemplates dataTypeTemplates, TIED tied, final TLDevice tlDevice) {
93-
List<ExtRefInfo.ExtRefWithBayReference> extRefBayReferenceList = new ArrayList<>();
92+
private List<ExtRefInfo.ExtRefWithBayReference> getExtRefWithBayReferenceInLDEPF(TIED tied, final TLDevice tlDevice) {
9493
String lDevicePath = "SCL/IED[@name=\"" + tied.getName() + "\"]/AccessPoint/Server/LDevice[@inst=\"" + tlDevice.getInst() + "\"]";
9594
Optional<TCompasBay> tCompasBay = PrivateUtils.extractCompasPrivate(tied, TCompasBay.class);
9695
if (tCompasBay.isEmpty()) {
@@ -100,16 +99,9 @@ private List<ExtRefInfo.ExtRefWithBayReference> getExtRefWithBayReferenceInLDEPF
10099
}
101100
return Collections.emptyList();
102101
}
103-
104-
if (dataTypeTemplatesService.isDoModAndDaStValExist(dataTypeTemplates, tlDevice.getLN0().getLnType())) {
105-
extRefBayReferenceList.addAll(tlDevice.getLN0()
106-
.getInputs()
107-
.getExtRef().stream()
108-
.map(extRef -> new ExtRefInfo.ExtRefWithBayReference(tied.getName(), tCompasBay.get(), extRef)).toList());
109-
} else {
110-
errorHandler.add(SclReportItem.error(lDevicePath, "DO@name=Mod/DA@name=stVal not found in DataTypeTemplate"));
111-
}
112-
return extRefBayReferenceList;
102+
return tlDevice.getLN0().getInputs().getExtRef().stream()
103+
.map(extRef -> new ExtRefInfo.ExtRefWithBayReference(tied.getName(), tCompasBay.get(), extRef))
104+
.toList();
113105
}
114106

115107
/**
@@ -277,14 +269,15 @@ public List<SclReportItem> manageBindingForLDEPF(SCL scd, EPF epf) {
277269
SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
278270
if (!epf.isSetChannels()) return errorHandler;
279271
iedService.getFilteredIeds(scd, ied -> !ied.getName().contains("TEST"))
280-
.forEach(tied -> ldeviceService.findLdevice(tied, LDEVICE_LDEPF)
281-
.ifPresent(tlDevice -> getExtRefWithBayReferenceInLDEPF(scd.getDataTypeTemplates(), tied, tlDevice)
272+
.forEach(tied -> ldeviceService.findLdevice(tied, tlDevice -> tlDevice.getInst().equals(LDEVICE_LDEPF))
273+
.filter(ldepfLdevice -> PrivateUtils.extractStringPrivate(ldepfLdevice.getLN0(), COMPAS_LNODE_STATUS).map(status -> !status.equals("off")).orElse(false))
274+
.ifPresent(ldepfLdevice -> getExtRefWithBayReferenceInLDEPF(tied, ldepfLdevice)
282275
.forEach(extRefBayRef -> epf.getChannels().getChannel().stream().filter(tChannel -> doesExtRefMatchLDEPFChannel(extRefBayRef.extRef(), tChannel))
283276
.findFirst().ifPresent(channel -> {
284277
List<TIED> iedSources = getIedSources(sclRootAdapter, extRefBayRef.compasBay(), channel);
285278
if (iedSources.size() == 1) {
286279
updateLDEPFExtRefBinding(extRefBayRef.extRef(), iedSources.getFirst(), channel);
287-
LDeviceAdapter lDeviceAdapter = new LDeviceAdapter(new IEDAdapter(sclRootAdapter, tied.getName()), tlDevice);
280+
LDeviceAdapter lDeviceAdapter = new LDeviceAdapter(new IEDAdapter(sclRootAdapter, tied.getName()), ldepfLdevice);
288281
updateLDEPFDos(lDeviceAdapter, extRefBayRef.extRef(), channel);
289282
} else {
290283
if (iedSources.size() > 1) {

sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ExtRefEditorServiceTest.java

Lines changed: 70 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package org.lfenergy.compas.sct.commons;
66

77
import org.assertj.core.api.SoftAssertions;
8-
import org.assertj.core.groups.Tuple;
98
import org.junit.jupiter.api.BeforeEach;
109
import org.junit.jupiter.api.Tag;
1110
import org.junit.jupiter.api.Test;
@@ -20,6 +19,7 @@
2019
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
2120
import org.lfenergy.compas.sct.commons.scl.ln.AbstractLNAdapter;
2221
import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller;
22+
import org.lfenergy.compas.sct.commons.util.PrivateEnum;
2323

2424
import java.util.List;
2525
import java.util.Optional;
@@ -37,7 +37,7 @@ class ExtRefEditorServiceTest {
3737

3838
@BeforeEach
3939
void init() {
40-
extRefEditorService = new ExtRefEditorService(new IedService(), new LdeviceService(new LnService()), new LnService(), new DataTypeTemplatesService());
40+
extRefEditorService = new ExtRefEditorService(new IedService(), new LdeviceService(new LnService()), new LnService());
4141
}
4242

4343
@Test
@@ -327,111 +327,6 @@ void manageBindingForLDEPF_when_extRefMatchFlowKindInternalOrExternal_should_upd
327327
assertExtRefIsBoundAccordingTOLDEPF(extRefBindExternally, analogueChannel10WithBayExternalBayScope);
328328
}
329329

330-
@Test
331-
void manageBindingForLDEPF_when_DOI_Mod_and_DAI_stVal_notExists_should_precede() {
332-
// Given
333-
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ldepf/scd_ldepf_withoutModStValInLN0.xml");
334-
// When
335-
TChannel channel = new TChannel();
336-
channel.setBayScope(TCBScopeType.BAY_INTERNAL);
337-
channel.setChannelType(TChannelType.DIGITAL);
338-
channel.setChannelNum("1");
339-
channel.setChannelShortLabel("MR.PX1");
340-
channel.setChannelLevMod(TChannelLevMod.POSITIVE_OR_RISING);
341-
channel.setChannelLevModQ(TChannelLevMod.OTHER);
342-
channel.setIEDType("BCU");
343-
channel.setIEDRedundancy(TIEDredundancy.NONE);
344-
channel.setIEDSystemVersionInstance("1");
345-
channel.setLDInst("LDPX");
346-
channel.setLNClass("PTRC");
347-
channel.setLNInst("0");
348-
channel.setDOName("Str");
349-
channel.setDOInst("0");
350-
channel.setDAName("general");
351-
352-
EPF epf = new EPF();
353-
Channels channels = new Channels();
354-
channels.getChannel().add(channel);
355-
epf.setChannels(channels);
356-
List<SclReportItem> sclReportItems = extRefEditorService.manageBindingForLDEPF(scd, epf);
357-
// Then
358-
assertThat(sclReportItems).isEmpty();
359-
TExtRef extRef1 = findExtRef(scd, "IED_NAME1", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1");
360-
assertThat(extRef1.getIedName()).isEqualTo("IED_NAME1");
361-
TExtRef extRef2 = findExtRef(scd, "IED_NAME2", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1");
362-
assertThat(extRef2.getIedName()).isEqualTo("IED_NAME2");
363-
TExtRef extRef3 = findExtRef(scd, "IED_NAME3", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1");
364-
assertThat(extRef3.getIedName()).isEqualTo("IED_NAME1");
365-
366-
assertExtRefIsBoundAccordingTOLDEPF(extRef1, channel);
367-
assertExtRefIsBoundAccordingTOLDEPF(extRef2, channel);
368-
assertExtRefIsBoundAccordingTOLDEPF(extRef3, channel);
369-
}
370-
371-
@Test
372-
void manageBindingForLDEPF_when_LDEPF_NotActive_should_precede() {
373-
//Given
374-
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ldepf/scd_with_inactive_ldevice_ldepf.xml");
375-
TChannel channel = new TChannel();
376-
channel.setBayScope(TCBScopeType.BAY_INTERNAL);
377-
channel.setChannelType(TChannelType.DIGITAL);
378-
channel.setChannelNum("1");
379-
channel.setChannelShortLabel("MR.PX1");
380-
channel.setChannelLevMod(TChannelLevMod.POSITIVE_OR_RISING);
381-
channel.setChannelLevModQ(TChannelLevMod.OTHER);
382-
channel.setIEDType("BCU");
383-
channel.setIEDRedundancy(TIEDredundancy.NONE);
384-
channel.setIEDSystemVersionInstance("1");
385-
channel.setLDInst("LDPX");
386-
channel.setLNClass("PTRC");
387-
channel.setLNInst("0");
388-
channel.setDOName("Str");
389-
channel.setDOInst("0");
390-
channel.setDAName("general");
391-
392-
EPF epf = new EPF();
393-
Channels channels = new Channels();
394-
channels.getChannel().add(channel);
395-
epf.setChannels(channels);
396-
// When
397-
List<SclReportItem> sclReportItems = extRefEditorService.manageBindingForLDEPF(scd, epf);
398-
// Then
399-
assertThat(sclReportItems).isEmpty();
400-
TExtRef extRef1 = findExtRef(scd, "IED_NAME1", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1");
401-
assertThat(extRef1.getIedName()).isEqualTo("IED_NAME1");
402-
TExtRef extRef2 = findExtRef(scd, "IED_NAME2", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1");
403-
assertThat(extRef2.getIedName()).isEqualTo("IED_NAME2");
404-
TExtRef extRef3 = findExtRef(scd, "IED_NAME3", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEAN_1_general_1");
405-
assertThat(extRef3.getIedName()).isEqualTo("IED_NAME1");
406-
407-
assertExtRefIsBoundAccordingTOLDEPF(extRef1, channel);
408-
assertExtRefIsBoundAccordingTOLDEPF(extRef2, channel);
409-
assertExtRefIsBoundAccordingTOLDEPF(extRef3, channel);
410-
}
411-
412-
@Test
413-
void manageBindingForLDEPF_when_DO_Mod_and_DA_stVal_NotFoundInDataTypeTemplate_should_return_error() {
414-
// Given
415-
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ldepf/scd_ldepf_withoutModStValInDataTypeTemplate.xml");
416-
// When
417-
EPF epf = new EPF();
418-
epf.setChannels(new Channels());
419-
List<SclReportItem> sclReportItems = extRefEditorService.manageBindingForLDEPF(scd, epf);
420-
// Then
421-
assertThat(sclReportItems).hasSize(3);
422-
assertThat(sclReportItems)
423-
.extracting(SclReportItem::message, SclReportItem::xpath)
424-
.containsExactly(
425-
Tuple.tuple("DO@name=Mod/DA@name=stVal not found in DataTypeTemplate",
426-
"SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LDEPF\"]"),
427-
Tuple.tuple("DO@name=Mod/DA@name=stVal not found in DataTypeTemplate",
428-
"SCL/IED[@name=\"IED_NAME2\"]/AccessPoint/Server/LDevice[@inst=\"LDEPF\"]"),
429-
Tuple.tuple("DO@name=Mod/DA@name=stVal not found in DataTypeTemplate",
430-
"SCL/IED[@name=\"IED_NAME3\"]/AccessPoint/Server/LDevice[@inst=\"LDEPF\"]")
431-
);
432-
}
433-
434-
435330
private void assertExtRefIsBoundAccordingTOLDEPF(TExtRef extRef, TChannel setting) {
436331
assertThat(extRef.getLdInst()).isEqualTo(setting.getLDInst());
437332
assertThat(extRef.getLnClass()).contains(setting.getLNClass());
@@ -812,4 +707,72 @@ void manageBindingForLDEPF_should_not_update_dai_setVal_when_channelLevMod_or_ch
812707
});
813708
}
814709

710+
@Test
711+
void manageBindingForLDEPF_should_return_error_report_when_missing_mandatory_privates() {
712+
//Given
713+
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ldepf/scd_ldepf_processing_bind_dai_update.xml");
714+
scd.getIED().forEach(tied -> tied.getPrivate().removeIf(tPrivate -> tPrivate.getType().equals(PrivateEnum.COMPAS_BAY.getPrivateType())
715+
|| tPrivate.getType().equals(PrivateEnum.COMPAS_ICDHEADER.getPrivateType())));
716+
717+
TChannel digitalChannel = new TChannel();
718+
digitalChannel.setBayScope(TCBScopeType.BAY_INTERNAL);
719+
digitalChannel.setChannelType(TChannelType.DIGITAL);
720+
digitalChannel.setChannelNum("1");
721+
digitalChannel.setChannelShortLabel("MR.PX1");
722+
digitalChannel.setChannelLevMod(TChannelLevMod.POSITIVE_OR_RISING);
723+
digitalChannel.setChannelLevModQ(TChannelLevMod.OTHER);
724+
digitalChannel.setIEDType("BCU");
725+
digitalChannel.setIEDRedundancy(TIEDredundancy.NONE);
726+
digitalChannel.setIEDSystemVersionInstance("1");
727+
digitalChannel.setLDInst("LDPX");
728+
digitalChannel.setLNClass("PTRC");
729+
digitalChannel.setLNInst("0");
730+
digitalChannel.setDOName("Str");
731+
digitalChannel.setDOInst("0");
732+
digitalChannel.setDAName("general");
733+
EPF epf = new EPF();
734+
Channels channels = new Channels();
735+
channels.getChannel().add(digitalChannel);
736+
epf.setChannels(channels);
737+
// When
738+
List<SclReportItem> sclReportItems = extRefEditorService.manageBindingForLDEPF(scd, epf);
739+
// Then
740+
assertThat(sclReportItems).containsExactly(SclReportItem.error("SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LDEPF\"]", "The IED has no Private Bay"),
741+
SclReportItem.error("SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LDEPF\"]", "The IED has no Private compas:ICDHeader"));
742+
}
743+
744+
@Test
745+
void manageBindingForLDEPF_should_not_been_configured_when_ldepf_ln0_is_off() {
746+
//Given
747+
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ldepf/scd_ldepf_processing_when_status_ln0_off.xml");
748+
TChannel digitalChannel = new TChannel();
749+
digitalChannel.setBayScope(TCBScopeType.BAY_INTERNAL);
750+
digitalChannel.setChannelType(TChannelType.DIGITAL);
751+
digitalChannel.setChannelNum("1");
752+
digitalChannel.setChannelShortLabel("MR.PX1");
753+
digitalChannel.setChannelLevMod(TChannelLevMod.POSITIVE_OR_RISING);
754+
digitalChannel.setChannelLevModQ(TChannelLevMod.OTHER);
755+
digitalChannel.setIEDType("BCU");
756+
digitalChannel.setIEDRedundancy(TIEDredundancy.NONE);
757+
digitalChannel.setIEDSystemVersionInstance("1");
758+
digitalChannel.setLDInst("LDPX");
759+
digitalChannel.setLNClass("PTRC");
760+
digitalChannel.setLNInst("0");
761+
digitalChannel.setDOName("Str");
762+
digitalChannel.setDOInst("0");
763+
digitalChannel.setDAName("general");
764+
EPF epf = new EPF();
765+
Channels channels = new Channels();
766+
channels.getChannel().add(digitalChannel);
767+
epf.setChannels(channels);
768+
// When
769+
List<SclReportItem> sclReportItems = extRefEditorService.manageBindingForLDEPF(scd, epf);
770+
// Then
771+
assertThat(sclReportItems).isEmpty();
772+
assertThat(scd)
773+
.usingRecursiveComparison()
774+
.isEqualTo(SclTestMarshaller.getSCLFromFile("/scd-ldepf/scd_ldepf_processing_when_status_ln0_off.xml"));
775+
}
776+
777+
815778
}

sct-commons/src/test/resources/scd-ldepf/scd_ldepf_dataTypeTemplateValid.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<Authentication/>
2525
<LDevice inst="LDEPF" ldName="IED_NAME1LDEPF">
2626
<LN0 lnClass="LLN0" inst="" lnType="LLN0_ID1">
27+
<Private type="COMPAS-LNodeStatus">on</Private>
2728
<DOI name="Mod">
2829
<DAI name="stVal" valImport="true">
2930
<Val>on</Val>
@@ -117,6 +118,7 @@
117118
<Authentication/>
118119
<LDevice inst="LDPHAS1" ldName="IED_NAME2LDPHAS1">
119120
<LN0 lnClass="LLN0" inst="" lnType="LLN0_ID1">
121+
<Private type="COMPAS-LNodeStatus">on</Private>
120122
<DOI name="Mod">
121123
<DAI name="stVal">
122124
<Val>on</Val>

sct-commons/src/test/resources/scd-ldepf/scd_ldepf_extref_with_IedType_BCU.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<Authentication/>
2525
<LDevice inst="LDEPF" ldName="IED_NAME1LDEPF">
2626
<LN0 lnClass="LLN0" inst="" lnType="LLN0_ID1">
27+
<Private type="COMPAS-LNodeStatus">on</Private>
2728
<DOI name="Mod">
2829
<DAI name="stVal" valImport="true">
2930
<Val>on</Val>

sct-commons/src/test/resources/scd-ldepf/scd_ldepf_iedSources_in_different_bay.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<Authentication/>
2525
<LDevice inst="LDEPF" ldName="IED_NAME1LDEPF">
2626
<LN0 lnClass="LLN0" inst="" lnType="LLN0_ID1">
27+
<Private type="COMPAS-LNodeStatus">on</Private>
2728
<DOI name="Mod">
2829
<DAI name="stVal" valImport="true">
2930
<Val>on</Val>
@@ -140,6 +141,7 @@
140141
<Authentication/>
141142
<LDevice inst="LDEPF" ldName="IED_NAME2LDEPF">
142143
<LN0 lnClass="LLN0" inst="" lnType="LLN0_ID1">
144+
<Private type="COMPAS-LNodeStatus">on</Private>
143145
<DOI name="Mod">
144146
<DAI name="stVal" valImport="true">
145147
<Val>on</Val>
@@ -184,6 +186,7 @@
184186
<Authentication/>
185187
<LDevice inst="LDEPF" ldName="IED_NAME3LDEPF">
186188
<LN0 lnClass="LLN0" inst="" lnType="LLN0_ID1">
189+
<Private type="COMPAS-LNodeStatus">on</Private>
187190
<DOI name="Mod">
188191
<DAI name="stVal" valImport="true">
189192
<Val>on</Val>

sct-commons/src/test/resources/scd-ldepf/scd_ldepf_manyIedSources_in_same_bay.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<Authentication/>
2525
<LDevice inst="LDEPF" ldName="IED_NAME1LDEPF">
2626
<LN0 lnClass="LLN0" inst="" lnType="LLN0_ID1">
27+
<Private type="COMPAS-LNodeStatus">on</Private>
2728
<DOI name="Mod">
2829
<DAI name="stVal" valImport="true">
2930
<Val>on</Val>
@@ -64,6 +65,7 @@
6465
<Authentication/>
6566
<LDevice inst="LDEPF" ldName="IED_NAME2LDEPF">
6667
<LN0 lnClass="LLN0" inst="" lnType="LLN0_ID1">
68+
<Private type="COMPAS-LNodeStatus">on</Private>
6769
<DOI name="Mod">
6870
<DAI name="stVal" valImport="true">
6971
<Val>on</Val>
@@ -148,6 +150,7 @@
148150
<Authentication/>
149151
<LDevice inst="LDEPF" ldName="IED_NAME2LDEPF">
150152
<LN0 lnClass="LLN0" inst="" lnType="LLN0_ID1">
153+
<Private type="COMPAS-LNodeStatus">on</Private>
151154
<DOI name="Mod">
152155
<DAI name="stVal" valImport="true">
153156
<Val>on</Val>

sct-commons/src/test/resources/scd-ldepf/scd_ldepf_processing_bind_dai_update.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<Authentication/>
2525
<LDevice inst="LDEPF" ldName="IED_NAME1LDEPF">
2626
<LN0 lnClass="LLN0" inst="" lnType="LLN0_ID1">
27+
<Private type="COMPAS-LNodeStatus">on</Private>
2728
<DOI name="Mod">
2829
<DAI name="stVal" valImport="true">
2930
<Val>on</Val>

0 commit comments

Comments
 (0)