Skip to content

Commit 662b3da

Browse files
Merge pull request #411 from com-pas/develop
Release 0.2.26
2 parents 2d6132b + 837ff3f commit 662b3da

File tree

10 files changed

+347
-62
lines changed

10 files changed

+347
-62
lines changed

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

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

77
import lombok.RequiredArgsConstructor;
8-
import org.apache.commons.lang3.StringUtils;
98
import org.lfenergy.compas.scl2007b4.model.*;
109
import org.lfenergy.compas.sct.commons.api.ExtRefEditor;
1110
import org.lfenergy.compas.sct.commons.dto.*;
@@ -27,6 +26,7 @@
2726

2827
import java.math.BigInteger;
2928
import java.util.*;
29+
import java.util.function.BinaryOperator;
3030
import java.util.function.Function;
3131
import java.util.stream.Collectors;
3232

@@ -90,7 +90,7 @@ private static List<TIED> getIedSources(SclRootAdapter sclRootAdapter, TCompasBa
9090
*/
9191
private List<ExtRefInfo.ExtRefWithBayReference> getExtRefWithBayReferenceInLDEPF(TDataTypeTemplates dataTypeTemplates, TIED tied, final TLDevice tlDevice, final List<SclReportItem> sclReportItems) {
9292
List<ExtRefInfo.ExtRefWithBayReference> extRefBayReferenceList = new ArrayList<>();
93-
String lDevicePath = "SCL/IED[@name=\""+ tied.getName() + "\"]/AccessPoint/Server/LDevice[@inst=\"" + tlDevice.getInst() + "\"]";
93+
String lDevicePath = "SCL/IED[@name=\"" + tied.getName() + "\"]/AccessPoint/Server/LDevice[@inst=\"" + tlDevice.getInst() + "\"]";
9494
Optional<TCompasBay> tCompasBay = PrivateUtils.extractCompasPrivate(tied, TCompasBay.class);
9595
if (tCompasBay.isEmpty()) {
9696
sclReportItems.add(SclReportItem.error(lDevicePath, "The IED has no Private Bay"));
@@ -405,8 +405,7 @@ private List<SclReportItem> updateLDEPFDos(LDeviceAdapter lDeviceAdapter, TExtRe
405405
private Optional<SclReportItem> updateVal(AbstractLNAdapter<?> lnAdapter, String doName, String daName, TExtRef extRef, TChannel setting) {
406406
String value = switch (daName) {
407407
case DU_DA_NAME -> setting.getChannelShortLabel();
408-
case SETVAL_DA_NAME ->
409-
LN_PREFIX_B.equals(lnAdapter.getPrefix()) || LN_PREFIX_A.equals(lnAdapter.getPrefix()) ? setting.getChannelLevModQ().value() : setting.getChannelLevMod().value();
408+
case SETVAL_DA_NAME -> LN_PREFIX_B.equals(lnAdapter.getPrefix()) || LN_PREFIX_A.equals(lnAdapter.getPrefix()) ? setting.getChannelLevModQ().value() : setting.getChannelLevMod().value();
410409
case STVAL_DA_NAME -> ActiveStatus.ON.getValue();
411410
case SETSRCREF_DA_NAME -> computeDaiValue(lnAdapter, extRef, setting.getDAName());
412411
default -> null;
@@ -464,7 +463,7 @@ public void debindCompasFlowsAndExtRefsBasedOnVoltageLevel(SCL scd) {
464463

465464

466465
@Override
467-
public void updateIedNameBasedOnLnode(SCL scl) {
466+
public List<SclReportItem> updateIedNameBasedOnLnode(SCL scl) {
468467
Map<TopoKey, TBay> bayByTopoKey = scl.getSubstation().stream()
469468
.flatMap(tSubstation -> tSubstation.getVoltageLevel().stream())
470469
.flatMap(tVoltageLevel -> tVoltageLevel.getBay().stream())
@@ -475,6 +474,7 @@ public void updateIedNameBasedOnLnode(SCL scl) {
475474
.flatMap(Optional::stream)
476475
.collect(Collectors.toMap(BayTopoKey::topoKey, BayTopoKey::bay));
477476

477+
List<SclReportItem> sclReportItems = new ArrayList<>();
478478
scl.getIED().stream()
479479
.flatMap(ldeviceService::getLdevices)
480480
.forEach(tlDevice ->
@@ -488,9 +488,21 @@ public void updateIedNameBasedOnLnode(SCL scl) {
488488
&& Objects.equals(tlNode.getLnInst(), tCompasFlow.getExtReflnInst())
489489
&& Utils.lnClassEquals(tlNode.getLnClass(), tCompasFlow.getExtReflnClass())
490490
&& Objects.equals(tlNode.getPrefix(), tCompasFlow.getExtRefprefix()))
491+
.filter(tlNode -> {
492+
Optional<TCompasICDHeader> tCompasICDHeader = PrivateUtils.extractCompasPrivate(tlNode, TCompasICDHeader.class);
493+
if (tCompasICDHeader.isPresent()) {
494+
return Objects.equals(tCompasFlow.getFlowSourceIEDType(), tCompasICDHeader.get().getIEDType())
495+
&& Objects.equals(tCompasFlow.getFlowIEDSystemVersioninstance(), tCompasICDHeader.get().getIEDSystemVersioninstance())
496+
&& Objects.equals(tCompasFlow.getFlowSourceIEDredundancy(), tCompasICDHeader.get().getIEDredundancy());
497+
} else {
498+
sclReportItems.add(SclReportItem.error("", ("The substation LNode with following attributes : IedName:%s / LdInst:%s / LnClass:%s / LnInst:%s " +
499+
"does not contain the needed (COMPAS - ICDHeader) private")
500+
.formatted(tlNode.getIedName(), tlNode.getLdInst(), tlNode.getLnClass().getFirst(), tlNode.getLnInst())));
501+
return false;
502+
}
503+
})
491504
.map(TLNode::getIedName)
492-
.filter(StringUtils::isNotBlank)
493-
.findFirst()
505+
.reduce(checkOnlyOneIed(tCompasFlow, tBay, sclReportItems))
494506
)
495507
.ifPresentOrElse(iedName -> {
496508
extRefService.getMatchingExtRefs(tlDevice, tCompasFlow).forEach(tExtRef -> tExtRef.setIedName(iedName));
@@ -503,6 +515,17 @@ public void updateIedNameBasedOnLnode(SCL scl) {
503515
)
504516
)
505517
);
518+
return sclReportItems;
519+
}
520+
521+
private static BinaryOperator<String> checkOnlyOneIed(TCompasFlow tCompasFlow, TBay tBay, List<SclReportItem> sclReportItems) {
522+
return (iedName1, iedName2) -> {
523+
sclReportItems.add(SclReportItem.error("",
524+
("Several LNode@IedName ('%s', '%s') are found in the bay '%s' for the following compas-flow attributes :" +
525+
" @FlowSourceIEDType '%s' @FlowSourceIEDredundancy '%s' @FlowIEDSystemVersioninstance '%s'").
526+
formatted(iedName1, iedName2, tBay.getName(), tCompasFlow.getFlowSourceIEDType(), tCompasFlow.getFlowSourceIEDredundancy(), tCompasFlow.getFlowIEDSystemVersioninstance())));
527+
return iedName1;
528+
};
506529
}
507530

508531
record TopoKey(String FlowNode, BigInteger FlowNodeOrder) {

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/ExtRefEditor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ public interface ExtRefEditor {
7272

7373
/**
7474
* Update compas:Flow.ExtRefiedName and ExtRef.iedName, based on Substation LNode iedName
75+
* @param scd SCL
76+
* @return list of encoutered errors
7577
*/
76-
void updateIedNameBasedOnLnode(SCL scd);
78+
List<SclReportItem> updateIedNameBasedOnLnode(SCL scd);
7779

7880
}

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ldevice/LDeviceAdapter.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,15 +164,10 @@ public String getXPath() {
164164

165165
/**
166166
* Updates LDevice name by combining IED name and LDevice ldInst value
167-
*
168-
* @throws ScdException throws when renaming LDevice and new name has more than 33 caracteres
169167
*/
170-
public void updateLDName() throws ScdException {
168+
public void updateLDName() {
171169
String newLdName = parentAdapter.getCurrentElem().getName() + currentElem.getInst();
172-
if (newLdName.length() > 33) {
173-
throw new ScdException(newLdName + "(IED.name + LDevice.inst) has more than 33 characters");
174-
}
175-
// renaming ldName
170+
// renaming ldName; Carefull because the maximum ldevice name length is 64 based on xsd
176171
currentElem.setLdName(newLdName);
177172
}
178173

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/PrivateUtils.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,19 @@ public static TPrivate createPrivate(List<TCompasTopo> compasTopos) {
168168
return tPrivate;
169169
}
170170

171+
/**
172+
* Create private of a given type containing a simple string as value
173+
* @param privateType type attribute of private element to create
174+
* @param privateValue value of private to create
175+
* @return the complete private
176+
*/
177+
public static TPrivate createStringPrivate(String privateType, String privateValue) {
178+
TPrivate tPrivate = new TPrivate();
179+
tPrivate.setType(privateType);
180+
tPrivate.getContent().add(privateValue);
181+
return tPrivate;
182+
}
183+
171184
/**
172185
* Create Private of given type as parameter
173186
* @param jaxbElement content of Private to create

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

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ void manageBindingForLDEPF_when_DO_Mod_and_DA_stVal_NotFoundInDataTypeTemplate_s
595595
.extracting(SclReportItem::message, SclReportItem::xpath)
596596
.containsExactly(
597597
Tuple.tuple("DO@name=Mod/DA@name=stVal not found in DataTypeTemplate",
598-
"SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LDEPF\"]"),
598+
"SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LDEPF\"]"),
599599
Tuple.tuple("DO@name=Mod/DA@name=stVal not found in DataTypeTemplate",
600600
"SCL/IED[@name=\"IED_NAME2\"]/AccessPoint/Server/LDevice[@inst=\"LDEPF\"]"),
601601
Tuple.tuple("DO@name=Mod/DA@name=stVal not found in DataTypeTemplate",
@@ -865,7 +865,7 @@ void debindCompasFlowsAndExtRefsBasedOnVoltageLevel(String testCase, SCL scd, Tu
865865
.containsExactly(flow2);
866866
}
867867

868-
private static Stream<Arguments> provideFlowAndExtRefForDebinding(){
868+
private static Stream<Arguments> provideFlowAndExtRefForDebinding() {
869869
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-flow-debind/scd_extref_flow_debind_success.xml");
870870
SCL scdVoltageLevel0 = SclTestMarshaller.getSCLFromFile("/scd-extref-flow-debind/scd_extref_flow_debind_volatagelevelname_0.xml");
871871
SCL scdVoltageLevelUnknown = SclTestMarshaller.getSCLFromFile("/scd-extref-flow-debind/scd_extref_flow_debind_volatagelevelname_unknown.xml");
@@ -901,7 +901,7 @@ private TInputs findInputs(SCL scd) {
901901
}
902902

903903
@Test
904-
void updateIedNameBasedOnLnode_should_update_CompasFlow_and_ExtRef_iedName(){
904+
void updateIedNameBasedOnLnode_should_update_CompasFlow_and_ExtRef_iedName() {
905905
// Given
906906
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_based_on_lnode_success.xml");
907907
// When
@@ -914,7 +914,7 @@ void updateIedNameBasedOnLnode_should_update_CompasFlow_and_ExtRef_iedName(){
914914
}
915915

916916
@Test
917-
void updateIedNameBasedOnLnode_when_no_matching_lnode_should_clear_binding(){
917+
void updateIedNameBasedOnLnode_when_no_matching_lnode_should_clear_binding() {
918918
// Given
919919
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_based_on_lnode_success.xml");
920920
PrivateUtils.extractCompasPrivate(scd.getSubstation().get(0).getVoltageLevel().get(0).getBay().get(0), TCompasTopo.class).orElseThrow().setNode("99");
@@ -928,4 +928,31 @@ void updateIedNameBasedOnLnode_when_no_matching_lnode_should_clear_binding(){
928928
assertExtRefIsNotBound(findExtRef(scd, "IED_NAME1", "LD_INST11", "STAT_LDSUIED_LPDO 1 Sortie_13_BOOLEAN_18_stVal_1"));
929929

930930
}
931+
932+
@Test
933+
void updateIedNameBasedOnLnode_when_several_ied_match_compasFlow_should_return_an_error() {
934+
// Given
935+
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_based_on_lnode_several_ied_matching_compasFlow.xml");
936+
// When
937+
List<SclReportItem> result = extRefEditorService.updateIedNameBasedOnLnode(scd);
938+
// Then
939+
assertThat(result)
940+
.extracting(SclReportItem::isError, SclReportItem::message)
941+
.containsExactly(Tuple.tuple(true,
942+
"Several LNode@IedName ('IED_NAME2', 'IED_NAME3') are found in the bay 'BAY_1' for the following compas-flow attributes " +
943+
": @FlowSourceIEDType 'SCU' @FlowSourceIEDredundancy 'A' @FlowIEDSystemVersioninstance '1'"));
944+
}
945+
946+
@Test
947+
void updateIedNameBasedOnLnode_when_no_Compas_ICD_Header_should_return_an_error() {
948+
// Given
949+
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_fails_no_Compas_ICDHeader.xml");
950+
// When
951+
List<SclReportItem> result = extRefEditorService.updateIedNameBasedOnLnode(scd);
952+
// Then
953+
assertThat(result)
954+
.extracting(SclReportItem::isError, SclReportItem::message)
955+
.containsExactly(Tuple.tuple(true,
956+
"The substation LNode with following attributes : IedName:IED_NAME2 / LdInst:LD_INST21 / LnClass:ANCR / LnInst:1 does not contain the needed (COMPAS - ICDHeader) private"));
957+
}
931958
}

0 commit comments

Comments
 (0)