Skip to content

Commit

Permalink
Merge pull request #377 from com-pas/feat/RSR-924_remove_validation_w…
Browse files Browse the repository at this point in the history
…hen_specific_DOI_and_DAI_does_not_exists

feat(#378): remove validation when DOI(Mod) and DAI(stVal) does not exists
  • Loading branch information
samirromdhani authored Feb 28, 2024
2 parents 3d59366 + 7529951 commit 702a8d8
Show file tree
Hide file tree
Showing 13 changed files with 1,042 additions and 131 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-FileCopyrightText: 2024 RTE FRANCE
//
// SPDX-License-Identifier: Apache-2.0

package org.lfenergy.compas.sct.commons;

import org.lfenergy.compas.scl2007b4.model.*;

import static org.lfenergy.compas.sct.commons.util.CommonConstants.MOD_DO_NAME;
import static org.lfenergy.compas.sct.commons.util.CommonConstants.STVAL_DA_NAME;

public class DataTypeTemplatesService {

final LnodeTypeService lnodeTypeService = new LnodeTypeService();
final DoTypeService doTypeService = new DoTypeService();
final DoService doService = new DoService();

/**
* verify if DO(name=Mod)/DA(name=stVal) exists in DataTypeTemplate
* @param dtt TDataTypeTemplates where Data object and Data attribute exists
* @param lNodeTypeId LNode Type ID where Data object exists
* DataTypeTemplates model :
* <DataTypeTemplates>
* <LNodeType lnClass="LNodeTypeClass" id="LNodeTypeID">
* <DO name="Mod" type="DOModTypeID" ../>
* </LNodeType>
* ...
* <DOType cdc="DOTypeCDC" id="DOModTypeID">
* <DA name="stVal" ../>
* </DOType>
* </DataTypeTemplates>
* @return true if the Data Object (Mod) and Data attribute (stVal) present, false otherwise
*/
public boolean isDoModAndDaStValExist(TDataTypeTemplates dtt, String lNodeTypeId) {
return lnodeTypeService.findLnodeType(dtt, lNodeType -> lNodeTypeId.equals(lNodeType.getId()))
.map(lNodeType -> doService.findDo(lNodeType, tdo -> MOD_DO_NAME.equals(tdo.getName()))
.map(tdo -> doTypeService.findDoType(dtt, doType -> tdo.getType().equals(doType.getId()))
.map(doType -> doType.getSDOOrDA().stream()
.filter(sdoOrDa -> sdoOrDa.getClass().equals(TDA.class))
.map(TDA.class::cast)
.anyMatch(tda -> STVAL_DA_NAME.equals(tda.getName())))
.orElse(false))
.orElse(false))
.orElse(false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ public class ExtRefEditorService implements ExtRefEditor {
"7", "THT"
);

private final IedService iedService;
private final LdeviceService ldeviceService;
private final ExtRefService extRefService;
private final DataTypeTemplatesService dataTypeTemplatesService;

/**
* Provides valid IED sources according to EPF configuration.<br/>
Expand Down Expand Up @@ -78,6 +80,37 @@ private static List<TIED> getIedSources(SclRootAdapter sclRootAdapter, TCompasBa
.toList();
}

/**
* Provides a list of ExtRef and associated Bay <br/>
* - The location of ExtRef should be in LDevice (inst=LDEPF) <br/>
* - ExtRef that lacks Bay or ICDHeader Private is not returned <br/>
*
* @param sclReportItems List of SclReportItem
* @return list of ExtRef and associated Bay
*/
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() + "\"]";
Optional<TCompasBay> tCompasBay = PrivateUtils.extractCompasPrivate(tied, TCompasBay.class);
if (tCompasBay.isEmpty()) {
sclReportItems.add(SclReportItem.error(lDevicePath, "The IED has no Private Bay"));
if (PrivateUtils.extractCompasPrivate(tied, TCompasICDHeader.class).isEmpty()) {
sclReportItems.add(SclReportItem.error(lDevicePath, "The IED has no Private compas:ICDHeader"));
}
return Collections.emptyList();
}

if (dataTypeTemplatesService.isDoModAndDaStValExist(dataTypeTemplates, tlDevice.getLN0().getLnType())) {
extRefBayReferenceList.addAll(tlDevice.getLN0()
.getInputs()
.getExtRef().stream()
.map(extRef -> new ExtRefInfo.ExtRefWithBayReference(tied.getName(), tCompasBay.get(), extRef)).toList());
} else {
sclReportItems.add(SclReportItem.error(lDevicePath, "DO@name=Mod/DA@name=stVal not found in DataTypeTemplate"));
}
return extRefBayReferenceList;
}

/**
* Verify if an Extref matches the EPF Channel or not.
*
Expand Down Expand Up @@ -266,29 +299,27 @@ public List<SclReportItem> updateAllExtRefIedNames(SCL scd) {
@Override
public List<SclReportItem> manageBindingForLDEPF(SCL scd, EPF epf) {
List<SclReportItem> sclReportItems = new ArrayList<>();
if (!epf.isSetChannels()) return sclReportItems;
SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
sclRootAdapter.streamIEDAdapters()
.filter(iedAdapter -> !iedAdapter.getName().contains("TEST"))
.map(iedAdapter -> iedAdapter.findLDeviceAdapterByLdInst(LDEVICE_LDEPF))
.flatMap(Optional::stream)
.forEach(lDeviceAdapter -> lDeviceAdapter.getExtRefBayReferenceForActifLDEPF(sclReportItems)
.forEach(extRefBayRef -> epf.getChannels().getChannel().stream().filter(tChannel -> doesExtRefMatchLDEPFChannel(extRefBayRef.extRef(), tChannel))
.findFirst().ifPresent(channel -> {
List<TIED> iedSources = getIedSources(sclRootAdapter, extRefBayRef.compasBay(), channel);
if (iedSources.size() == 1) {
updateLDEPFExtRefBinding(extRefBayRef.extRef(), iedSources.get(0), channel);
sclReportItems.addAll(updateLDEPFDos(lDeviceAdapter, extRefBayRef.extRef(), channel));
} else {
if (iedSources.size() > 1) {
sclReportItems.add(SclReportItem.warning(null, "There is more than one IED source to bind the signal " +
"/IED@name=" + extRefBayRef.iedName() + "/LDevice@inst=LDEPF/LN0" +
"/ExtRef@desc=" + extRefBayRef.extRef().getDesc()));
}
// If the source IED is not found, there will be no update or report message.
}
}))
);
if (!epf.isSetChannels()) return sclReportItems;
iedService.getFilteredIeds(scd, ied -> !ied.getName().contains("TEST"))
.forEach(tied -> ldeviceService.findLdevice(tied, tlDevice -> LDEVICE_LDEPF.equals(tlDevice.getInst()))
.ifPresent(tlDevice -> getExtRefWithBayReferenceInLDEPF(scd.getDataTypeTemplates(), tied, tlDevice, sclReportItems)
.forEach(extRefBayRef -> epf.getChannels().getChannel().stream().filter(tChannel -> doesExtRefMatchLDEPFChannel(extRefBayRef.extRef(), tChannel))
.findFirst().ifPresent(channel -> {
List<TIED> iedSources = getIedSources(sclRootAdapter, extRefBayRef.compasBay(), channel);
if (iedSources.size() == 1) {
updateLDEPFExtRefBinding(extRefBayRef.extRef(), iedSources.get(0), channel);
LDeviceAdapter lDeviceAdapter = new LDeviceAdapter(new IEDAdapter(sclRootAdapter, tied.getName()), tlDevice);
sclReportItems.addAll(updateLDEPFDos(lDeviceAdapter, extRefBayRef.extRef(), channel));
} else {
if (iedSources.size() > 1) {
sclReportItems.add(SclReportItem.warning(null, "There is more than one IED source to bind the signal " +
"/IED@name=" + extRefBayRef.iedName() + "/LDevice@inst=LDEPF/LN0" +
"/ExtRef@desc=" + extRefBayRef.extRef().getDesc()));
}
// If the source IED is not found, there will be no update or report message.
}
}))));
return sclReportItems;
}

Expand Down Expand Up @@ -404,7 +435,6 @@ private String computeDaiValue(AbstractLNAdapter<?> lnAdapter, TExtRef extRef, S

@Override
public void debindCompasFlowsAndExtRefsBasedOnVoltageLevel(SCL scd) {
LdeviceService ldeviceService = new LdeviceService();
scd.getSubstation()
.stream()
.flatMap(tSubstation -> tSubstation.getVoltageLevel().stream())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,6 @@ && trimToEmpty(tfcda.getLnInst()).equals(trimToEmpty(bindingInfo.getLnInst()))
* @param compasBay The Bay object
* @param extRef The ExtRef object
*/
public record ExtRefBayReference(String iedName, TCompasBay compasBay, TExtRef extRef){ }
public record ExtRefWithBayReference(String iedName, TCompasBay compasBay, TExtRef extRef){ }

}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ public class InputsAdapter extends SclElementAdapter<LN0Adapter, TInputs> {
private static final String MESSAGE_INVALID_SERVICE_TYPE = "The signal ExtRef ServiceType attribute is unexpected : %s";
private static final String MESSAGE_IED_MISSING_COMPAS_BAY_UUID = "IED is missing Private/compas:Bay@UUID attribute";
private static final String MESSAGE_EXTREF_DESC_MALFORMED = "ExtRef.serviceType=Report but ExtRef.desc attribute is malformed";
private static final String MESSAGE_LDEVICE_STATUS_UNDEFINED = "The LDevice status is undefined";
private static final String MESSAGE_EXTREF_IEDNAME_DOES_NOT_MATCH_ANY_SYSTEM_VERSION_UUID = "The signal ExtRef iedName does not match any " +
"IED/Private/compas:ICDHeader@ICDSystemVersionUUID";
private static final String MESSAGE_SOURCE_LDEVICE_STATUS_UNDEFINED = "The signal ExtRef source LDevice %s status is undefined";
Expand Down Expand Up @@ -98,7 +97,7 @@ protected String elementXPath() {
public List<SclReportItem> updateAllExtRefIedNames(Map<String, IEDAdapter> icdSystemVersionToIed) {
Optional<String> optionalLDeviceStatus = getLDeviceAdapter().getLDeviceStatus();
if (optionalLDeviceStatus.isEmpty()) {
return List.of(getLDeviceAdapter().buildFatalReportItem(MESSAGE_LDEVICE_STATUS_UNDEFINED));
optionalLDeviceStatus = Optional.of(ActiveStatus.ON.getValue());
}
try {
ActiveStatus lDeviceStatus = ActiveStatus.fromValue(optionalLDeviceStatus.get());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@

import java.util.*;

import static org.lfenergy.compas.sct.commons.scl.ln.AbstractLNAdapter.MOD_DO_TYPE_NAME;
import static org.lfenergy.compas.sct.commons.scl.ln.AbstractLNAdapter.STVAL_DA_TYPE_NAME;
import static org.lfenergy.compas.sct.commons.util.CommonConstants.*;
import static org.lfenergy.compas.sct.commons.util.Utils.copySclElement;

Expand Down Expand Up @@ -489,33 +487,6 @@ private String createVal(TExtRef tExtRef) {
return sourceLdName + "/" + lnClass + "." + tExtRef.getSrcCBName();
}

/**
* Provides a list of ExtRef and associated Bay <br/>
* - The location of ExtRef should be in an active LDevice (inst=LDEPF) <br/>
* - ExtRef that lacks Bay or ICDHeader Private is not returned <br/>
*
* @param sclReportItems List of SclReportItem
* @return list of ExtRef and associated Bay
*/
public List<ExtRefInfo.ExtRefBayReference> getExtRefBayReferenceForActifLDEPF(final List<SclReportItem> sclReportItems) {
List<ExtRefInfo.ExtRefBayReference> extRefBayReferenceList = new ArrayList<>();
IEDAdapter parentIedAdapter = getParentAdapter();
if (parentIedAdapter.getPrivateCompasBay().isEmpty()) {
sclReportItems.add(SclReportItem.error(getXPath(), "The IED has no Private Bay"));
if (parentIedAdapter.getCompasICDHeader().isEmpty()) {
sclReportItems.add(SclReportItem.error(getXPath(), "The IED has no Private compas:ICDHeader"));
}
return Collections.emptyList();
}

getLDeviceStatus().map(ActiveStatus::fromValue).ifPresentOrElse(s -> {
if (ActiveStatus.ON.equals(s)) {
extRefBayReferenceList.addAll(getLN0Adapter().getInputsAdapter().getCurrentElem().getExtRef().stream().map(extRef -> new ExtRefInfo.ExtRefBayReference(parentIedAdapter.getName(), parentIedAdapter.getPrivateCompasBay().get(), extRef)).toList());
}
}, () -> sclReportItems.add(SclReportItem.error(getXPath(), "There is no DOI@name=" + MOD_DO_TYPE_NAME + "/DAI@name=" + STVAL_DA_TYPE_NAME + "/Val for LDevice@inst" + LDEVICE_LDEPF)));
return extRefBayReferenceList;
}

private TFCDA toFCDA(TFCDAFilter tfcdaFilter) {
TFCDA tfcda = new TFCDA();
tfcda.setLdInst(tfcdaFilter.getLdInst());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// SPDX-FileCopyrightText: 2024 RTE FRANCE
//
// SPDX-License-Identifier: Apache-2.0

package org.lfenergy.compas.sct.commons;

import org.junit.jupiter.api.Test;
import org.lfenergy.compas.scl2007b4.model.*;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

class DataTypeTemplatesServiceTest {

@Test
void isDoModAndDaStValExist_when_LNodeType_not_exist_should_return_false() {
//Given
SCL scl = new SCL();
TDataTypeTemplates dtt = new TDataTypeTemplates();
scl.setDataTypeTemplates(dtt);
//When
DataTypeTemplatesService dataTypeTemplatesService = new DataTypeTemplatesService();
boolean result = dataTypeTemplatesService.isDoModAndDaStValExist(dtt, "lnodeTypeId");
//Then
assertThat(result).isFalse();
}


@Test
void isDoModAndDaStValExist_when_Do_not_exist_should_return_false() {
//Given
SCL scl = new SCL();
TDataTypeTemplates dtt = new TDataTypeTemplates();
TLNodeType tlNodeType = new TLNodeType();
tlNodeType.setId("lnodeTypeId");
dtt.getLNodeType().add(tlNodeType);
scl.setDataTypeTemplates(dtt);
//When
DataTypeTemplatesService dataTypeTemplatesService = new DataTypeTemplatesService();
boolean result = dataTypeTemplatesService.isDoModAndDaStValExist(dtt, "lnodeTypeId");
//Then
assertThat(result).isFalse();
}

@Test
void isDoModAndDaStValExist_when_DoType_not_exist_should_return_false() {
//Given
SCL scl = new SCL();
TDataTypeTemplates dtt = new TDataTypeTemplates();
TLNodeType tlNodeType = new TLNodeType();
tlNodeType.setId("lnodeTypeId");
TDO tdo = new TDO();
tdo.setType("doTypeId");
tdo.setName("Mod");
tlNodeType.getDO().add(tdo);
dtt.getLNodeType().add(tlNodeType);
//When
DataTypeTemplatesService dataTypeTemplatesService = new DataTypeTemplatesService();
boolean result = dataTypeTemplatesService.isDoModAndDaStValExist(dtt, "lnodeTypeId");
//Then
assertThat(result).isFalse();
}


@Test
void isDoModAndDaStValExist_when_Da_Mod_not_exist_should_return_false() {
//Given
SCL scl = new SCL();
TDataTypeTemplates dtt = new TDataTypeTemplates();
TLNodeType tlNodeType = new TLNodeType();
tlNodeType.setId("lnodeTypeId");
TDO tdo = new TDO();
tdo.setType("doTypeId");
tdo.setName("Mod");
tlNodeType.getDO().add(tdo);
dtt.getLNodeType().add(tlNodeType);
TDOType tdoType = new TDOType();
tdoType.setId("doTypeId");
dtt.getDOType().add(tdoType);
scl.setDataTypeTemplates(dtt);
//When
DataTypeTemplatesService dataTypeTemplatesService = new DataTypeTemplatesService();
boolean result = dataTypeTemplatesService.isDoModAndDaStValExist(dtt, "lnodeTypeId");
//Then
assertThat(result).isFalse();
}


@Test
void isDoModAndDaStValExist_when_Da_stVal_not_found_should_return_false() {
//Given
SCL scl = new SCL();
TDataTypeTemplates dtt = new TDataTypeTemplates();
TLNodeType tlNodeType = new TLNodeType();
tlNodeType.setId("lnodeTypeId");
TDO tdo = new TDO();
tdo.setType("doTypeId");
tdo.setName("Mod");
tlNodeType.getDO().add(tdo);
dtt.getLNodeType().add(tlNodeType);
TDOType tdoType = new TDOType();
tdoType.setId("doTypeId");
TDA tda = new TDA();
tda.setName("daName");
tdoType.getSDOOrDA().add(tda);
dtt.getDOType().add(tdoType);
scl.setDataTypeTemplates(dtt);
//When
DataTypeTemplatesService dataTypeTemplatesService = new DataTypeTemplatesService();
boolean result = dataTypeTemplatesService.isDoModAndDaStValExist(dtt, "lnodeTypeId");
//Then
assertThat(result).isFalse();
}


@Test
void isDoModAndDaStValExist_when_DO_Mod_And_DA_stVal_exist_return_true() {
//Given
SCL scl = new SCL();
TDataTypeTemplates dtt = new TDataTypeTemplates();
TLNodeType tlNodeType = new TLNodeType();
tlNodeType.setId("lnodeTypeId");
TDO tdo = new TDO();
tdo.setType("doTypeId");
tdo.setName("Mod");
tlNodeType.getDO().add(tdo);
dtt.getLNodeType().add(tlNodeType);
TDOType tdoType = new TDOType();
tdoType.setId("doTypeId");
TDA tda = new TDA();
tda.setName("stVal");
tdoType.getSDOOrDA().add(tda);
dtt.getDOType().add(tdoType);
scl.setDataTypeTemplates(dtt);
//When
DataTypeTemplatesService dataTypeTemplatesService = new DataTypeTemplatesService();
boolean result = dataTypeTemplatesService.isDoModAndDaStValExist(dtt, "lnodeTypeId");
//Then
assertThat(result).isTrue();
}
}
Loading

0 comments on commit 702a8d8

Please sign in to comment.