44
55package org .lfenergy .compas .sct .commons ;
66
7+ import lombok .Getter ;
78import lombok .RequiredArgsConstructor ;
89import org .lfenergy .compas .scl2007b4 .model .*;
910import org .lfenergy .compas .sct .commons .api .ExtRefEditor ;
1516import org .lfenergy .compas .sct .commons .model .epf .TCBScopeType ;
1617import org .lfenergy .compas .sct .commons .model .epf .TChannel ;
1718import org .lfenergy .compas .sct .commons .model .epf .TChannelType ;
19+ import org .lfenergy .compas .sct .commons .model .epf .TChannelLevMod ;
1820import org .lfenergy .compas .sct .commons .scl .SclRootAdapter ;
1921import org .lfenergy .compas .sct .commons .scl .ied .IEDAdapter ;
2022import org .lfenergy .compas .sct .commons .scl .ldevice .LDeviceAdapter ;
3436@ RequiredArgsConstructor
3537public class ExtRefEditorService implements ExtRefEditor {
3638 private static final String INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO = "Invalid or missing attributes in ExtRef binding info" ;
39+ private static final String COMPAS_LNODE_STATUS = "COMPAS-LNodeStatus" ;
40+ private static final List <DoNameAndDaName > DO_DA_MAPPINGS = List .of (
41+ new DoNameAndDaName (CHNUM1_DO_NAME , DU_DA_NAME ),
42+ new DoNameAndDaName (LEVMOD_DO_NAME , SETVAL_DA_NAME ),
43+ new DoNameAndDaName (MOD_DO_NAME , STVAL_DA_NAME ),
44+ new DoNameAndDaName (SRCREF_DO_NAME , SETSRCREF_DA_NAME )
45+ );
3746
3847 private final IedService iedService ;
3948 private final LdeviceService ldeviceService ;
4049 private final LnEditor lnEditor ;
41- private final DataTypeTemplatesService dataTypeTemplatesService ;
50+
51+ @ Getter
52+ private final List <SclReportItem > errorHandler = new ArrayList <>();
4253
4354 /**
4455 * Provides valid IED sources according to EPF configuration.<br/>
@@ -76,30 +87,21 @@ private List<TIED> getIedSources(SclRootAdapter sclRootAdapter, TCompasBay compa
7687 * - The location of ExtRef should be in LDevice (inst=LDEPF) <br/>
7788 * - ExtRef that lacks Bay or ICDHeader Private is not returned <br/>
7889 *
79- * @param sclReportItems List of SclReportItem
8090 * @return list of ExtRef and associated Bay
8191 */
82- private List <ExtRefInfo .ExtRefWithBayReference > getExtRefWithBayReferenceInLDEPF (TDataTypeTemplates dataTypeTemplates , TIED tied , final TLDevice tlDevice , final List <SclReportItem > sclReportItems ) {
83- List <ExtRefInfo .ExtRefWithBayReference > extRefBayReferenceList = new ArrayList <>();
92+ private List <ExtRefInfo .ExtRefWithBayReference > getExtRefWithBayReferenceInLDEPF (TIED tied , final TLDevice tlDevice ) {
8493 String lDevicePath = "SCL/IED[@name=\" " + tied .getName () + "\" ]/AccessPoint/Server/LDevice[@inst=\" " + tlDevice .getInst () + "\" ]" ;
8594 Optional <TCompasBay > tCompasBay = PrivateUtils .extractCompasPrivate (tied , TCompasBay .class );
8695 if (tCompasBay .isEmpty ()) {
87- sclReportItems .add (SclReportItem .error (lDevicePath , "The IED has no Private Bay" ));
96+ errorHandler .add (SclReportItem .error (lDevicePath , "The IED has no Private Bay" ));
8897 if (PrivateUtils .extractCompasPrivate (tied , TCompasICDHeader .class ).isEmpty ()) {
89- sclReportItems .add (SclReportItem .error (lDevicePath , "The IED has no Private compas:ICDHeader" ));
98+ errorHandler .add (SclReportItem .error (lDevicePath , "The IED has no Private compas:ICDHeader" ));
9099 }
91100 return Collections .emptyList ();
92101 }
93-
94- if (dataTypeTemplatesService .isDoModAndDaStValExist (dataTypeTemplates , tlDevice .getLN0 ().getLnType ())) {
95- extRefBayReferenceList .addAll (tlDevice .getLN0 ()
96- .getInputs ()
97- .getExtRef ().stream ()
98- .map (extRef -> new ExtRefInfo .ExtRefWithBayReference (tied .getName (), tCompasBay .get (), extRef )).toList ());
99- } else {
100- sclReportItems .add (SclReportItem .error (lDevicePath , "DO@name=Mod/DA@name=stVal not found in DataTypeTemplate" ));
101- }
102- return extRefBayReferenceList ;
102+ return tlDevice .getLN0 ().getInputs ().getExtRef ().stream ()
103+ .map (extRef -> new ExtRefInfo .ExtRefWithBayReference (tied .getName (), tCompasBay .get (), extRef ))
104+ .toList ();
103105 }
104106
105107 /**
@@ -114,7 +116,7 @@ private static Boolean doesExtRefMatchLDEPFChannel(TExtRef extRef, TChannel tCha
114116 && extRef .getDesc ().startsWith ("DYN_LDEPF_ANALOG CHANNEL " + tChannel .getChannelNum () + "_1_AnalogueValue" )
115117 && extRef .getDesc ().endsWith ("_" + tChannel .getDAName () + "_1" );
116118 Boolean doesExtRefDescMatchDigitalChannel = tChannel .getChannelType ().equals (TChannelType .DIGITAL )
117- && extRef .getDesc ().startsWith ("DYN_LDEPF_DIGITAL CHANNEL " + tChannel .getChannelNum () + "_1_BOOLEEN " )
119+ && extRef .getDesc ().startsWith ("DYN_LDEPF_DIGITAL CHANNEL " + tChannel .getChannelNum () + "_1_BOOLEAN " )
118120 && extRef .getDesc ().endsWith ("_" + tChannel .getDAName () + "_1" );
119121 return extRef .isSetDesc () && (doesExtRefDescMatchAnalogChannel || doesExtRefDescMatchDigitalChannel )
120122 && extRef .isSetPLN () && Utils .lnClassEquals (extRef .getPLN (), tChannel .getLNClass ())
@@ -263,29 +265,30 @@ public TExtRef updateExtRefSource(SCL scd, ExtRefInfo extRefInfo) throws ScdExce
263265
264266 @ Override
265267 public List <SclReportItem > manageBindingForLDEPF (SCL scd , EPF epf ) {
266- List < SclReportItem > sclReportItems = new ArrayList <> ();
268+ errorHandler . clear ();
267269 SclRootAdapter sclRootAdapter = new SclRootAdapter (scd );
268- if (!epf .isSetChannels ()) return sclReportItems ;
270+ if (!epf .isSetChannels ()) return errorHandler ;
269271 iedService .getFilteredIeds (scd , ied -> !ied .getName ().contains ("TEST" ))
270- .forEach (tied -> ldeviceService .findLdevice (tied , LDEVICE_LDEPF )
271- .ifPresent (tlDevice -> getExtRefWithBayReferenceInLDEPF (scd .getDataTypeTemplates (), tied , tlDevice , sclReportItems )
272+ .forEach (tied -> ldeviceService .findLdevice (tied , tlDevice -> tlDevice .getInst ().equals (LDEVICE_LDEPF ))
273+ .filter (ldepfLdevice -> PrivateUtils .extractStringPrivate (ldepfLdevice .getLN0 (), COMPAS_LNODE_STATUS ).map (status -> !status .equals ("off" )).orElse (false ))
274+ .ifPresent (ldepfLdevice -> getExtRefWithBayReferenceInLDEPF (tied , ldepfLdevice )
272275 .forEach (extRefBayRef -> epf .getChannels ().getChannel ().stream ().filter (tChannel -> doesExtRefMatchLDEPFChannel (extRefBayRef .extRef (), tChannel ))
273276 .findFirst ().ifPresent (channel -> {
274277 List <TIED > iedSources = getIedSources (sclRootAdapter , extRefBayRef .compasBay (), channel );
275278 if (iedSources .size () == 1 ) {
276- updateLDEPFExtRefBinding (extRefBayRef . extRef () , iedSources .getFirst (), channel );
277- LDeviceAdapter lDeviceAdapter = new LDeviceAdapter (new IEDAdapter (sclRootAdapter , tied .getName ()), tlDevice );
278- sclReportItems . addAll ( updateLDEPFDos (lDeviceAdapter , extRefBayRef .extRef (), channel ) );
279+ updateLDEPFExtRefBinding (extRefBayRef , iedSources .getFirst (), channel );
280+ LDeviceAdapter lDeviceAdapter = new LDeviceAdapter (new IEDAdapter (sclRootAdapter , tied .getName ()), ldepfLdevice );
281+ updateLDEPFDos (lDeviceAdapter , extRefBayRef .extRef (), channel );
279282 } else {
280283 if (iedSources .size () > 1 ) {
281- sclReportItems .add (SclReportItem .warning (null , "There is more than one IED source to bind the signal " +
284+ errorHandler .add (SclReportItem .warning (null , "There is more than one IED source to bind the signal " +
282285 "/IED@name=" + extRefBayRef .iedName () + "/LDevice@inst=LDEPF/LN0" +
283286 "/ExtRef@desc=" + extRefBayRef .extRef ().getDesc ()));
284287 }
285288 // If the source IED is not found, there will be no update or report message.
286289 }
287290 }))));
288- return sclReportItems ;
291+ return errorHandler ;
289292 }
290293
291294 @ Override
@@ -320,56 +323,65 @@ public void epfPostProcessing(SCL scd) {
320323 })));
321324 }
322325
323- private void updateLDEPFExtRefBinding (TExtRef extRef , TIED iedSource , TChannel setting ) {
324- extRef .setIedName (iedSource .getName ());
325- extRef .setLdInst (setting .getLDInst ());
326- extRef .getLnClass ().add (setting .getLNClass ());
327- extRef .setLnInst (setting .getLNInst ());
326+ private void updateLDEPFExtRefBinding (ExtRefInfo .ExtRefWithBayReference extRefWithBay , TIED iedSource , TChannel setting ) {
327+ TExtRef tExtRef = extRefWithBay .extRef ();
328+ tExtRef .setIedName (iedSource .getName ());
329+ tExtRef .setLdInst (setting .getLDInst ());
330+ tExtRef .getLnClass ().add (setting .getLNClass ());
331+ tExtRef .setLnInst (setting .getLNInst ());
328332 if (!isBlank (setting .getLNPrefix ())) {
329- extRef .setPrefix (setting .getLNPrefix ());
333+ tExtRef .setPrefix (setting .getLNPrefix ());
330334 }
331335 String doName = isBlank (setting .getDOInst ()) || setting .getDOInst ().equals ("0" ) ? setting .getDOName () : setting .getDOName () + setting .getDOInst ();
332- extRef .setDoName (doName );
336+ tExtRef .setDoName (doName );
337+ // This is true for External Binding
338+ if (!extRefWithBay .iedName ().equals (iedSource .getName ())) {
339+ tExtRef .setServiceType (
340+ switch (setting .getChannelType ()) {
341+ case DIGITAL -> TServiceType .GOOSE ;
342+ case ANALOG -> TServiceType .SMV ;
343+ });
344+ }
333345 }
334346
335- private List <SclReportItem > updateLDEPFDos (LDeviceAdapter lDeviceAdapter , TExtRef extRef , TChannel setting ) {
336- List <SclReportItem > sclReportItems = new ArrayList <>();
337- List <DoNameAndDaName > doNameAndDaNameList = List .of (
338- new DoNameAndDaName (CHNUM1_DO_NAME , DU_DA_NAME ),
339- new DoNameAndDaName (LEVMOD_DO_NAME , SETVAL_DA_NAME ),
340- new DoNameAndDaName (MOD_DO_NAME , STVAL_DA_NAME ),
341- new DoNameAndDaName (SRCREF_DO_NAME , SETSRCREF_DA_NAME )
342- );
347+ private void updateLDEPFDos (LDeviceAdapter lDeviceAdapter , TExtRef extRef , TChannel setting ) {
343348 if (setting .getChannelType ().equals (TChannelType .DIGITAL )) {
344349 //digital
345350 lDeviceAdapter .findLnAdapter (LN_RBDR , setting .getChannelNum (), null )
346- .ifPresent (lnAdapter -> doNameAndDaNameList .forEach (doNameAndDaName -> updateVal (lnAdapter , doNameAndDaName . doName , doNameAndDaName . daName , extRef , setting ). ifPresent ( sclReportItems :: add )));
351+ .ifPresent (lnAdapter -> DO_DA_MAPPINGS .forEach (doNameAndDaName -> updateVal (lnAdapter , doNameAndDaName , extRef , setting )));
347352 lDeviceAdapter .findLnAdapter (LN_RBDR , setting .getChannelNum (), LN_PREFIX_B )
348- .ifPresent (lnAdapter -> doNameAndDaNameList .forEach (doNameAndDaName -> updateVal (lnAdapter , doNameAndDaName . doName , doNameAndDaName . daName , extRef , setting ). ifPresent ( sclReportItems :: add )));
353+ .ifPresent (lnAdapter -> DO_DA_MAPPINGS .forEach (doNameAndDaName -> updateVal (lnAdapter , doNameAndDaName , extRef , setting )));
349354 }
350355 if (setting .getChannelType ().equals (TChannelType .ANALOG )) {
351356 //analog
352357 lDeviceAdapter .findLnAdapter (LN_RADR , setting .getChannelNum (), null )
353- .ifPresent (lnAdapter -> doNameAndDaNameList .forEach (doNameAndDaName -> updateVal (lnAdapter , doNameAndDaName . doName , doNameAndDaName . daName , extRef , setting ). ifPresent ( sclReportItems :: add )));
358+ .ifPresent (lnAdapter -> DO_DA_MAPPINGS .forEach (doNameAndDaName -> updateVal (lnAdapter , doNameAndDaName , extRef , setting )));
354359 lDeviceAdapter .findLnAdapter (LN_RADR , setting .getChannelNum (), LN_PREFIX_A )
355- .ifPresent (lnAdapter -> doNameAndDaNameList .forEach (doNameAndDaName -> updateVal (lnAdapter , doNameAndDaName . doName , doNameAndDaName . daName , extRef , setting ). ifPresent ( sclReportItems :: add )));
360+ .ifPresent (lnAdapter -> DO_DA_MAPPINGS .forEach (doNameAndDaName -> updateVal (lnAdapter , doNameAndDaName , extRef , setting )));
356361 }
357- return sclReportItems ;
358362 }
359363
360- private Optional <SclReportItem > updateVal (AbstractLNAdapter <?> lnAdapter , String doName , String daName , TExtRef extRef , TChannel setting ) {
361- String value = switch (daName ) {
362- case DU_DA_NAME -> setting .getChannelShortLabel ();
363- case SETVAL_DA_NAME -> LN_PREFIX_B .equals (lnAdapter .getPrefix ()) || LN_PREFIX_A .equals (lnAdapter .getPrefix ()) ? setting .getChannelLevModQ ().value () : setting .getChannelLevMod ().value ();
364- case STVAL_DA_NAME -> ActiveStatus .ON .getValue ();
365- case SETSRCREF_DA_NAME -> computeDaiValue (lnAdapter , extRef , setting .getDAName ());
366- default -> null ;
364+ private void updateVal (AbstractLNAdapter <?> lnAdapter , DoNameAndDaName doDaName , TExtRef extRef , TChannel setting ) {
365+ String lnPrefix = lnAdapter .getPrefix ();
366+ Optional <SclReportItem > sclReportItem = switch (doDaName .daName ) {
367+ case DU_DA_NAME -> setting .isSetChannelShortLabel () ? lnAdapter .getDOIAdapterByName (doDaName .doName ).updateDAI (doDaName .daName , setting .getChannelShortLabel ()) :
368+ Optional .empty ();
369+ case SETVAL_DA_NAME -> {
370+ if (LN_PREFIX_B .equals (lnPrefix ) || LN_PREFIX_A .equals (lnPrefix )) {
371+ yield setting .isSetChannelLevModQ () && !setting .getChannelLevModQ ().equals (TChannelLevMod .NA ) ? lnAdapter .getDOIAdapterByName (doDaName .doName ).updateDAI (doDaName .daName , setting .getChannelLevModQ ().value ()) : Optional .empty ();
372+ } else {
373+ yield setting .isSetChannelLevMod () && !setting .getChannelLevMod ().equals (TChannelLevMod .NA ) ? lnAdapter .getDOIAdapterByName (doDaName .doName ).updateDAI (doDaName .daName , setting .getChannelLevMod ().value ()) : Optional .empty ();
374+ }
375+ }
376+ case STVAL_DA_NAME -> lnAdapter .getDOIAdapterByName (doDaName .doName ).updateDAI (doDaName .daName , ActiveStatus .ON .getValue ());
377+ case SETSRCREF_DA_NAME -> lnAdapter .getDOIAdapterByName (doDaName .doName ).updateDAI (doDaName .daName , computeDaiValue (lnPrefix , extRef , setting .getDAName ()));
378+ default -> throw new IllegalStateException ("Unexpected value: " + doDaName .daName );
367379 };
368- return lnAdapter . getDOIAdapterByName ( doName ). updateDAI ( daName , value );
380+ sclReportItem . ifPresent ( errorHandler :: add );
369381 }
370382
371- private String computeDaiValue (AbstractLNAdapter <?> lnAdapter , TExtRef extRef , String daName ) {
372- if (LN_PREFIX_B .equals (lnAdapter . getPrefix ()) || LN_PREFIX_A .equals (lnAdapter . getPrefix () )) {
383+ private String computeDaiValue (String lnPrefix , TExtRef extRef , String daName ) {
384+ if (LN_PREFIX_B .equals (lnPrefix ) || LN_PREFIX_A .equals (lnPrefix )) {
373385 return extRef .getIedName () +
374386 extRef .getLdInst () + "/" +
375387 trimToEmpty (extRef .getPrefix ()) +
0 commit comments