Skip to content

Commit

Permalink
Merge pull request #411 from com-pas/develop
Browse files Browse the repository at this point in the history
Release 0.2.26
  • Loading branch information
GuillaumeJAFFRE authored Jul 11, 2024
2 parents 2d6132b + 837ff3f commit 662b3da
Show file tree
Hide file tree
Showing 10 changed files with 347 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package org.lfenergy.compas.sct.commons;

import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.lfenergy.compas.scl2007b4.model.*;
import org.lfenergy.compas.sct.commons.api.ExtRefEditor;
import org.lfenergy.compas.sct.commons.dto.*;
Expand All @@ -27,6 +26,7 @@

import java.math.BigInteger;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -90,7 +90,7 @@ private static List<TIED> getIedSources(SclRootAdapter sclRootAdapter, TCompasBa
*/
private List<ExtRefInfo.ExtRefWithBayReference> getExtRefWithBayReferenceInLDEPF(TDataTypeTemplates dataTypeTemplates, TIED tied, final TLDevice tlDevice, final List<SclReportItem> sclReportItems) {
List<ExtRefInfo.ExtRefWithBayReference> extRefBayReferenceList = new ArrayList<>();
String lDevicePath = "SCL/IED[@name=\""+ tied.getName() + "\"]/AccessPoint/Server/LDevice[@inst=\"" + tlDevice.getInst() + "\"]";
String lDevicePath = "SCL/IED[@name=\"" + tied.getName() + "\"]/AccessPoint/Server/LDevice[@inst=\"" + tlDevice.getInst() + "\"]";
Optional<TCompasBay> tCompasBay = PrivateUtils.extractCompasPrivate(tied, TCompasBay.class);
if (tCompasBay.isEmpty()) {
sclReportItems.add(SclReportItem.error(lDevicePath, "The IED has no Private Bay"));
Expand Down Expand Up @@ -405,8 +405,7 @@ private List<SclReportItem> updateLDEPFDos(LDeviceAdapter lDeviceAdapter, TExtRe
private Optional<SclReportItem> 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 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;
Expand Down Expand Up @@ -464,7 +463,7 @@ public void debindCompasFlowsAndExtRefsBasedOnVoltageLevel(SCL scd) {


@Override
public void updateIedNameBasedOnLnode(SCL scl) {
public List<SclReportItem> updateIedNameBasedOnLnode(SCL scl) {
Map<TopoKey, TBay> bayByTopoKey = scl.getSubstation().stream()
.flatMap(tSubstation -> tSubstation.getVoltageLevel().stream())
.flatMap(tVoltageLevel -> tVoltageLevel.getBay().stream())
Expand All @@ -475,6 +474,7 @@ public void updateIedNameBasedOnLnode(SCL scl) {
.flatMap(Optional::stream)
.collect(Collectors.toMap(BayTopoKey::topoKey, BayTopoKey::bay));

List<SclReportItem> sclReportItems = new ArrayList<>();
scl.getIED().stream()
.flatMap(ldeviceService::getLdevices)
.forEach(tlDevice ->
Expand All @@ -488,9 +488,21 @@ public void updateIedNameBasedOnLnode(SCL scl) {
&& Objects.equals(tlNode.getLnInst(), tCompasFlow.getExtReflnInst())
&& Utils.lnClassEquals(tlNode.getLnClass(), tCompasFlow.getExtReflnClass())
&& Objects.equals(tlNode.getPrefix(), tCompasFlow.getExtRefprefix()))
.filter(tlNode -> {
Optional<TCompasICDHeader> tCompasICDHeader = PrivateUtils.extractCompasPrivate(tlNode, TCompasICDHeader.class);
if (tCompasICDHeader.isPresent()) {
return Objects.equals(tCompasFlow.getFlowSourceIEDType(), tCompasICDHeader.get().getIEDType())
&& Objects.equals(tCompasFlow.getFlowIEDSystemVersioninstance(), tCompasICDHeader.get().getIEDSystemVersioninstance())
&& Objects.equals(tCompasFlow.getFlowSourceIEDredundancy(), tCompasICDHeader.get().getIEDredundancy());
} else {
sclReportItems.add(SclReportItem.error("", ("The substation LNode with following attributes : IedName:%s / LdInst:%s / LnClass:%s / LnInst:%s " +
"does not contain the needed (COMPAS - ICDHeader) private")
.formatted(tlNode.getIedName(), tlNode.getLdInst(), tlNode.getLnClass().getFirst(), tlNode.getLnInst())));
return false;
}
})
.map(TLNode::getIedName)
.filter(StringUtils::isNotBlank)
.findFirst()
.reduce(checkOnlyOneIed(tCompasFlow, tBay, sclReportItems))
)
.ifPresentOrElse(iedName -> {
extRefService.getMatchingExtRefs(tlDevice, tCompasFlow).forEach(tExtRef -> tExtRef.setIedName(iedName));
Expand All @@ -503,6 +515,17 @@ public void updateIedNameBasedOnLnode(SCL scl) {
)
)
);
return sclReportItems;
}

private static BinaryOperator<String> checkOnlyOneIed(TCompasFlow tCompasFlow, TBay tBay, List<SclReportItem> sclReportItems) {
return (iedName1, iedName2) -> {
sclReportItems.add(SclReportItem.error("",
("Several LNode@IedName ('%s', '%s') are found in the bay '%s' for the following compas-flow attributes :" +
" @FlowSourceIEDType '%s' @FlowSourceIEDredundancy '%s' @FlowIEDSystemVersioninstance '%s'").
formatted(iedName1, iedName2, tBay.getName(), tCompasFlow.getFlowSourceIEDType(), tCompasFlow.getFlowSourceIEDredundancy(), tCompasFlow.getFlowIEDSystemVersioninstance())));
return iedName1;
};
}

record TopoKey(String FlowNode, BigInteger FlowNodeOrder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ public interface ExtRefEditor {

/**
* Update compas:Flow.ExtRefiedName and ExtRef.iedName, based on Substation LNode iedName
* @param scd SCL
* @return list of encoutered errors
*/
void updateIedNameBasedOnLnode(SCL scd);
List<SclReportItem> updateIedNameBasedOnLnode(SCL scd);

}
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,10 @@ public String getXPath() {

/**
* Updates LDevice name by combining IED name and LDevice ldInst value
*
* @throws ScdException throws when renaming LDevice and new name has more than 33 caracteres
*/
public void updateLDName() throws ScdException {
public void updateLDName() {
String newLdName = parentAdapter.getCurrentElem().getName() + currentElem.getInst();
if (newLdName.length() > 33) {
throw new ScdException(newLdName + "(IED.name + LDevice.inst) has more than 33 characters");
}
// renaming ldName
// renaming ldName; Carefull because the maximum ldevice name length is 64 based on xsd
currentElem.setLdName(newLdName);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,19 @@ public static TPrivate createPrivate(List<TCompasTopo> compasTopos) {
return tPrivate;
}

/**
* Create private of a given type containing a simple string as value
* @param privateType type attribute of private element to create
* @param privateValue value of private to create
* @return the complete private
*/
public static TPrivate createStringPrivate(String privateType, String privateValue) {
TPrivate tPrivate = new TPrivate();
tPrivate.setType(privateType);
tPrivate.getContent().add(privateValue);
return tPrivate;
}

/**
* Create Private of given type as parameter
* @param jaxbElement content of Private to create
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ void manageBindingForLDEPF_when_DO_Mod_and_DA_stVal_NotFoundInDataTypeTemplate_s
.extracting(SclReportItem::message, SclReportItem::xpath)
.containsExactly(
Tuple.tuple("DO@name=Mod/DA@name=stVal not found in DataTypeTemplate",
"SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LDEPF\"]"),
"SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LDEPF\"]"),
Tuple.tuple("DO@name=Mod/DA@name=stVal not found in DataTypeTemplate",
"SCL/IED[@name=\"IED_NAME2\"]/AccessPoint/Server/LDevice[@inst=\"LDEPF\"]"),
Tuple.tuple("DO@name=Mod/DA@name=stVal not found in DataTypeTemplate",
Expand Down Expand Up @@ -865,7 +865,7 @@ void debindCompasFlowsAndExtRefsBasedOnVoltageLevel(String testCase, SCL scd, Tu
.containsExactly(flow2);
}

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

@Test
void updateIedNameBasedOnLnode_should_update_CompasFlow_and_ExtRef_iedName(){
void updateIedNameBasedOnLnode_should_update_CompasFlow_and_ExtRef_iedName() {
// Given
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_based_on_lnode_success.xml");
// When
Expand All @@ -914,7 +914,7 @@ void updateIedNameBasedOnLnode_should_update_CompasFlow_and_ExtRef_iedName(){
}

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

}

@Test
void updateIedNameBasedOnLnode_when_several_ied_match_compasFlow_should_return_an_error() {
// Given
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_based_on_lnode_several_ied_matching_compasFlow.xml");
// When
List<SclReportItem> result = extRefEditorService.updateIedNameBasedOnLnode(scd);
// Then
assertThat(result)
.extracting(SclReportItem::isError, SclReportItem::message)
.containsExactly(Tuple.tuple(true,
"Several LNode@IedName ('IED_NAME2', 'IED_NAME3') are found in the bay 'BAY_1' for the following compas-flow attributes " +
": @FlowSourceIEDType 'SCU' @FlowSourceIEDredundancy 'A' @FlowIEDSystemVersioninstance '1'"));
}

@Test
void updateIedNameBasedOnLnode_when_no_Compas_ICD_Header_should_return_an_error() {
// Given
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_fails_no_Compas_ICDHeader.xml");
// When
List<SclReportItem> result = extRefEditorService.updateIedNameBasedOnLnode(scd);
// Then
assertThat(result)
.extracting(SclReportItem::isError, SclReportItem::message)
.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"));
}
}
Loading

0 comments on commit 662b3da

Please sign in to comment.