Skip to content

Commit

Permalink
Merge pull request #278 from com-pas/develop
Browse files Browse the repository at this point in the history
Merge develop into main for pre-release
  • Loading branch information
samirromdhani authored Apr 25, 2023
2 parents c5e74c7 + db735e7 commit fe12ba7
Show file tree
Hide file tree
Showing 17 changed files with 1,517 additions and 251 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


import lombok.*;
import org.lfenergy.compas.scl2007b4.model.TCompasBay;
import org.lfenergy.compas.scl2007b4.model.TExtRef;
import org.lfenergy.compas.scl2007b4.model.TFCDA;
/**
Expand Down Expand Up @@ -91,4 +92,12 @@ public boolean checkMatchingFCDA(@NonNull TFCDA tfcda){
return fcdaInfo.checkFCDACompatibilitiesForBinding(fcdaOfBinding);
}

/**
* ExtRef and related Bay model
* @param iedName The name of the IED containing bay
* @param compasBay The Bay object
* @param extRef The ExtRef object
*/
public record ExtRefBayReference(String iedName, TCompasBay compasBay, TExtRef extRef){ }

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// SPDX-FileCopyrightText: 2023 RTE FRANCE
//
// SPDX-License-Identifier: Apache-2.0

package org.lfenergy.compas.sct.commons.dto;

import java.math.BigInteger;
import java.util.List;
import java.util.Optional;
import java.util.function.*;

import lombok.Builder;
import org.apache.commons.lang3.StringUtils;
import org.lfenergy.compas.scl2007b4.model.*;
import org.lfenergy.compas.sct.commons.exception.ScdException;
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
import org.lfenergy.compas.sct.commons.scl.ied.AbstractLNAdapter;
import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter;
import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter;
import org.lfenergy.compas.sct.commons.util.LDeviceStatus;
import org.lfenergy.compas.sct.commons.util.Utils;


/**
* Represents a list of LDEPF settings
*
* This is a functional interface whose functional method is @getSettings
*/
@FunctionalInterface
public interface LDEPFSettingsSupplier {

/**
* This method provides list of LDEPF settings
*/
List<LDEPFSetting> getSettings();

@Builder
record LDEPFSetting(String rteIedType, String iedRedundancy, BigInteger iedInstance,
String channelShortLabel, String channelMREP, String channelLevModQ,
String channelLevModLevMod, String bapVariant, String bapIgnoredValue,
String ldInst, String lnPrefix, String lnClass, String lnInst,
String doName, String doInst, String sdoName,
String daName, String daType,
String dabType, String bdaName, String sbdaName,
String channelAnalogNum, String channelDigitalNum, String opt) {
}

BiPredicate<LDEPFSetting, TExtRef> isAnalogMatchDesc = (setting, extRef) ->
setting.channelAnalogNum() != null && setting.channelDigitalNum() == null
&& extRef.getDesc().startsWith("DYN_LDEPF_ANALOG CHANNEL " + setting.channelAnalogNum()+"_1_AnalogueValue")
&& extRef.getDesc().endsWith("_" + setting.daName() + "_1");
BiPredicate<LDEPFSetting, TExtRef> isDigitalMatchDesc = (setting, extRef) ->
setting.channelDigitalNum() != null && setting.channelAnalogNum() == null
&& extRef.getDesc().startsWith("DYN_LDEPF_DIGITAL CHANNEL " + setting.channelDigitalNum()+"_1_BOOLEEN")
&& extRef.getDesc().endsWith("_" + setting.daName() + "_1");


BiPredicate<IEDAdapter, LDEPFSetting> isIcdHeaderMatch = (iedAdapter, setting) -> iedAdapter.getCompasICDHeader()
.map(compasICDHeader -> compasICDHeader.getIEDType().value().equals(setting.rteIedType())
&& compasICDHeader.getIEDredundancy().value().equals(setting.iedRedundancy())
&& compasICDHeader.getIEDSystemVersioninstance().equals(setting.iedInstance()))
.orElse(false);

BiFunction<IEDAdapter, LDEPFSetting, Optional<LDeviceAdapter>> getActiveSourceLDevice = (iedAdapter, setting) ->
iedAdapter.findLDeviceAdapterByLdInst(setting.ldInst())
.filter(lDeviceAdapter -> lDeviceAdapter.getLDeviceStatus()
.map(status -> status.equals(LDeviceStatus.ON))
.orElse(false))
.stream().findFirst();

BiFunction<LDeviceAdapter, LDEPFSetting, Optional<AbstractLNAdapter<?>>> getActiveLNodeSource = (lDeviceAdapter, setting) ->
lDeviceAdapter.getLNAdaptersIncludingLN0().stream()
.filter(lnAdapter -> lnAdapter.getLNClass().equals(setting.lnClass())
&& lnAdapter.getLNInst().equals(setting.lnInst())
&& Utils.equalsOrBothBlank(setting.lnPrefix(), lnAdapter.getPrefix()))
.findFirst()
.filter(lnAdapter -> lnAdapter.getDaiModStValValue()
.map(status -> status.equals(LDeviceStatus.ON))
.orElse(true));

BiPredicate<AbstractLNAdapter<?>, LDEPFSetting> isValidDataTypeTemplate = (lnAdapter, setting) -> {
String doName = setting.doInst() == null || setting.doInst().equals("0") ? setting.doName() : setting.doName()+setting.doInst();
var lnType = lnAdapter.getLnType();
return StringUtils.isEmpty(doName) || StringUtils.isEmpty(setting.daName()) ||
lnAdapter.getDataTypeTemplateAdapter().getLNodeTypeAdapterById(lnType)
.filter(lNodeTypeAdapter -> {
try {
lNodeTypeAdapter.check(new DoTypeName(doName), new DaTypeName(setting.daName()));
} catch (ScdException ex) {
return false;
}
return true;
}).isPresent();
};

/**
* Provides the matching setting for an ExtRef.
* @param extRef The ExtRef object
* @return the matching LDEPFSetting for an ExtRef
*/
default Optional<LDEPFSetting> getLDEPFSettingMatchingExtRef(TExtRef extRef) {
if(!extRef.isSetDesc()) return Optional.empty();
return getSettings().stream()
.filter(setting -> isAnalogMatchDesc.or(isDigitalMatchDesc).test(setting, extRef))
.filter(setting -> extRef.isSetPLN() && Utils.lnClassEquals(extRef.getPLN(), setting.lnClass())
&& extRef.isSetPDO() && extRef.getPDO().equals(setting.doName()))
.findFirst();
}

/**
* Provides the IED sources that belong to the LDEPF setting <br/>
* Example of this setting include:
* 1. COMPAS-Bay and COMPAS-ICDHeader verification.<br/>
* 2. Active LDevice source object with the same DO/DA hierarchy as the LDEPF setting.
* @param sclRootAdapter SCL
* @param compasBay TCompasBay
* @param setting LDEPFSetting
* @return the IED sources matching the LDEPFSetting
*/
default List<TIED> getIedSources(SclRootAdapter sclRootAdapter, TCompasBay compasBay, LDEPFSetting setting) {
return sclRootAdapter.streamIEDAdapters()
.filter(iedAdapter -> iedAdapter.getPrivateCompasBay().filter(bay -> bay.getUUID().equals(compasBay.getUUID())).isPresent())
.filter(iedAdapter -> isIcdHeaderMatch.test(iedAdapter, setting))
.filter(iedAdapter -> getActiveSourceLDevice.apply(iedAdapter, setting)
.filter(lDeviceAdapter -> getActiveLNodeSource.apply(lDeviceAdapter, setting)
.filter(lnAdapter -> isValidDataTypeTemplate.test(lnAdapter, setting)).isPresent())
.isPresent())
.map(IEDAdapter::getCurrentElem).limit(2).toList();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,12 @@
package org.lfenergy.compas.sct.commons.scl;

import org.apache.commons.lang3.StringUtils;
import org.lfenergy.compas.scl2007b4.model.SCL;
import org.lfenergy.compas.scl2007b4.model.TCompasICDHeader;
import org.lfenergy.compas.scl2007b4.model.TExtRef;
import org.lfenergy.compas.scl2007b4.model.TIED;
import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings;
import org.lfenergy.compas.sct.commons.dto.SclReport;
import org.lfenergy.compas.sct.commons.dto.SclReportItem;
import org.lfenergy.compas.scl2007b4.model.*;
import org.lfenergy.compas.sct.commons.dto.*;
import org.lfenergy.compas.sct.commons.dto.LDEPFSettingsSupplier.LDEPFSetting;
import org.lfenergy.compas.sct.commons.dto.ExtRefInfo.ExtRefBayReference;
import org.lfenergy.compas.sct.commons.exception.ScdException;
import org.lfenergy.compas.sct.commons.scl.ied.ControlBlockAdapter;
import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter;
import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter;
import org.lfenergy.compas.sct.commons.scl.ied.LN0Adapter;
import org.lfenergy.compas.sct.commons.scl.ied.*;
import org.lfenergy.compas.sct.commons.util.ControlBlockEnum;
import org.lfenergy.compas.sct.commons.util.PrivateEnum;
import org.lfenergy.compas.sct.commons.util.Utils;
Expand All @@ -27,6 +21,7 @@
import java.util.stream.Stream;

import static org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings.*;
import static org.lfenergy.compas.sct.commons.util.CommonConstants.IED_TEST_NAME;
import static org.lfenergy.compas.sct.commons.util.Utils.isExtRefFeedBySameControlBlock;

public final class ExtRefService {
Expand Down Expand Up @@ -245,4 +240,50 @@ public static List<TExtRef> filterDuplicatedExtRefs(List<TExtRef> tExtRefs) {
});
return filteredList;
}


/**
* ExtRef Binding For LDevice (inst=LDEPF) that matching LDEPF configuration
* @param scd SCL
* @param settingsSupplier LDEPFSettingsSupplier
* @return a report contains errors
*/
public static SclReport manageBindingForLDEPF(SCL scd, LDEPFSettingsSupplier settingsSupplier) {
SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
List<SclReportItem> sclReportItems = new ArrayList<>();
List<ExtRefBayReference> extRefBayReferences = sclRootAdapter.streamIEDAdapters()
.filter(iedAdapter -> !iedAdapter.getName().equals(IED_TEST_NAME))
.map(iedAdapter -> iedAdapter.getExtRefBayReferenceForActifLDEPF(sclReportItems))
.flatMap(List::stream).toList();
for (ExtRefBayReference extRefBayRef: extRefBayReferences){
var lDPFSettingMatchingExtRef = settingsSupplier.getLDEPFSettingMatchingExtRef(extRefBayRef.extRef());
if(lDPFSettingMatchingExtRef.isPresent()){
List<TIED> iedSources = settingsSupplier.getIedSources(sclRootAdapter, extRefBayRef.compasBay(), lDPFSettingMatchingExtRef.get());
if(iedSources.size() != 1) {
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()));
}
continue;
}
updateLDEPFExtRefBinding(extRefBayRef.extRef(), iedSources.get(0), lDPFSettingMatchingExtRef.get());
}
}
return new SclReport(sclRootAdapter, sclReportItems);
}

private static void updateLDEPFExtRefBinding(TExtRef extRef, TIED iedSource, LDEPFSetting setting) {
extRef.setIedName(iedSource.getName());
extRef.setLdInst(setting.ldInst());
extRef.getLnClass().add(setting.lnClass());
extRef.setLnInst(setting.lnInst());
if(setting.lnPrefix() != null){
extRef.setPrefix(setting.lnPrefix());
}
var doName = setting.doInst().equals("0") ? setting.doName() : setting.doName()+setting.doInst() ;
extRef.setDoName(doName);

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.stream.Collectors;

import static org.lfenergy.compas.sct.commons.util.CommonConstants.ICD_SYSTEM_VERSION_UUID;
import static org.lfenergy.compas.sct.commons.util.CommonConstants.IED_TEST_NAME;
import static org.lfenergy.compas.sct.commons.util.PrivateEnum.COMPAS_ICDHEADER;

/**
Expand Down Expand Up @@ -80,7 +81,6 @@ public class SclService {

private static final String UNKNOWN_LDEVICE_S_IN_IED_S = "Unknown LDevice (%s) in IED (%s)";
private static final String INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO = "Invalid or missing attributes in ExtRef binding info";
private static final String IED_TEST_NAME = "IEDTEST";

private SclService() {
throw new IllegalStateException("SclService class");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,24 @@
import org.apache.commons.lang3.StringUtils;
import org.lfenergy.compas.scl2007b4.model.*;
import org.lfenergy.compas.sct.commons.dto.ExtRefBindingInfo;
import org.lfenergy.compas.sct.commons.dto.ExtRefInfo.ExtRefBayReference;
import org.lfenergy.compas.sct.commons.dto.ExtRefSignalInfo;
import org.lfenergy.compas.sct.commons.dto.SclReportItem;
import org.lfenergy.compas.sct.commons.exception.ScdException;
import org.lfenergy.compas.sct.commons.scl.ObjectReference;
import org.lfenergy.compas.sct.commons.scl.PrivateService;
import org.lfenergy.compas.sct.commons.scl.SclElementAdapter;
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
import org.lfenergy.compas.sct.commons.util.MonitoringLnClassEnum;
import org.lfenergy.compas.sct.commons.util.ServicesConfigEnum;
import org.lfenergy.compas.sct.commons.util.Utils;
import org.lfenergy.compas.sct.commons.util.*;

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

import static org.lfenergy.compas.sct.commons.scl.ied.AbstractLNAdapter.MOD_DO_TYPE_NAME;
import static org.lfenergy.compas.sct.commons.scl.ied.AbstractLNAdapter.STVAL_DA_TYPE_NAME;
import static org.lfenergy.compas.sct.commons.util.CommonConstants.LDEVICE_LDEPF;

/**
* A representation of the model object
* <em><b>{@link org.lfenergy.compas.scl2007b4.model.TIED IED}</b></em>.
Expand Down Expand Up @@ -414,5 +417,35 @@ private List<TExtRef> retrieveAllExtRefForServiceType(TServiceType tServiceType)
.toList();
}

/**
* 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<ExtRefBayReference> getExtRefBayReferenceForActifLDEPF(final List<SclReportItem> sclReportItems) {
return findLDeviceAdapterByLdInst(LDEVICE_LDEPF)
.filter(lDeviceAdapter -> {
if(getPrivateCompasBay().isEmpty()) {
sclReportItems.add(SclReportItem.fatal(getXPath(), "The IED has no Private Bay"));
if(getCompasICDHeader().isEmpty()) {
sclReportItems.add(SclReportItem.fatal(getXPath(), "The IED has no Private compas:ICDHeader"));
}
return false;
}
if(lDeviceAdapter.getLDeviceStatus().isEmpty()) {
sclReportItems.add(SclReportItem.fatal(getXPath(),
"There is no DOI@name="+MOD_DO_TYPE_NAME+"/DAI@name="+STVAL_DA_TYPE_NAME + "/Val for LDevice@inst"+LDEVICE_LDEPF));
return false;
}
return lDeviceAdapter.getLDeviceStatus().get().equals(LDeviceStatus.ON);
})
.map(lDeviceAdapter -> lDeviceAdapter.getLN0Adapter()
.getInputsAdapter().getCurrentElem().getExtRef().stream()
.map(extRef -> new ExtRefBayReference(getName(), getPrivateCompasBay().get(), extRef))
.toList())
.stream().flatMap(List::stream).toList();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ public final class CommonConstants {
public static final String CONTROLBLOCK_NAME_PREFIX = "CB" + ATTRIBUTE_VALUE_SEPARATOR;
public static final String DATASET_NAME_PREFIX = "DS" + ATTRIBUTE_VALUE_SEPARATOR;

public static final String LDEVICE_LDEPF = "LDEPF";
public static final String IED_TEST_NAME = "IEDTEST";

/**
* Private Controlller, should not be instanced
*/
Expand Down
Loading

0 comments on commit fe12ba7

Please sign in to comment.