Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(#412): RSR-1048 add special case for InRef binding for LDEPF DIGITAL BOOLEAN channels #416

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@
import org.apache.commons.lang3.tuple.Pair;
import org.lfenergy.compas.scl2007b4.model.*;
import org.lfenergy.compas.sct.commons.dto.*;
import org.lfenergy.compas.sct.commons.scl.ldevice.LDeviceActivation;
import org.lfenergy.compas.sct.commons.scl.ObjectReference;
import org.lfenergy.compas.sct.commons.scl.ied.InputsAdapter;
import org.lfenergy.compas.sct.commons.scl.ldevice.LDeviceActivation;
import org.lfenergy.compas.sct.commons.scl.ldevice.LDeviceAdapter;
import org.lfenergy.compas.sct.commons.util.PrivateUtils;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static org.lfenergy.compas.sct.commons.util.CommonConstants.BEHAVIOUR_DO_NAME;
Expand Down Expand Up @@ -47,9 +48,6 @@
* <li>{@link LN0Adapter#getDAI <em>Returns the value of the <b>DataAttributeRef </b> containment reference By filter</em>}</li>
* <li>{@link LN0Adapter#getDAIValues(DataAttributeRef) <em>Returns <b>DAI (sGroup, value) </b> containment reference list By <b>DataAttributeRef </b> filter</em>}</li>
*
* <li>{@link LN0Adapter#getDataSetByName(String) <em>Returns the value of the <b>TDataSet </b>object reference By the value of the <b>name </b>attribute </em>}</li>
*
* <li>{@link LN0Adapter#getControlBlocks(List, TServiceType) <em>Returns the value of the <b>ControlBlock </b>containment reference list that match <b>datSet </b> value of given <b>TDataSet</b> </em>}</li>
* <li>{@link LN0Adapter#addPrivate <em>Add <b>TPrivate </b>under this object</em>}</li>
* <li>{@link LN0Adapter#removeAllControlBlocksAndDatasets() <em>Remove all <b>ControlBlock</b></em>}</li>
* </ul>
Expand All @@ -75,6 +73,7 @@ public class LN0Adapter extends AbstractLNAdapter<LN0> {
public static final DaTypeName BEHAVIOUR_DA_TYPE_NAME = getDaTypeNameForBeh();
private static final String DAI_NAME_PURPOSE = "purpose";
private static final String INREF_PREFIX = "InRef";
private static final Pattern LDEFP_DIGITAL_CHANNEL_PATTERN = Pattern.compile("DYN_LDEPF_DIGITAL CHANNEL \\d+_\\d+_BOOLEAN");

/**
* Constructor
Expand Down Expand Up @@ -188,7 +187,7 @@ public Optional<SclReportItem> updateLDeviceStatus(List<Pair<String, String>> ie
if (daiBehList.isEmpty()) {
return Optional.of(buildFatalReportItem("The LDevice doesn't have a DO @name='Beh' OR its associated DA@fc='ST' AND DA@name='stVal'"));
}
Set<String> enumValues = getEnumValues(daiBehList.get(0).getDaName().getType());
Set<String> enumValues = getEnumValues(daiBehList.getFirst().getDaName().getType());
Optional<TCompasLDevice> optionalTCompasLDevice = PrivateUtils.extractCompasPrivate(getParentAdapter().getCurrentElem(), TCompasLDevice.class);
if (optionalTCompasLDevice.isEmpty()) {
return Optional.of(buildFatalReportItem("The LDevice doesn't have a Private compas:LDevice."));
Expand Down Expand Up @@ -237,13 +236,23 @@ public List<SclReportItem> updateDoInRef() {
&& doiAdapter.findDataAdapterByName(DAI_NAME_PURPOSE).isPresent())
.map(doiAdapter -> doiAdapter.getDataAdapterByName(DAI_NAME_PURPOSE).getCurrentElem().getVal().stream()
.findFirst()
.map(tVal -> doiAdapter.updateDaiFromExtRef(getBoundExtRefsByDesc(tVal.getValue())))
.map(tVal -> doiAdapter.updateDaiFromExtRef(getExtRefsBoundToInRef(tVal.getValue())))
.orElse(List.of(SclReportItem.warning(getXPath(), "The DOI %s can't be bound with an ExtRef".formatted(getXPath()))))
)
.flatMap(List::stream)
.collect(Collectors.toList());
}

private List<TExtRef> getExtRefsBoundToInRef(String desc) {
List<TExtRef> boundExtRefs = getBoundExtRefsByDesc(desc);
// Special case for LDEPF DIGITAL CHANNEL of type BOOLEAN RSR-1048
if (boundExtRefs.isEmpty() && LDEFP_DIGITAL_CHANNEL_PATTERN.matcher(desc).matches()) {
String descWithoutType = desc.substring(0, desc.lastIndexOf("_"));
return getBoundExtRefsByDesc(descWithoutType);
}
return boundExtRefs;
}

private List<TExtRef> getBoundExtRefsByDesc(String desc) {
return getExtRefs().stream()
.filter(tExtRef -> tExtRef.isSetIedName() && tExtRef.isSetLdInst() && tExtRef.isSetLnClass() && tExtRef.isSetDoName() &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ void getControlBlocksForMatchingFCDA_should_return_expected_Items(LN0 ln0, TServ
List<ControlBlock> controlBlocks = ln0Adapter.getControlBlocksForMatchingFCDA(extRefInfo).toList();
// Then
assertThat(controlBlocks).hasSize(1);
assertThat(controlBlocks.get(0).getServiceType()).isEqualTo(serviceType);
assertThat(controlBlocks.getFirst().getServiceType()).isEqualTo(serviceType);
}

private static Stream<Arguments> provideServiceType() {
Expand Down Expand Up @@ -335,7 +335,7 @@ void getDOIAdapters_should_return_expected_list_of_DOIAdapter() {
LN0Adapter ln0Adapter = new LN0Adapter(null, ln0);
// When Then
assertThat(ln0Adapter.getDOIAdapters()).isNotEmpty();
assertThat(ln0Adapter.getDOIAdapters().get(0).getCurrentElem().getName()).isEqualTo("Do");
assertThat(ln0Adapter.getDOIAdapters().getFirst().getCurrentElem().getName()).isEqualTo("Do");
}

@Test
Expand Down Expand Up @@ -434,7 +434,7 @@ void testFindMatch() {
// When Then
AbstractDAIAdapter<?> daiAdapter = (AbstractDAIAdapter<?>) assertDoesNotThrow(() -> ln0Adapter.findMatch(doTypeName, daTypeName).get());
assertThat(daiAdapter.getCurrentElem().getName()).isEqualTo("bda3");
assertThat(daiAdapter.getCurrentElem().getVal().get(0).getValue()).isEqualTo("Completed-diff");
assertThat(daiAdapter.getCurrentElem().getVal().getFirst().getValue()).isEqualTo("Completed-diff");
DoTypeName doTypeName2 = new DoTypeName("Do.sdo1");
// When Then
assertThat(ln0Adapter.findMatch(doTypeName2, daTypeName)).isEmpty();
Expand Down Expand Up @@ -540,7 +540,7 @@ void testGetDAI() {
var dataAttributeRefs = ln0Adapter.getDAI(filter, false);
// Then
assertThat(dataAttributeRefs).hasSize(1);
assertThat(dataAttributeRefs.get(0).getDaName().getType()).isEqualTo("BehaviourModeKind");
assertThat(dataAttributeRefs.getFirst().getDaName().getType()).isEqualTo("BehaviourModeKind");
}

@Test
Expand Down Expand Up @@ -864,7 +864,7 @@ void createControlBlockIfNotExists_should_create_SampledValueControl() {
// Then
assertThat(sourceLn0.getCurrentElem().getSampledValueControl())
.hasSize(1);
TSampledValueControl tSampledValueControl = sourceLn0.getCurrentElem().getSampledValueControl().get(0);
TSampledValueControl tSampledValueControl = sourceLn0.getCurrentElem().getSampledValueControl().getFirst();
assertThat(tSampledValueControl)
.extracting(TControl::getName, TSampledValueControl::getSmvID, TControl::getDatSet,
TSampledValueControl::isMulticast, TSampledValueControl::getSmpRate, TSampledValueControl::getNofASDU, TSampledValueControl::getSmpMod, TSampledValueControl::getSecurityEnable,
Expand Down Expand Up @@ -895,7 +895,7 @@ void createControlBlockIfNotExists_should_create_ReportControl() {
// Then
assertThat(sourceLn0.getCurrentElem().getReportControl())
.hasSize(1);
TReportControl tReportControl = sourceLn0.getCurrentElem().getReportControl().get(0);
TReportControl tReportControl = sourceLn0.getCurrentElem().getReportControl().getFirst();
assertThat(tReportControl)
.extracting(TControl::getName, TReportControl::getRptID, TControl::getDatSet,
TReportControl::isBuffered, TReportControl::getBufTime, TReportControl::isIndexed, TControlWithTriggerOpt::getIntgPd, TReportControl::getConfRev)
Expand Down Expand Up @@ -1140,6 +1140,42 @@ void updateDoInRef_when_ExtRef_desc_matches_should_update_setSrcRef_and_setSrcCB
assertThat(sclReportItems).isEmpty();
}

@Test
void updateDoInRef_when_DAI_purpose_of_Ldevice_LDEPF_ends_with_BOOLEAN_should_match_desc_that_ends_with_enum_and_update_setSrcRef_and_setSrcCB_and_setTstRef_and_setTstCB() {
// Given
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-test-update-inref/scd_update_inref_test.xml");
LN0Adapter sourceLn0 = findLn0(scd, "IED_NAME1", "LDEPF");
String doiNameInRef = "InRef3";
String originalSetSrcCB = getDaiValue(sourceLn0, doiNameInRef, SETSRCCB_DA_NAME);
String expectedSrcRef = "IED_NAME1LDEPF/PRANCR1.Do11.sdo11";
String expectedSrcCb = "IED_NAME1LDEPF/prefixANCR1.GSE1";
String originalSetTstCB = getDaiValue(sourceLn0, doiNameInRef, SETTSTCB_DA_NAME);
String expectedTstRef = "IED_NAME1LDEPF/PRANCR1.Do11.sdo11";
String expectedTstCB = "IED_NAME1LDEPF/prefixANCR3.GSE3";

// When
List<SclReportItem> sclReportItems = sourceLn0.updateDoInRef();
// Then

String finalSetSrcRef = getDaiValue(sourceLn0, doiNameInRef, SETSRCREF_DA_NAME);
String finalSetSrcCB = getDaiValue(sourceLn0, doiNameInRef, SETSRCCB_DA_NAME);
String finalSetTstRef = getDaiValue(sourceLn0, doiNameInRef, SETTSTREF_DA_NAME);
String finalSetTstCB = getDaiValue(sourceLn0, doiNameInRef, SETTSTCB_DA_NAME);
assertThat(finalSetSrcRef)
.isNotBlank()
.isEqualTo(expectedSrcRef);
assertThat(finalSetSrcCB)
.isNotEqualTo(originalSetSrcCB)
.isEqualTo(expectedSrcCb);
assertThat(finalSetTstRef)
.isNotBlank()
.isEqualTo(expectedTstRef);
assertThat(finalSetTstCB)
.isNotEqualTo(originalSetTstCB)
.isEqualTo(expectedTstCB);
assertThat(sclReportItems).isEmpty();
}

@Test
void updateDoInRef_when_ExtRef_desc_matches_and_dais_not_updatable_should_not_update_setSrcRef_and_setSrcCB_and_setTstRef_and_setTstCB() {
// Given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,30 @@
</LN0>
</LDevice>

<!-- Case with LDEPF and DAI purpose ends with BOOLEAN matching the InRef with Enum -->
<LDevice inst="LDEPF" ldName="IED_NAME1LDEPF">
<LN0 lnClass="LLN0" inst="" lnType="LN11">
<DOI name="InRef3">
<DAI name="purpose">
<Val>DYN_LDEPF_DIGITAL CHANNEL 36_1_BOOLEAN</Val>
</DAI>
<DAI name="setSrcRef" valKind="RO" valImport="true"/>
<DAI name="setSrcCB" valKind="RO" valImport="true">
<Val>OLD_VAL</Val>
</DAI>
<DAI name="setTstRef" valKind="RO" valImport="true"/>
<DAI name="setTstCB" valKind="RO" valImport="true">
<Val>OLD_VAL</Val>
</DAI>
</DOI>
<Inputs>
<ExtRef iedName="IED_NAME1" desc="DYN_LDEPF_DIGITAL CHANNEL 36_1_FaultDirectionKind_13_dirGeneral_1" ldInst="LDEPF" lnClass="ANCR" lnInst="1" prefix="PR" intAddr="INT_ADDR11" pDO="Do11.sdo11" doName="Do11.sdo11" srcLDInst="LD22" srcCBName="GSE1" srcPrefix="prefix" srcLNClass="ANCR" srcLNInst="1"/>
<ExtRef iedName="IED_NAME1" desc="DYN_LDEPF_DIGITAL CHANNEL 36_1_FaultDirectionKind_13_dirGeneral_2" ldInst="LDEPF" lnClass="ANCR" lnInst="1" prefix="PR" intAddr="INT_ADDR11" pDO="Do11.sdo11" doName="Do11.sdo11" srcLDInst="LD22" srcCBName="GSE2" srcPrefix="prefix" srcLNClass="ANCR" srcLNInst="2"/>
<ExtRef iedName="IED_NAME1" desc="DYN_LDEPF_DIGITAL CHANNEL 36_1_FaultDirectionKind_13_dirGeneral_3" ldInst="LDEPF" lnClass="ANCR" lnInst="1" prefix="PR" intAddr="INT_ADDR11" pDO="Do11.sdo11" doName="Do11.sdo11" srcLDInst="LD22" srcCBName="GSE3" srcPrefix="prefix" srcLNClass="ANCR" srcLNInst="3"/>
</Inputs>
</LN0>
</LDevice>

<!-- Case with ExtRef.desc suffix not ending with "_1" -->
<LDevice inst="LD_WITH_1_Bad_InRef" ldName="IED_NAME1LD_INST12">
<LN0 lnClass="LLN0" inst="" lnType="LN11">
Expand Down Expand Up @@ -179,4 +203,4 @@
<DA name="purpose" bType="VisString255" fc="DC"/>
</DOType>
</DataTypeTemplates>
</SCL>
</SCL>
Loading