Skip to content

Commit fe12ba7

Browse files
Merge pull request #278 from com-pas/develop
Merge develop into main for pre-release
2 parents c5e74c7 + db735e7 commit fe12ba7

17 files changed

+1517
-251
lines changed

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ExtRefInfo.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77

88
import lombok.*;
9+
import org.lfenergy.compas.scl2007b4.model.TCompasBay;
910
import org.lfenergy.compas.scl2007b4.model.TExtRef;
1011
import org.lfenergy.compas.scl2007b4.model.TFCDA;
1112
/**
@@ -91,4 +92,12 @@ public boolean checkMatchingFCDA(@NonNull TFCDA tfcda){
9192
return fcdaInfo.checkFCDACompatibilitiesForBinding(fcdaOfBinding);
9293
}
9394

95+
/**
96+
* ExtRef and related Bay model
97+
* @param iedName The name of the IED containing bay
98+
* @param compasBay The Bay object
99+
* @param extRef The ExtRef object
100+
*/
101+
public record ExtRefBayReference(String iedName, TCompasBay compasBay, TExtRef extRef){ }
102+
94103
}

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/LDEPFSettings.java

Lines changed: 0 additions & 25 deletions
This file was deleted.
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// SPDX-FileCopyrightText: 2023 RTE FRANCE
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
package org.lfenergy.compas.sct.commons.dto;
6+
7+
import java.math.BigInteger;
8+
import java.util.List;
9+
import java.util.Optional;
10+
import java.util.function.*;
11+
12+
import lombok.Builder;
13+
import org.apache.commons.lang3.StringUtils;
14+
import org.lfenergy.compas.scl2007b4.model.*;
15+
import org.lfenergy.compas.sct.commons.exception.ScdException;
16+
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
17+
import org.lfenergy.compas.sct.commons.scl.ied.AbstractLNAdapter;
18+
import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter;
19+
import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter;
20+
import org.lfenergy.compas.sct.commons.util.LDeviceStatus;
21+
import org.lfenergy.compas.sct.commons.util.Utils;
22+
23+
24+
/**
25+
* Represents a list of LDEPF settings
26+
*
27+
* This is a functional interface whose functional method is @getSettings
28+
*/
29+
@FunctionalInterface
30+
public interface LDEPFSettingsSupplier {
31+
32+
/**
33+
* This method provides list of LDEPF settings
34+
*/
35+
List<LDEPFSetting> getSettings();
36+
37+
@Builder
38+
record LDEPFSetting(String rteIedType, String iedRedundancy, BigInteger iedInstance,
39+
String channelShortLabel, String channelMREP, String channelLevModQ,
40+
String channelLevModLevMod, String bapVariant, String bapIgnoredValue,
41+
String ldInst, String lnPrefix, String lnClass, String lnInst,
42+
String doName, String doInst, String sdoName,
43+
String daName, String daType,
44+
String dabType, String bdaName, String sbdaName,
45+
String channelAnalogNum, String channelDigitalNum, String opt) {
46+
}
47+
48+
BiPredicate<LDEPFSetting, TExtRef> isAnalogMatchDesc = (setting, extRef) ->
49+
setting.channelAnalogNum() != null && setting.channelDigitalNum() == null
50+
&& extRef.getDesc().startsWith("DYN_LDEPF_ANALOG CHANNEL " + setting.channelAnalogNum()+"_1_AnalogueValue")
51+
&& extRef.getDesc().endsWith("_" + setting.daName() + "_1");
52+
BiPredicate<LDEPFSetting, TExtRef> isDigitalMatchDesc = (setting, extRef) ->
53+
setting.channelDigitalNum() != null && setting.channelAnalogNum() == null
54+
&& extRef.getDesc().startsWith("DYN_LDEPF_DIGITAL CHANNEL " + setting.channelDigitalNum()+"_1_BOOLEEN")
55+
&& extRef.getDesc().endsWith("_" + setting.daName() + "_1");
56+
57+
58+
BiPredicate<IEDAdapter, LDEPFSetting> isIcdHeaderMatch = (iedAdapter, setting) -> iedAdapter.getCompasICDHeader()
59+
.map(compasICDHeader -> compasICDHeader.getIEDType().value().equals(setting.rteIedType())
60+
&& compasICDHeader.getIEDredundancy().value().equals(setting.iedRedundancy())
61+
&& compasICDHeader.getIEDSystemVersioninstance().equals(setting.iedInstance()))
62+
.orElse(false);
63+
64+
BiFunction<IEDAdapter, LDEPFSetting, Optional<LDeviceAdapter>> getActiveSourceLDevice = (iedAdapter, setting) ->
65+
iedAdapter.findLDeviceAdapterByLdInst(setting.ldInst())
66+
.filter(lDeviceAdapter -> lDeviceAdapter.getLDeviceStatus()
67+
.map(status -> status.equals(LDeviceStatus.ON))
68+
.orElse(false))
69+
.stream().findFirst();
70+
71+
BiFunction<LDeviceAdapter, LDEPFSetting, Optional<AbstractLNAdapter<?>>> getActiveLNodeSource = (lDeviceAdapter, setting) ->
72+
lDeviceAdapter.getLNAdaptersIncludingLN0().stream()
73+
.filter(lnAdapter -> lnAdapter.getLNClass().equals(setting.lnClass())
74+
&& lnAdapter.getLNInst().equals(setting.lnInst())
75+
&& Utils.equalsOrBothBlank(setting.lnPrefix(), lnAdapter.getPrefix()))
76+
.findFirst()
77+
.filter(lnAdapter -> lnAdapter.getDaiModStValValue()
78+
.map(status -> status.equals(LDeviceStatus.ON))
79+
.orElse(true));
80+
81+
BiPredicate<AbstractLNAdapter<?>, LDEPFSetting> isValidDataTypeTemplate = (lnAdapter, setting) -> {
82+
String doName = setting.doInst() == null || setting.doInst().equals("0") ? setting.doName() : setting.doName()+setting.doInst();
83+
var lnType = lnAdapter.getLnType();
84+
return StringUtils.isEmpty(doName) || StringUtils.isEmpty(setting.daName()) ||
85+
lnAdapter.getDataTypeTemplateAdapter().getLNodeTypeAdapterById(lnType)
86+
.filter(lNodeTypeAdapter -> {
87+
try {
88+
lNodeTypeAdapter.check(new DoTypeName(doName), new DaTypeName(setting.daName()));
89+
} catch (ScdException ex) {
90+
return false;
91+
}
92+
return true;
93+
}).isPresent();
94+
};
95+
96+
/**
97+
* Provides the matching setting for an ExtRef.
98+
* @param extRef The ExtRef object
99+
* @return the matching LDEPFSetting for an ExtRef
100+
*/
101+
default Optional<LDEPFSetting> getLDEPFSettingMatchingExtRef(TExtRef extRef) {
102+
if(!extRef.isSetDesc()) return Optional.empty();
103+
return getSettings().stream()
104+
.filter(setting -> isAnalogMatchDesc.or(isDigitalMatchDesc).test(setting, extRef))
105+
.filter(setting -> extRef.isSetPLN() && Utils.lnClassEquals(extRef.getPLN(), setting.lnClass())
106+
&& extRef.isSetPDO() && extRef.getPDO().equals(setting.doName()))
107+
.findFirst();
108+
}
109+
110+
/**
111+
* Provides the IED sources that belong to the LDEPF setting <br/>
112+
* Example of this setting include:
113+
* 1. COMPAS-Bay and COMPAS-ICDHeader verification.<br/>
114+
* 2. Active LDevice source object with the same DO/DA hierarchy as the LDEPF setting.
115+
* @param sclRootAdapter SCL
116+
* @param compasBay TCompasBay
117+
* @param setting LDEPFSetting
118+
* @return the IED sources matching the LDEPFSetting
119+
*/
120+
default List<TIED> getIedSources(SclRootAdapter sclRootAdapter, TCompasBay compasBay, LDEPFSetting setting) {
121+
return sclRootAdapter.streamIEDAdapters()
122+
.filter(iedAdapter -> iedAdapter.getPrivateCompasBay().filter(bay -> bay.getUUID().equals(compasBay.getUUID())).isPresent())
123+
.filter(iedAdapter -> isIcdHeaderMatch.test(iedAdapter, setting))
124+
.filter(iedAdapter -> getActiveSourceLDevice.apply(iedAdapter, setting)
125+
.filter(lDeviceAdapter -> getActiveLNodeSource.apply(lDeviceAdapter, setting)
126+
.filter(lnAdapter -> isValidDataTypeTemplate.test(lnAdapter, setting)).isPresent())
127+
.isPresent())
128+
.map(IEDAdapter::getCurrentElem).limit(2).toList();
129+
}
130+
131+
}

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ExtRefService.java

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,12 @@
55
package org.lfenergy.compas.sct.commons.scl;
66

77
import org.apache.commons.lang3.StringUtils;
8-
import org.lfenergy.compas.scl2007b4.model.SCL;
9-
import org.lfenergy.compas.scl2007b4.model.TCompasICDHeader;
10-
import org.lfenergy.compas.scl2007b4.model.TExtRef;
11-
import org.lfenergy.compas.scl2007b4.model.TIED;
12-
import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings;
13-
import org.lfenergy.compas.sct.commons.dto.SclReport;
14-
import org.lfenergy.compas.sct.commons.dto.SclReportItem;
8+
import org.lfenergy.compas.scl2007b4.model.*;
9+
import org.lfenergy.compas.sct.commons.dto.*;
10+
import org.lfenergy.compas.sct.commons.dto.LDEPFSettingsSupplier.LDEPFSetting;
11+
import org.lfenergy.compas.sct.commons.dto.ExtRefInfo.ExtRefBayReference;
1512
import org.lfenergy.compas.sct.commons.exception.ScdException;
16-
import org.lfenergy.compas.sct.commons.scl.ied.ControlBlockAdapter;
17-
import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter;
18-
import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter;
19-
import org.lfenergy.compas.sct.commons.scl.ied.LN0Adapter;
13+
import org.lfenergy.compas.sct.commons.scl.ied.*;
2014
import org.lfenergy.compas.sct.commons.util.ControlBlockEnum;
2115
import org.lfenergy.compas.sct.commons.util.PrivateEnum;
2216
import org.lfenergy.compas.sct.commons.util.Utils;
@@ -27,6 +21,7 @@
2721
import java.util.stream.Stream;
2822

2923
import static org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings.*;
24+
import static org.lfenergy.compas.sct.commons.util.CommonConstants.IED_TEST_NAME;
3025
import static org.lfenergy.compas.sct.commons.util.Utils.isExtRefFeedBySameControlBlock;
3126

3227
public final class ExtRefService {
@@ -245,4 +240,50 @@ public static List<TExtRef> filterDuplicatedExtRefs(List<TExtRef> tExtRefs) {
245240
});
246241
return filteredList;
247242
}
243+
244+
245+
/**
246+
* ExtRef Binding For LDevice (inst=LDEPF) that matching LDEPF configuration
247+
* @param scd SCL
248+
* @param settingsSupplier LDEPFSettingsSupplier
249+
* @return a report contains errors
250+
*/
251+
public static SclReport manageBindingForLDEPF(SCL scd, LDEPFSettingsSupplier settingsSupplier) {
252+
SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
253+
List<SclReportItem> sclReportItems = new ArrayList<>();
254+
List<ExtRefBayReference> extRefBayReferences = sclRootAdapter.streamIEDAdapters()
255+
.filter(iedAdapter -> !iedAdapter.getName().equals(IED_TEST_NAME))
256+
.map(iedAdapter -> iedAdapter.getExtRefBayReferenceForActifLDEPF(sclReportItems))
257+
.flatMap(List::stream).toList();
258+
for (ExtRefBayReference extRefBayRef: extRefBayReferences){
259+
var lDPFSettingMatchingExtRef = settingsSupplier.getLDEPFSettingMatchingExtRef(extRefBayRef.extRef());
260+
if(lDPFSettingMatchingExtRef.isPresent()){
261+
List<TIED> iedSources = settingsSupplier.getIedSources(sclRootAdapter, extRefBayRef.compasBay(), lDPFSettingMatchingExtRef.get());
262+
if(iedSources.size() != 1) {
263+
if(iedSources.size() > 1) {
264+
sclReportItems.add(SclReportItem.warning(null, "There is more than one IED source to bind the signal " +
265+
"/IED@name="+extRefBayRef.iedName()+"/LDevice@inst=LDEPF/LN0" +
266+
"/ExtRef@desc="+extRefBayRef.extRef().getDesc()));
267+
}
268+
continue;
269+
}
270+
updateLDEPFExtRefBinding(extRefBayRef.extRef(), iedSources.get(0), lDPFSettingMatchingExtRef.get());
271+
}
272+
}
273+
return new SclReport(sclRootAdapter, sclReportItems);
274+
}
275+
276+
private static void updateLDEPFExtRefBinding(TExtRef extRef, TIED iedSource, LDEPFSetting setting) {
277+
extRef.setIedName(iedSource.getName());
278+
extRef.setLdInst(setting.ldInst());
279+
extRef.getLnClass().add(setting.lnClass());
280+
extRef.setLnInst(setting.lnInst());
281+
if(setting.lnPrefix() != null){
282+
extRef.setPrefix(setting.lnPrefix());
283+
}
284+
var doName = setting.doInst().equals("0") ? setting.doName() : setting.doName()+setting.doInst() ;
285+
extRef.setDoName(doName);
286+
287+
}
288+
248289
}

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SclService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.stream.Collectors;
2626

2727
import static org.lfenergy.compas.sct.commons.util.CommonConstants.ICD_SYSTEM_VERSION_UUID;
28+
import static org.lfenergy.compas.sct.commons.util.CommonConstants.IED_TEST_NAME;
2829
import static org.lfenergy.compas.sct.commons.util.PrivateEnum.COMPAS_ICDHEADER;
2930

3031
/**
@@ -80,7 +81,6 @@ public class SclService {
8081

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

8585
private SclService() {
8686
throw new IllegalStateException("SclService class");

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/IEDAdapter.java

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,24 @@
88
import org.apache.commons.lang3.StringUtils;
99
import org.lfenergy.compas.scl2007b4.model.*;
1010
import org.lfenergy.compas.sct.commons.dto.ExtRefBindingInfo;
11+
import org.lfenergy.compas.sct.commons.dto.ExtRefInfo.ExtRefBayReference;
1112
import org.lfenergy.compas.sct.commons.dto.ExtRefSignalInfo;
1213
import org.lfenergy.compas.sct.commons.dto.SclReportItem;
1314
import org.lfenergy.compas.sct.commons.exception.ScdException;
1415
import org.lfenergy.compas.sct.commons.scl.ObjectReference;
1516
import org.lfenergy.compas.sct.commons.scl.PrivateService;
1617
import org.lfenergy.compas.sct.commons.scl.SclElementAdapter;
1718
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
18-
import org.lfenergy.compas.sct.commons.util.MonitoringLnClassEnum;
19-
import org.lfenergy.compas.sct.commons.util.ServicesConfigEnum;
20-
import org.lfenergy.compas.sct.commons.util.Utils;
19+
import org.lfenergy.compas.sct.commons.util.*;
2120

2221
import java.util.*;
2322
import java.util.function.Function;
2423
import java.util.stream.Stream;
2524

25+
import static org.lfenergy.compas.sct.commons.scl.ied.AbstractLNAdapter.MOD_DO_TYPE_NAME;
26+
import static org.lfenergy.compas.sct.commons.scl.ied.AbstractLNAdapter.STVAL_DA_TYPE_NAME;
27+
import static org.lfenergy.compas.sct.commons.util.CommonConstants.LDEVICE_LDEPF;
28+
2629
/**
2730
* A representation of the model object
2831
* <em><b>{@link org.lfenergy.compas.scl2007b4.model.TIED IED}</b></em>.
@@ -414,5 +417,35 @@ private List<TExtRef> retrieveAllExtRefForServiceType(TServiceType tServiceType)
414417
.toList();
415418
}
416419

420+
/**
421+
* Provides a list of ExtRef and associated Bay <br/>
422+
* - The location of ExtRef should be in an active LDevice (inst=LDEPF) <br/>
423+
* - ExtRef that lacks Bay or ICDHeader Private is not returned <br/>
424+
* @param sclReportItems List of SclReportItem
425+
* @return list of ExtRef and associated Bay
426+
*/
427+
public List<ExtRefBayReference> getExtRefBayReferenceForActifLDEPF(final List<SclReportItem> sclReportItems) {
428+
return findLDeviceAdapterByLdInst(LDEVICE_LDEPF)
429+
.filter(lDeviceAdapter -> {
430+
if(getPrivateCompasBay().isEmpty()) {
431+
sclReportItems.add(SclReportItem.fatal(getXPath(), "The IED has no Private Bay"));
432+
if(getCompasICDHeader().isEmpty()) {
433+
sclReportItems.add(SclReportItem.fatal(getXPath(), "The IED has no Private compas:ICDHeader"));
434+
}
435+
return false;
436+
}
437+
if(lDeviceAdapter.getLDeviceStatus().isEmpty()) {
438+
sclReportItems.add(SclReportItem.fatal(getXPath(),
439+
"There is no DOI@name="+MOD_DO_TYPE_NAME+"/DAI@name="+STVAL_DA_TYPE_NAME + "/Val for LDevice@inst"+LDEVICE_LDEPF));
440+
return false;
441+
}
442+
return lDeviceAdapter.getLDeviceStatus().get().equals(LDeviceStatus.ON);
443+
})
444+
.map(lDeviceAdapter -> lDeviceAdapter.getLN0Adapter()
445+
.getInputsAdapter().getCurrentElem().getExtRef().stream()
446+
.map(extRef -> new ExtRefBayReference(getName(), getPrivateCompasBay().get(), extRef))
447+
.toList())
448+
.stream().flatMap(List::stream).toList();
449+
}
417450

418451
}

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/CommonConstants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ public final class CommonConstants {
2222
public static final String CONTROLBLOCK_NAME_PREFIX = "CB" + ATTRIBUTE_VALUE_SEPARATOR;
2323
public static final String DATASET_NAME_PREFIX = "DS" + ATTRIBUTE_VALUE_SEPARATOR;
2424

25+
public static final String LDEVICE_LDEPF = "LDEPF";
26+
public static final String IED_TEST_NAME = "IEDTEST";
27+
2528
/**
2629
* Private Controlller, should not be instanced
2730
*/

0 commit comments

Comments
 (0)