Skip to content

Commit

Permalink
feat(#351): RSR-894 Update Compasflow and extref prebindings
Browse files Browse the repository at this point in the history
Signed-off-by: massifben <105049157+massifben@users.noreply.github.com>
  • Loading branch information
massifben committed Dec 15, 2023
1 parent e1373c0 commit 007e055
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
// SPDX-FileCopyrightText: 2023 RTE FRANCE
// SPDX-FileCopyrightText: 2022 RTE FRANCE
//
// SPDX-License-Identifier: Apache-2.0

package org.lfenergy.compas.sct.commons;

<<<<<<<< HEAD:sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefEditorService.java
import lombok.RequiredArgsConstructor;
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 @@ -21,17 +25,19 @@
import org.lfenergy.compas.sct.commons.scl.ln.LN0Adapter;
import org.lfenergy.compas.sct.commons.util.ActiveStatus;
import org.lfenergy.compas.sct.commons.util.PrivateEnum;
========
import org.lfenergy.compas.scl2007b4.model.TCompasFlow;
import org.lfenergy.compas.scl2007b4.model.TExtRef;
import org.lfenergy.compas.scl2007b4.model.TLDevice;
>>>>>>>> feat(#351): RSR-894 Update Compasflow and extref prebindings:sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefService.java
import org.lfenergy.compas.sct.commons.util.PrivateUtils;
import org.lfenergy.compas.sct.commons.util.Utils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.apache.commons.lang3.StringUtils.*;
import static org.lfenergy.compas.sct.commons.util.CommonConstants.*;
import static org.lfenergy.compas.sct.commons.util.Utils.isExtRefFeedBySameControlBlock;
public class ExtRefService {

<<<<<<<< HEAD:sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefEditorService.java
@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";
Expand Down Expand Up @@ -228,34 +234,20 @@ public TExtRef updateExtRefSource(SCL scd, ExtRefInfo extRefInfo) throws ScdExce
ExtRefBindingInfo bindingInfo = extRefInfo.getBindingInfo();
if (bindingInfo == null || !bindingInfo.isValid()) {
throw new ScdException(INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO);
========
public Stream<TExtRef> getExtRefs(TLDevice tlDevice) {
if (tlDevice.isSetLN0() && tlDevice.getLN0().isSetInputs() && tlDevice.getLN0().getInputs().isSetExtRef()) {
return tlDevice.getLN0().getInputs().getExtRef().stream();
>>>>>>>> feat(#351): RSR-894 Update Compasflow and extref prebindings:sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefService.java
}
if (bindingInfo.getIedName().equals(iedName) || TServiceType.POLL.equals(bindingInfo.getServiceType())) {
throw new ScdException("Internal binding can't have control block");
}
ExtRefSourceInfo sourceInfo = extRefInfo.getSourceInfo();
if (sourceInfo == null || !sourceInfo.isValid()) {
throw new ScdException(INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO);
}

SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName);
LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst);
AbstractLNAdapter<?> anLNAdapter = AbstractLNAdapter.builder()
.withLDeviceAdapter(lDeviceAdapter)
.withLnClass(lnClass)
.withLnInst(lnInst)
.withLnPrefix(prefix)
.build();
return anLNAdapter.updateExtRefSource(extRefInfo);
return Stream.empty();
}

@Override
public List<SclReportItem> updateAllExtRefIedNames(SCL scd) {
SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
List<SclReportItem> iedErrors = validateIed(sclRootAdapter);
if (!iedErrors.isEmpty()) {
return iedErrors;
public Stream<TCompasFlow> getCompasFlows(TLDevice tlDevice) {
if (tlDevice.isSetLN0() && tlDevice.getLN0().isSetInputs() && tlDevice.getLN0().getInputs().isSetExtRef()) {
return PrivateUtils.extractCompasPrivates(tlDevice.getLN0().getInputs(), TCompasFlow.class);
}
<<<<<<<< HEAD:sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefEditorService.java
Map<String, IEDAdapter> icdSystemVersionToIed = sclRootAdapter.streamIEDAdapters()
.collect(Collectors.toMap(
iedAdapter -> iedAdapter.getCompasICDHeader()
Expand Down Expand Up @@ -411,6 +403,51 @@ private String computeDaiValue(AbstractLNAdapter<?> lnAdapter, TExtRef extRef, S
extRef.getDoName() + "." +
daName;
}
========
return Stream.empty();
}

/**
* Check if extRef matches CompasFlow
*
* @param extRef extRef
* @param compasFlow compasFlow
* @return true if all required attributes matches. Note that empty string, whitespaces only string and null values are considered as matching
* (missing attributes matches attribute with empty string value or whitespaces only). Return false otherwise.
*/
public boolean matchesCompasFlow(TExtRef extRef, TCompasFlow compasFlow) {
String extRefLnClass = extRef.isSetLnClass() ? extRef.getLnClass().get(0) : null;
return Utils.equalsOrBothBlank(compasFlow.getDataStreamKey(), extRef.getDesc())
&& Utils.equalsOrBothBlank(compasFlow.getExtRefiedName(), extRef.getIedName())
&& Utils.equalsOrBothBlank(compasFlow.getExtRefldinst(), extRef.getLdInst())
&& Utils.equalsOrBothBlank(compasFlow.getExtRefprefix(), extRef.getPrefix())
&& Utils.equalsOrBothBlank(compasFlow.getExtReflnClass(), extRefLnClass)
&& Utils.equalsOrBothBlank(compasFlow.getExtReflnInst(), extRef.getLnInst());
}

public void clearBinding(TExtRef extRef) {
extRef.setIedName(null);
extRef.setLdInst(null);
extRef.setPrefix(null);
extRef.setLnInst(null);
extRef.setDoName(null);
extRef.setDaName(null);
extRef.setServiceType(null);
extRef.setSrcLDInst(null);
extRef.setSrcPrefix(null);
extRef.setSrcLNInst(null);
extRef.setSrcCBName(null);
extRef.unsetLnClass();
extRef.unsetSrcLNClass();
}

public void clearBinding(TCompasFlow compasFlow) {
compasFlow.setExtRefiedName(null);
compasFlow.setExtRefldinst(null);
compasFlow.setExtRefprefix(null);
compasFlow.setExtReflnInst(null);
compasFlow.setExtReflnClass(null);
>>>>>>>> feat(#351): RSR-894 Update Compasflow and extref prebindings:sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefService.java
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,9 @@ public interface ExtRefEditor {
*/
void debindCompasFlowsAndExtRefsBasedOnVoltageLevel(SCL scd);

/**
* Update compas:Flow.ExtRefiedName and ExtRef.iedName, based on Substation LNode iedName
*/
void updateIedNameBasedOnLnode(SCL scd);

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import org.apache.commons.lang3.StringUtils;
import org.lfenergy.compas.scl2007b4.model.*;
import org.lfenergy.compas.sct.commons.ExtRefEditorService;
import org.lfenergy.compas.sct.commons.ExtRefService;
import org.lfenergy.compas.sct.commons.ExtRefEditorService;
import org.lfenergy.compas.sct.commons.dto.DataAttributeRef;
import org.lfenergy.compas.sct.commons.dto.FcdaForDataSetsCreation;
import org.lfenergy.compas.sct.commons.dto.SclReportItem;
Expand Down Expand Up @@ -374,7 +376,7 @@ private SclRootAdapter getSclRootAdapter() {
* @return list ExtRefs without duplication
*/
public List<TExtRef> filterDuplicatedExtRefs() {
return ExtRefEditorService.filterDuplicatedExtRefs(extRefService.getExtRefs(currentElem).toList());
zzz return ExtRefEditorService.filterDuplicatedExtRefs(extRefService.getExtRefs(currentElem).toList());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package org.lfenergy.compas.sct.commons;

import org.junit.jupiter.api.BeforeEach;
import org.assertj.core.api.Assertions;
import org.assertj.core.groups.Tuple;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -20,9 +21,13 @@
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
import org.lfenergy.compas.sct.commons.scl.ldevice.LDeviceAdapter;
import org.lfenergy.compas.sct.commons.scl.ln.AbstractLNAdapter;
import org.lfenergy.compas.sct.commons.testhelpers.MarshallerWrapper;
import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller;
import org.lfenergy.compas.sct.commons.util.PrivateUtils;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
Expand Down Expand Up @@ -828,5 +833,32 @@ private TInputs findInputs(SCL scd) {
.orElseThrow();

}
@Test
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
extRefEditorService.updateIedNameBasedOnLnode(scd);
// Then
assertThat(findCompasFlow(scd, "IED_NAME1", "LD_INST11", "STAT_LDSUIED_LPDO 1 Sortie_13_BOOLEAN_18_stVal_1").getExtRefiedName())
.isEqualTo("IED_NAME2");
assertThat(findExtRef(scd, "IED_NAME1", "LD_INST11", "STAT_LDSUIED_LPDO 1 Sortie_13_BOOLEAN_18_stVal_1").getIedName())
.isEqualTo("IED_NAME2");
}

@Test
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");
// When
extRefEditorService.updateIedNameBasedOnLnode(scd);
// Then
TCompasFlow compasFlow = findCompasFlow(scd, "IED_NAME1", "LD_INST11", "STAT_LDSUIED_LPDO 1 Sortie_13_BOOLEAN_18_stVal_1");
assertThat(compasFlow)
.extracting(TCompasFlow::getExtRefiedName, TCompasFlow::getExtRefldinst, TCompasFlow::getExtRefprefix, TCompasFlow::getExtReflnClass, TCompasFlow::getExtReflnInst)
.containsOnlyNulls();
assertExtRefIsNotBound(findExtRef(scd, "IED_NAME1", "LD_INST11", "STAT_LDSUIED_LPDO 1 Sortie_13_BOOLEAN_18_stVal_1"));

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.lfenergy.compas.sct.commons.scl.ln.LN0Adapter;
import org.lfenergy.compas.sct.commons.scl.ln.LNAdapter;
import org.lfenergy.compas.sct.commons.util.ControlBlockEnum;
import org.lfenergy.compas.sct.commons.util.PrivateUtils;
import org.lfenergy.compas.sct.commons.util.Utils;
import org.opentest4j.AssertionFailedError;

Expand Down Expand Up @@ -69,7 +70,14 @@ public static TExtRef findExtRef(SCL scl, String iedName, String ldInst, String
.stream()
.filter(extRef -> extRefDesc.equals(extRef.getDesc()))
.findFirst()
.orElseThrow(() -> new AssertionFailedError(String.format("ExtRef.des=%s not found in IED.name=%s,LDevice.inst=%s", extRefDesc, iedName, ldInst)));
.orElseThrow(() -> new AssertionFailedError(String.format("ExtRef.desc=%s not found in IED.name=%s,LDevice.inst=%s", extRefDesc, iedName, ldInst)));
}

public static TCompasFlow findCompasFlow(SCL scl, String iedName, String ldInst, String compasFlowDataStreamKey) {
return PrivateUtils.extractCompasPrivates(findInputs(scl, iedName, ldInst).getCurrentElem(), TCompasFlow.class)
.filter(compasFlow -> compasFlowDataStreamKey.equals(compasFlow.getDataStreamKey()))
.findFirst()
.orElseThrow(() -> new AssertionFailedError(String.format("CompasFlow.dataStreamKey=%s not found in IED.name=%s,LDevice.inst=%s", compasFlowDataStreamKey, iedName, ldInst)));
}

public static LN0Adapter findLn0(SCL scl, String iedName, String ldInst) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- SPDX-FileCopyrightText: 2023 RTE FRANCE -->
<!-- -->
<!-- SPDX-License-Identifier: Apache-2.0 -->
<SCL version="2007" revision="B" release="4" xmlns="http://www.iec.ch/61850/2003/SCL" xmlns:compas="https://www.lfenergy.org/compas/extension/v1">
<Header id="hId" version="2007" revision="B" toolID="COMPAS"/>
<Substation name="SITE">
<VoltageLevel nomFreq="50" numPhases="3" name="0">
<Voltage unit="V" multiplier="k">0</Voltage>
<Bay name="BAY_1">
<Private type="COMPAS-Topo">
<compas:Topo Node="101" NodeOrder="2" Direction="Down"/>
</Private>
<Private type="COMPAS-Bay">
<compas:Bay BayCodif="TG00000001" UUID="9cd6f05b-1bbd-4ba3-86c5-41c99103e06d" Version="1"
MainShortLabel="SITE1" SecondLabel="SITE-TGENE" NumBay="7" BayCount="1"/>
</Private>
<Function name="FUNCTION_1">
<Private type="COMPAS-Function">
<compas:Function UUID="8f4cda3f-828c-4006-9b87-2af96b19304b" Label="FUNCTION_1"/>
</Private>
<LNode iedName="IED_NAME2" ldInst="LD_INST21" lnClass="ANCR" lnInst="1"/>
</Function>
</Bay>
</VoltageLevel>
</Substation>
<IED name="IED_NAME1">
<Private type="COMPAS-ICDHeader">
<compas:ICDHeader ICDSystemVersionUUID="System_Version_IED_NAME1" IEDType="BCU" IEDSubstationinstance="11" IEDSystemVersioninstance="1" IEDName="IED_NAME1" VendorName="SCLE SFE" IEDmodel="ARKENS-SV1120-HGAAA-EB5" IEDredundancy="A" BayLabel="3THEIX2" hwRev="0.0.2." swRev="1.0a"
headerId="ARKENS-SV1120-HGAAA-EB5_SCU" headerVersion="1.2a" headerRevision="412995"/>
</Private>
<AccessPoint name="AP_NAME">
<Server>
<Authentication/>
<LDevice inst="LD_INST11" ldName="IED_NAME1LD_INST11">
<LN0 lnClass="LLN0" inst="" lnType="LNEX1">
<DOI name="Mod">
<DAI name="stVal">
<Val>on</Val>
</DAI>
</DOI>
<Inputs>
<Private type="COMPAS-Flow">
<compas:Flow FlowSourceBayNode="101" FlowSourceBayNodeOrder="2" dataStreamKey="STAT_LDSUIED_LPDO 1 Sortie_13_BOOLEAN_18_stVal_1" ExtRefiedName="IED_NAME_A_CHANGER" ExtRefldinst="LD_INST21" ExtRefprefix="" ExtReflnClass="ANCR" ExtReflnInst="1" FlowID="1" FlowStatus="ACTIVE" FlowKind="BAY_INTERNAL"/>
</Private>
<ExtRef iedName="IED_NAME_A_CHANGER" ldInst="LD_INST21" lnClass="ANCR" lnInst="1" doName="DoName1" daName="daName1" intAddr="INT_ADDR11" pDO="Do11.sdo11" pDA="da11.bda111.bda112.bda113" desc="STAT_LDSUIED_LPDO 1 Sortie_13_BOOLEAN_18_stVal_1"/>
</Inputs>
</LN0>
</LDevice>
</Server>
</AccessPoint>
</IED>
<IED name="IED_NAME2">
<Private type="COMPAS-ICDHeader">
<compas:ICDHeader ICDSystemVersionUUID="System_Version_IED_NAME2" IEDType="BCU" IEDSubstationinstance="22" IEDSystemVersioninstance="1" IEDName="IED_NAME2" VendorName="SCLE SFE" IEDmodel="ARKENS-SV1120-HGAAA-EB5" IEDredundancy="A" BayLabel="3THEIX2" hwRev="0.0.2." swRev="1.0a"
headerId="ARKENS-SV1120-HGAAA-EB5_SCU" headerVersion="1.2a" headerRevision="412995"/>
</Private>
<AccessPoint name="AP_NAME">
<Server>
<Authentication/>
<LDevice inst="LD_INST21">
<LN0 lnClass="LLN0" inst="" lnType="LNEX1">
<DOI name="Mod">
<DAI name="stVal">
<Val>on</Val>
</DAI>
</DOI>
</LN0>
<LN lnClass="ANCR" inst="1" lnType="lnType"/>
</LDevice>
</Server>
</AccessPoint>
</IED>
<DataTypeTemplates>
<LNodeType lnClass="LLN0" id="LNEX1">
<DO name="Mod" type="DO1"/>
</LNodeType>
<LNodeType lnClass="ANCR" id="lnType">
<DO name="DoName1" type="DO2"/>
</LNodeType>
<DOType cdc="ENC" id="DO1">
<DA fc="ST" name="stVal" bType="Enum" type="BehaviourModeKind"/>
</DOType>
<DOType cdc="ENC" id="DO2">
<DA fc="BL" name="daName1" bType="BOOLEAN"/>
</DOType>
<EnumType id="BehaviourModeKind">
<EnumVal ord="1">on</EnumVal>
<EnumVal ord="2">off</EnumVal>
<EnumVal ord="3">test</EnumVal>
</EnumType>
</DataTypeTemplates>
</SCL>

0 comments on commit 007e055

Please sign in to comment.