Skip to content

Commit aa960c2

Browse files
committed
refactor: LDEPF service - simplify structure by removing Adapter class, closes #505, RSR-1244
Signed-off-by: Samir Romdhani <[email protected]>
1 parent cb36862 commit aa960c2

File tree

5 files changed

+172
-113
lines changed

5 files changed

+172
-113
lines changed

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefEditorService.java

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

77
import lombok.Getter;
88
import lombok.RequiredArgsConstructor;
9+
import lombok.extern.slf4j.Slf4j;
910
import org.lfenergy.compas.scl2007b4.model.*;
1011
import org.lfenergy.compas.sct.commons.api.ExtRefEditor;
1112
import org.lfenergy.compas.sct.commons.api.LnEditor;
@@ -21,6 +22,7 @@
2122
import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter;
2223
import org.lfenergy.compas.sct.commons.scl.ldevice.LDeviceAdapter;
2324
import org.lfenergy.compas.sct.commons.scl.ln.AbstractLNAdapter;
25+
import org.lfenergy.compas.sct.commons.scl.ln.LnId;
2426
import org.lfenergy.compas.sct.commons.util.ActiveStatus;
2527
import org.lfenergy.compas.sct.commons.util.PrivateUtils;
2628
import org.lfenergy.compas.sct.commons.util.Utils;
@@ -33,6 +35,7 @@
3335
import static org.apache.commons.lang3.StringUtils.*;
3436
import static org.lfenergy.compas.sct.commons.util.CommonConstants.*;
3537

38+
@Slf4j
3639
@RequiredArgsConstructor
3740
public class ExtRefEditorService implements ExtRefEditor {
3841
private static final String INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO = "Invalid or missing attributes in ExtRef binding info";
@@ -47,6 +50,7 @@ public class ExtRefEditorService implements ExtRefEditor {
4750
private final IedService iedService;
4851
private final LdeviceService ldeviceService;
4952
private final LnEditor lnEditor;
53+
private final DataTypeTemplatesService dataTypeTemplatesService;
5054

5155
@Getter
5256
private final List<SclReportItem> errorHandler = new ArrayList<>();
@@ -60,24 +64,27 @@ public class ExtRefEditorService implements ExtRefEditor {
6064
* 4. Active LNode source object that should match the provided parameters<br/>
6165
* 5. Valid DataTypeTemplate Object hierarchy that should match the DO/DA/BDA parameters<br/>
6266
*
63-
* @param sclRootAdapter SCL scl object
67+
* @param scl SCL object
6468
* @param compasBay TCompasBay represent Bay Private
6569
* @param channel TChannel represent parameters
6670
* @return the IED sources matching the LDEPF parameters
6771
*/
68-
private List<TIED> getIedSources(SclRootAdapter sclRootAdapter, TCompasBay compasBay, TChannel channel) {
69-
return sclRootAdapter.streamIEDAdapters()
70-
.filter(iedAdapter -> (channel.getBayScope().equals(TCBScopeType.BAY_EXTERNAL)
71-
&& iedAdapter.getPrivateCompasBay().stream().noneMatch(bay -> bay.getUUID().equals(compasBay.getUUID())))
72-
|| (channel.getBayScope().equals(TCBScopeType.BAY_INTERNAL)
73-
&& iedAdapter.getPrivateCompasBay().stream().anyMatch(bay -> bay.getUUID().equals(compasBay.getUUID()))))
74-
.filter(iedAdapter -> doesIcdHeaderMatchLDEPFChannel(iedAdapter, channel))
75-
.filter(iedAdapter -> getActiveSourceLDeviceByLDEPFChannel(iedAdapter, channel)
76-
.map(lDeviceAdapter -> getActiveLNSourceByLDEPFChannel(lDeviceAdapter, channel)
77-
.map(lnAdapter -> isValidDataTypeTemplate(lnAdapter, channel))
72+
private List<TIED> getIedSources(SCL scl, TCompasBay compasBay, TChannel channel) {
73+
return scl.getIED()
74+
.stream()
75+
.filter(tied -> {
76+
Optional<TCompasBay> tCompasBay = PrivateUtils.extractCompasPrivate(tied, TCompasBay.class);
77+
return (channel.getBayScope().equals(TCBScopeType.BAY_EXTERNAL)
78+
&& tCompasBay.stream().noneMatch(bay -> bay.getUUID().equals(compasBay.getUUID())))
79+
|| (channel.getBayScope().equals(TCBScopeType.BAY_INTERNAL)
80+
&& tCompasBay.stream().anyMatch(bay -> bay.getUUID().equals(compasBay.getUUID())));
81+
}).filter(tied -> doesIcdHeaderMatchLDEPFChannel(tied, channel))
82+
.filter(tied -> ldeviceService.findLdevice(tied, channel.getLDInst())
83+
.filter(tlDevice -> ldeviceService.getLdeviceStatus(tlDevice).map(ActiveStatus.ON::equals).orElse(false))
84+
.map(tlDevice -> getActiveLNSourceByLDEPFChannel(tlDevice, channel)
85+
.map(tAnyLN -> isValidDataTypeTemplate(scl.getDataTypeTemplates(), tAnyLN, channel))
7886
.orElse(false))
7987
.orElse(false))
80-
.map(IEDAdapter::getCurrentElem)
8188
.limit(2)
8289
.toList();
8390
}
@@ -126,83 +133,58 @@ private static Boolean doesExtRefMatchLDEPFChannel(TExtRef extRef, TChannel tCha
126133
/**
127134
* Verify whether the IED satisfies the EPF channel for the private element `TCompasICDHeader`
128135
*
129-
* @param iedAdapter IEDAdapter
136+
* @param tied TIED
130137
* @param channel TChannel
131138
* @return true if the TCompasICDHeader matches the EPF channel
132139
*/
133-
private static boolean doesIcdHeaderMatchLDEPFChannel(IEDAdapter iedAdapter, TChannel channel) {
134-
return iedAdapter.getCompasICDHeader()
135-
.map(compasICDHeader -> compasICDHeader.getIEDType().value().equals(channel.getIEDType())
140+
private static boolean doesIcdHeaderMatchLDEPFChannel(TIED tied, TChannel channel) {
141+
Optional<TCompasICDHeader> tCompasICDHeader = PrivateUtils.extractCompasPrivate(tied, TCompasICDHeader.class);
142+
return tCompasICDHeader.map(compasICDHeader -> compasICDHeader.getIEDType().value().equals(channel.getIEDType())
136143
&& compasICDHeader.getIEDredundancy().value().equals(channel.getIEDRedundancy().value())
137144
&& compasICDHeader.getIEDSystemVersioninstance().toString().equals(channel.getIEDSystemVersionInstance()))
138145
.orElse(false);
139146
}
140147

141-
/**
142-
* Provides Active LDevice according to EPF channel's inst attribute
143-
*
144-
* @param iedAdapter IEDAdapter
145-
* @param channel TChannel
146-
* @return LDeviceAdapter object that matches the EPF channel
147-
*/
148-
private Optional<LDeviceAdapter> getActiveSourceLDeviceByLDEPFChannel(IEDAdapter iedAdapter, TChannel channel) {
149-
return ldeviceService.findLdevice(iedAdapter.getCurrentElem(), channel.getLDInst())
150-
.filter(tlDevice -> ldeviceService.getLdeviceStatus(tlDevice).map(ActiveStatus.ON::equals).orElse(false))
151-
.map(tlDevice -> new LDeviceAdapter(iedAdapter, tlDevice));
152-
}
153-
154148
/**
155149
* Provides Active LN Object that satisfies the EPF channel attributes (lnClass, lnInst, prefix)
156150
*
157-
* @param lDeviceAdapter LDeviceAdapter
151+
* @param tlDevice TLDevice
158152
* @param channel TChannel
159153
* @return AbstractLNAdapter object that matches the EPF channel
160154
*/
161-
private static Optional<AbstractLNAdapter<?>> getActiveLNSourceByLDEPFChannel(LDeviceAdapter lDeviceAdapter, TChannel channel) {
162-
return lDeviceAdapter.getLNAdaptersIncludingLN0()
163-
.stream()
164-
.filter(lnAdapter -> lnAdapter.getLNClass().equals(channel.getLNClass())
165-
&& lnAdapter.getLNInst().equals(channel.getLNInst())
166-
&& trimToEmpty(channel.getLNPrefix()).equals(trimToEmpty(lnAdapter.getPrefix())))
155+
private Optional<TAnyLN> getActiveLNSourceByLDEPFChannel(TLDevice tlDevice, TChannel channel) {
156+
return lnEditor.getAnylns(tlDevice)
157+
.filter(tAnyLN -> lnEditor.matchesLn(tAnyLN, channel.getLNClass(), channel.getLNInst(), channel.getLNPrefix()))
167158
.findFirst()
168-
.filter(lnAdapter -> lnAdapter.getDaiModStValValue()
169-
.map(status -> status.equals(ActiveStatus.ON.getValue()))
170-
.orElse(true));
159+
.filter(tAnyLN -> lnEditor.getDaiModStValValue(tAnyLN).map(ActiveStatus.ON::equals).orElse(true));
171160
}
172161

173162
/**
174163
* Verify whether the LN satisfies the EPF channel parameters for Data Type Template elements.
175164
*
176-
* @param lnAdapter AbstractLNAdapter
165+
* @param dtt TDataTypeTemplates
166+
* @param tAnyLN TAnyLN
177167
* @param channel TChannel
178168
* @return true if the LN matches the EPF channel
179169
*/
180-
private static boolean isValidDataTypeTemplate(AbstractLNAdapter<?> lnAdapter, TChannel channel) {
170+
private boolean isValidDataTypeTemplate(TDataTypeTemplates dtt, TAnyLN tAnyLN, TChannel channel) {
181171
if (isBlank(channel.getDOName())) {
182172
return true;
183173
}
184174
String doName = isBlank(channel.getDOInst()) || channel.getDOInst().equals("0") ? channel.getDOName() : channel.getDOName() + channel.getDOInst();
185-
DoTypeName doTypeName = new DoTypeName(doName);
175+
String daName = channel.getDAName();
176+
List<String> sdoNames = new ArrayList<>();
177+
List<String> bdaNames = new ArrayList<>();
186178
if (isNotBlank(channel.getSDOName())) {
187-
doTypeName.getStructNames().add(channel.getSDOName());
179+
sdoNames.add(channel.getSDOName());
188180
}
189-
DaTypeName daTypeName = new DaTypeName(channel.getDAName());
190181
if (isNotBlank(channel.getBDAName())) {
191-
daTypeName.setBType(TPredefinedBasicTypeEnum.STRUCT);
192-
daTypeName.getStructNames().add(channel.getBDAName());
182+
bdaNames.add(channel.getBDAName());
193183
}
194184
if (isNotBlank(channel.getSBDAName())) {
195-
daTypeName.getStructNames().add(channel.getSBDAName());
185+
bdaNames.add(channel.getSBDAName());
196186
}
197-
return lnAdapter.getDataTypeTemplateAdapter().getLNodeTypeAdapterById(lnAdapter.getLnType())
198-
.filter(lNodeTypeAdapter -> {
199-
try {
200-
lNodeTypeAdapter.checkDoAndDaTypeName(doTypeName, daTypeName);
201-
} catch (ScdException ex) {
202-
return false;
203-
}
204-
return true;
205-
}).isPresent();
187+
return dataTypeTemplatesService.findDoLinkedToDa(dtt, tAnyLN.getLnType(), new DoLinkedToDaFilter(doName, sdoNames, daName, bdaNames)).isPresent();
206188
}
207189

208190
@Override
@@ -266,19 +248,18 @@ public TExtRef updateExtRefSource(SCL scd, ExtRefInfo extRefInfo) throws ScdExce
266248
@Override
267249
public List<SclReportItem> manageBindingForLDEPF(SCL scd, EPF epf) {
268250
errorHandler.clear();
269-
SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
270251
if (!epf.isSetChannels()) return errorHandler;
252+
log.info("Processing %d EPF setting channels".formatted(epf.getChannels().getChannel().size()));
271253
iedService.getFilteredIeds(scd, ied -> !ied.getName().contains("TEST"))
272254
.forEach(tied -> ldeviceService.findLdevice(tied, tlDevice -> tlDevice.getInst().equals(LDEVICE_LDEPF))
273255
.filter(ldepfLdevice -> PrivateUtils.extractStringPrivate(ldepfLdevice.getLN0(), COMPAS_LNODE_STATUS).map(status -> !status.equals("off")).orElse(false))
274256
.ifPresent(ldepfLdevice -> getExtRefWithBayReferenceInLDEPF(tied, ldepfLdevice)
275257
.forEach(extRefBayRef -> epf.getChannels().getChannel().stream().filter(tChannel -> doesExtRefMatchLDEPFChannel(extRefBayRef.extRef(), tChannel))
276258
.findFirst().ifPresent(channel -> {
277-
List<TIED> iedSources = getIedSources(sclRootAdapter, extRefBayRef.compasBay(), channel);
259+
List<TIED> iedSources = getIedSources(scd, extRefBayRef.compasBay(), channel);
278260
if (iedSources.size() == 1) {
279261
updateLDEPFExtRefBinding(extRefBayRef, iedSources.getFirst(), channel);
280-
LDeviceAdapter lDeviceAdapter = new LDeviceAdapter(new IEDAdapter(sclRootAdapter, tied.getName()), ldepfLdevice);
281-
updateLDEPFDos(lDeviceAdapter, extRefBayRef.extRef(), channel);
262+
updateLDEPFDos(scd.getDataTypeTemplates(), tied, ldepfLdevice, extRefBayRef.extRef(), channel);
282263
} else {
283264
if (iedSources.size() > 1) {
284265
errorHandler.add(SclReportItem.warning(null, "There is more than one IED source to bind the signal " +
@@ -344,42 +325,6 @@ private void updateLDEPFExtRefBinding(ExtRefInfo.ExtRefWithBayReference extRefWi
344325
}
345326
}
346327

347-
private void updateLDEPFDos(LDeviceAdapter lDeviceAdapter, TExtRef extRef, TChannel setting) {
348-
if (setting.getChannelType().equals(TChannelType.DIGITAL)) {
349-
//digital
350-
lDeviceAdapter.findLnAdapter(LN_RBDR, setting.getChannelNum(), null)
351-
.ifPresent(lnAdapter -> DO_DA_MAPPINGS.forEach(doNameAndDaName -> updateVal(lnAdapter, doNameAndDaName, extRef, setting)));
352-
lDeviceAdapter.findLnAdapter(LN_RBDR, setting.getChannelNum(), LN_PREFIX_B)
353-
.ifPresent(lnAdapter -> DO_DA_MAPPINGS.forEach(doNameAndDaName -> updateVal(lnAdapter, doNameAndDaName, extRef, setting)));
354-
}
355-
if (setting.getChannelType().equals(TChannelType.ANALOG)) {
356-
//analog
357-
lDeviceAdapter.findLnAdapter(LN_RADR, setting.getChannelNum(), null)
358-
.ifPresent(lnAdapter -> DO_DA_MAPPINGS.forEach(doNameAndDaName -> updateVal(lnAdapter, doNameAndDaName, extRef, setting)));
359-
lDeviceAdapter.findLnAdapter(LN_RADR, setting.getChannelNum(), LN_PREFIX_A)
360-
.ifPresent(lnAdapter -> DO_DA_MAPPINGS.forEach(doNameAndDaName -> updateVal(lnAdapter, doNameAndDaName, extRef, setting)));
361-
}
362-
}
363-
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);
379-
};
380-
sclReportItem.ifPresent(errorHandler::add);
381-
}
382-
383328
private String computeDaiValue(String lnPrefix, TExtRef extRef, String daName) {
384329
if (LN_PREFIX_B.equals(lnPrefix) || LN_PREFIX_A.equals(lnPrefix)) {
385330
return extRef.getIedName() +
@@ -399,6 +344,63 @@ private String computeDaiValue(String lnPrefix, TExtRef extRef, String daName) {
399344
}
400345
}
401346

347+
private void updateLDEPFDos(TDataTypeTemplates dtt, TIED tied, TLDevice tlDevice, TExtRef tExtRef, TChannel setting) {
348+
// Digital
349+
if (setting.getChannelType().equals(TChannelType.DIGITAL)) {
350+
lnEditor.findLn(tlDevice, tAnyLN -> lnEditor.matchesLn(tAnyLN, LN_RBDR, setting.getChannelNum(), null))
351+
.ifPresent(tln -> updateDaiValue(dtt, tied, tlDevice, tln, tExtRef, setting));
352+
lnEditor.findLn(tlDevice, tAnyLN -> lnEditor.matchesLn(tAnyLN, LN_RBDR, setting.getChannelNum(), LN_PREFIX_B))
353+
.ifPresent(tln -> updateDaiValue(dtt, tied, tlDevice, tln, tExtRef, setting));
354+
}
355+
// Analog
356+
if (setting.getChannelType().equals(TChannelType.ANALOG)) {
357+
lnEditor.findLn(tlDevice, tAnyLN -> lnEditor.matchesLn(tAnyLN, LN_RADR, setting.getChannelNum(), null))
358+
.ifPresent(tln -> updateDaiValue(dtt, tied, tlDevice, tln, tExtRef, setting));
359+
lnEditor.findLn(tlDevice, tAnyLN -> lnEditor.matchesLn(tAnyLN, LN_RADR, setting.getChannelNum(), LN_PREFIX_A))
360+
.ifPresent(tln -> updateDaiValue(dtt, tied, tlDevice, tln, tExtRef, setting));
361+
}
362+
}
363+
364+
private void updateDaiValue(TDataTypeTemplates dtt, TIED tied, TLDevice tlDevice, TAnyLN tln, TExtRef tExtRef, TChannel setting) {
365+
DO_DA_MAPPINGS.forEach(doNameAndDaName -> Optional.ofNullable(getNewDaiValue(doNameAndDaName.daName, LnId.from(tln).prefix(), tExtRef, setting))
366+
.ifPresent(newDaiValue -> updateDaiVal(dtt, tied, tlDevice, tln, DoLinkedToDaFilter.from(doNameAndDaName.doName, doNameAndDaName.daName), newDaiValue)));
367+
}
368+
369+
private String getNewDaiValue(String daName, String lnPrefix, TExtRef extRef, TChannel setting) {
370+
return switch (daName) {
371+
case DU_DA_NAME -> setting.isSetChannelShortLabel() ? setting.getChannelShortLabel(): null;
372+
case SETVAL_DA_NAME -> {
373+
if(LN_PREFIX_B.equals(lnPrefix) || LN_PREFIX_A.equals(lnPrefix)){
374+
yield setting.isSetChannelLevModQ() && !setting.getChannelLevModQ().equals(TChannelLevMod.NA) ? setting.getChannelLevModQ().value(): null;
375+
} else {
376+
yield setting.isSetChannelLevMod() && !setting.getChannelLevMod().equals(TChannelLevMod.NA) ? setting.getChannelLevMod().value(): null;
377+
}
378+
}
379+
case STVAL_DA_NAME -> ActiveStatus.ON.getValue();
380+
case SETSRCREF_DA_NAME -> computeDaiValue(lnPrefix, extRef, setting.getDAName());
381+
default -> throw new IllegalStateException("Unexpected value: " + setting.getDAName());
382+
};
383+
}
384+
385+
private void updateDaiVal(TDataTypeTemplates dtt, TIED tied, TLDevice tlDevice, TAnyLN tln, DoLinkedToDaFilter doLinkedToDaFilter, String newDaiValue) {
386+
dataTypeTemplatesService.getFilteredDoLinkedToDa(dtt, tln.getLnType(), doLinkedToDaFilter)
387+
.map(doLinkedToDa1 -> lnEditor.getDoLinkedToDaCompletedFromDAI(tied, tlDevice.getInst(), tln, doLinkedToDa1))
388+
.findFirst()
389+
.filter(doLinkedToDa1 -> {
390+
if (!doLinkedToDa1.isUpdatable()){
391+
errorHandler.add(SclReportItem.warning(tied.getName() + "/" + LDEVICE_LDSUIED + "/" + LnId.from(tln).lnClass() + "/DOI@name=\"" + doLinkedToDaFilter.doName() + "\"/DAI@name=\"" + doLinkedToDaFilter.daName() + "\"/Val", "The DAI cannot be updated"));
392+
}
393+
return doLinkedToDa1.isUpdatable();
394+
})
395+
.ifPresent(doLinkedToDa1 -> {
396+
TVal tVal = new TVal();
397+
tVal.setValue(newDaiValue);
398+
doLinkedToDa1.dataAttribute().addDaVal(tVal);
399+
lnEditor.updateOrCreateDOAndDAInstances(tln, doLinkedToDa1);
400+
log.info("LDEPF - Update DOI => LN(lnClass=%s, inst=%s, prefix=%s) / DOI(name=%s)/DAI(name=%s) with value=%s".formatted(LnId.from(tln).lnClass(), LnId.from(tln).lnInst(), LnId.from(tln).prefix(), doLinkedToDaFilter.doName(), doLinkedToDaFilter.daName(), newDaiValue));
401+
});
402+
}
403+
402404
private record DoNameAndDaName(String doName, String daName) {
403405
}
404406

0 commit comments

Comments
 (0)