Skip to content

Commit c807c33

Browse files
committed
Merge pull request #463 from com-pas/feat/459-change-lnservicegetdaimodstval
feat(#459): Change LnService.getDaiModStVal
2 parents c503f12 + d018835 commit c807c33

File tree

15 files changed

+254
-179
lines changed

15 files changed

+254
-179
lines changed

sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceIntegrationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class SclAutomationServiceIntegrationTest {
3232
private SclAutomationService sclAutomationService ;
3333
private static final SclEditor sclEditor = new SclService() ;
3434
private static final SubstationEditor substationEditor = new SubstationService(new VoltageLevelService()) ;
35-
private static final ControlBlockEditor controlBlockEditor = new ControlBlockEditorService(new ControlService(), new LdeviceService()) ;
35+
private static final ControlBlockEditor controlBlockEditor = new ControlBlockEditorService(new ControlService(), new LdeviceService(new LnService()));
3636

3737
private HeaderDTO headerDTO;
3838

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public class ExtRefEditorService implements ExtRefEditor {
5454
* @param channel TChannel represent parameters
5555
* @return the IED sources matching the LDEPF parameters
5656
*/
57-
private static List<TIED> getIedSources(SclRootAdapter sclRootAdapter, TCompasBay compasBay, TChannel channel) {
57+
private List<TIED> getIedSources(SclRootAdapter sclRootAdapter, TCompasBay compasBay, TChannel channel) {
5858
return sclRootAdapter.streamIEDAdapters()
5959
.filter(iedAdapter -> (channel.getBayScope().equals(TCBScopeType.BAY_EXTERNAL)
6060
&& iedAdapter.getPrivateCompasBay().stream().noneMatch(bay -> bay.getUUID().equals(compasBay.getUUID())))
@@ -143,8 +143,7 @@ private static boolean doesIcdHeaderMatchLDEPFChannel(IEDAdapter iedAdapter, TCh
143143
* @param channel TChannel
144144
* @return LDeviceAdapter object that matches the EPF channel
145145
*/
146-
private static Optional<LDeviceAdapter> getActiveSourceLDeviceByLDEPFChannel(IEDAdapter iedAdapter, TChannel channel) {
147-
LdeviceService ldeviceService = new LdeviceService();
146+
private Optional<LDeviceAdapter> getActiveSourceLDeviceByLDEPFChannel(IEDAdapter iedAdapter, TChannel channel) {
148147
return ldeviceService.findLdevice(iedAdapter.getCurrentElem(), tlDevice -> tlDevice.getInst().equals(channel.getLDInst()))
149148
.filter(tlDevice -> ldeviceService.getLdeviceStatus(tlDevice).map(ActiveStatus.ON::equals).orElse(false))
150149
.map(tlDevice -> new LDeviceAdapter(iedAdapter, tlDevice));

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,23 @@
44

55
package org.lfenergy.compas.sct.commons;
66

7-
import org.lfenergy.compas.scl2007b4.model.*;
7+
import lombok.RequiredArgsConstructor;
8+
import org.lfenergy.compas.scl2007b4.model.TAccessPoint;
9+
import org.lfenergy.compas.scl2007b4.model.TIED;
10+
import org.lfenergy.compas.scl2007b4.model.TLDevice;
11+
import org.lfenergy.compas.scl2007b4.model.TServer;
812
import org.lfenergy.compas.sct.commons.util.ActiveStatus;
913

1014
import java.util.Objects;
1115
import java.util.Optional;
1216
import java.util.function.Predicate;
1317
import java.util.stream.Stream;
1418

19+
@RequiredArgsConstructor
1520
public class LdeviceService {
1621

22+
private final LnService lnService;
23+
1724
public Stream<TLDevice> getLdevices(TIED tied) {
1825
if (!tied.isSetAccessPoint()) {
1926
return Stream.empty();
@@ -40,7 +47,6 @@ public Optional<TLDevice> findLdevice(TIED tied, Predicate<TLDevice> ldevicePred
4047
}
4148

4249
public Optional<ActiveStatus> getLdeviceStatus(TLDevice tlDevice) {
43-
LnService lnService = new LnService();
44-
return lnService.getDaiModStval(tlDevice.getLN0());
50+
return lnService.getDaiModStValValue(tlDevice.getLN0());
4551
}
4652
}

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

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import org.lfenergy.compas.sct.commons.util.ActiveStatus;
1313

1414
import java.util.ArrayList;
15-
import java.util.Collection;
1615
import java.util.List;
1716
import java.util.Optional;
1817
import java.util.function.Predicate;
@@ -25,6 +24,8 @@
2524
@Slf4j
2625
public class LnService implements LnEditor {
2726

27+
private static final DoLinkedToDaFilter DAI_FILTER_MOD_STVAL = DoLinkedToDaFilter.from(MOD_DO_NAME, STVAL_DA_NAME);
28+
2829
public Stream<TAnyLN> getAnylns(TLDevice tlDevice) {
2930
return Stream.concat(Stream.of(tlDevice.getLN0()), tlDevice.getLN().stream());
3031
}
@@ -60,33 +61,29 @@ public Optional<TLN> findLn(TLDevice tlDevice, Predicate<TLN> lnPredicate) {
6061
* @return the Lnode Status
6162
*/
6263
public ActiveStatus getLnStatus(TAnyLN tAnyLN, LN0 ln0) {
63-
Optional<ActiveStatus> ln0Status = getDaiModStval(ln0);
64-
return getDaiModStval(tAnyLN).filter(ActiveStatus.OFF::equals).orElseGet(() -> ln0Status.orElse(ActiveStatus.OFF));
64+
Optional<ActiveStatus> ln0Status = getDaiModStValValue(ln0);
65+
return getDaiModStValValue(tAnyLN).filter(ActiveStatus.OFF::equals).orElseGet(() -> ln0Status.orElse(ActiveStatus.OFF));
6566
}
6667

67-
public Optional<ActiveStatus> getDaiModStval(TAnyLN tAnyLN) {
68-
return tAnyLN
69-
.getDOI()
68+
public Optional<ActiveStatus> getDaiModStValValue(TAnyLN tAnyLN) {
69+
return getDaiModStVal(tAnyLN)
7070
.stream()
71-
.filter(tdoi -> MOD_DO_NAME.equals(tdoi.getName()))
71+
.flatMap(tdai -> tdai.getVal().stream())
72+
.map(TVal::getValue)
7273
.findFirst()
73-
.flatMap(tdoi -> tdoi.getSDIOrDAI()
74-
.stream()
75-
.filter(dai -> dai.getClass().equals(TDAI.class))
76-
.map(TDAI.class::cast)
77-
.filter(tdai -> STVAL_DA_NAME.equals(tdai.getName()))
78-
.map(TDAI::getVal)
79-
.flatMap(Collection::stream)
80-
.findFirst()
81-
.map(TVal::getValue))
8274
.map(ActiveStatus::fromValue);
8375
}
76+
77+
public Optional<TDAI> getDaiModStVal(TAnyLN tAnyLN) {
78+
return getDOAndDAInstances(tAnyLN, DAI_FILTER_MOD_STVAL);
79+
}
80+
8481
public Stream<TAnyLN> getActiveLns(TLDevice tlDevice) {
8582
LN0 ln0 = tlDevice.getLN0();
8683
Stream<TLN> tlnStream = tlDevice.getLN()
8784
.stream()
8885
.filter(tln -> ActiveStatus.ON.equals(getLnStatus(tln, ln0)));
89-
Stream<LN0> ln0Stream = Stream.of(ln0).filter(ln02 -> getDaiModStval(ln02).map(ActiveStatus.ON::equals).orElse(false));
86+
Stream<LN0> ln0Stream = Stream.of(ln0).filter(ln02 -> getDaiModStValValue(ln02).map(ActiveStatus.ON::equals).orElse(false));
9087
return Stream.concat(ln0Stream, tlnStream);
9188
}
9289

@@ -99,7 +96,7 @@ public Optional<TDAI> getDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDaFilter doLi
9996
return tAnyLN.getDOI().stream().filter(doi -> doi.getName().equals(doLinkedToDaFilter.doName()))
10097
.findFirst()
10198
.flatMap(doi -> {
102-
if(structNamesList.size() > 1) {
99+
if (structNamesList.size() > 1) {
103100
String firstSDIName = structNamesList.removeFirst();
104101
return this.getSdiByName(doi, firstSDIName)
105102
.map(intermediateSdi -> findSDIByStructName(intermediateSdi, structNamesList))
@@ -116,7 +113,7 @@ public Optional<TDAI> getDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDaFilter doLi
116113
return Optional.empty();
117114
})
118115
.stream().findFirst();
119-
} else if(structNamesList.size() == 1){
116+
} else if (structNamesList.size() == 1) {
120117
return doi.getSDIOrDAI().stream()
121118
.filter(unNaming -> unNaming.getClass().equals(TDAI.class))
122119
.map(TDAI.class::cast)
@@ -138,7 +135,7 @@ public void updateOrCreateDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDa doLinkedT
138135
.ifPresentOrElse(tVal -> tVal.setValue(value),
139136
() -> tdai.getVal().add(newVal(value)));
140137
} else {
141-
for (DaVal daVal: daiVals) {
138+
for (DaVal daVal : daiVals) {
142139
tdai.getVal().stream()
143140
.filter(tValElem -> tValElem.isSetSGroup() && tValElem.getSGroup() == daVal.settingGroup())
144141
.findFirst()
@@ -198,22 +195,22 @@ private Optional<TDAI> createDoiSdiDaiChainIfNotExists(TAnyLN tAnyLN, DataObject
198195

199196
TDOI doi = tAnyLN.getDOI().stream().filter(doi1 -> doi1.getName().equals(dataObject.getDoName()))
200197
.findFirst()
201-
.orElseGet(()-> {
198+
.orElseGet(() -> {
202199
TDOI newDOI = new TDOI();
203200
newDOI.setName(dataObject.getDoName());
204201
tAnyLN.getDOI().add(newDOI);
205202
return newDOI;
206203
});
207-
if(structInstances.size() > 1){
204+
if (structInstances.size() > 1) {
208205
TSDI firstSDI = findOrCreateSDIFromDOI(doi, structInstances.getFirst());
209206
TSDI lastSDI = findOrCreateSDIByStructName(firstSDI, structInstances);
210-
if(structInstances.size() == 1){
207+
if (structInstances.size() == 1) {
211208
return lastSDI.getSDIOrDAI().stream()
212209
.filter(tUnNaming -> tUnNaming.getClass().equals(TDAI.class))
213210
.map(TDAI.class::cast)
214211
.filter(tdai -> tdai.getName().equals(structInstances.getFirst()))
215212
.map(tdai -> {
216-
if(tdai.isSetValImport()) {
213+
if (tdai.isSetValImport()) {
217214
tdai.setValImport(dataAttribute.isValImport());
218215
}
219216
return tdai;
@@ -226,13 +223,13 @@ private Optional<TDAI> createDoiSdiDaiChainIfNotExists(TAnyLN tAnyLN, DataObject
226223
return Optional.of(newDAI);
227224
});
228225
}
229-
} else if(structInstances.size() == 1){
226+
} else if (structInstances.size() == 1) {
230227
return doi.getSDIOrDAI().stream()
231228
.filter(tUnNaming -> tUnNaming.getClass().equals(TDAI.class))
232229
.map(TDAI.class::cast)
233230
.filter(tdai -> tdai.getName().equals(structInstances.getFirst()))
234231
.map(tdai -> {
235-
if(tdai.isSetValImport()) tdai.setValImport(dataAttribute.isValImport());
232+
if (tdai.isSetValImport()) tdai.setValImport(dataAttribute.isValImport());
236233
return tdai;
237234
})
238235
.findFirst()
@@ -247,7 +244,7 @@ private Optional<TDAI> createDoiSdiDaiChainIfNotExists(TAnyLN tAnyLN, DataObject
247244
}
248245

249246
private TSDI findSDIByStructName(TSDI tsdi, List<String> sdiNames) {
250-
if(sdiNames.isEmpty()) return tsdi;
247+
if (sdiNames.isEmpty()) return tsdi;
251248
return this.getSdiByName(tsdi, sdiNames.getFirst())
252249
.map(sdi1 -> {
253250
sdiNames.removeFirst();
@@ -294,14 +291,13 @@ private Optional<TSDI> getSdiByName(TSDI sdi, String sdiName) {
294291
}
295292

296293
/**
297-
*
298-
* @param sdi TSDI
294+
* @param sdi TSDI
299295
* @param structName list start with sdi name
300296
* @return already existing TSDI or newly created TSDI from given TSDI
301297
*/
302298
private TSDI findOrCreateSDIByStructName(TSDI sdi, List<String> structName) {
303299
structName.removeFirst();
304-
if(structName.isEmpty() || structName.size() == 1) return sdi;
300+
if (structName.isEmpty() || structName.size() == 1) return sdi;
305301
return findOrCreateSDIByStructName(findOrCreateSDIFromSDI(sdi, structName.getFirst()), structName);
306302
}
307303

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/LnEditor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@
88
import org.lfenergy.compas.scl2007b4.model.TDAI;
99
import org.lfenergy.compas.sct.commons.domain.DoLinkedToDa;
1010
import org.lfenergy.compas.sct.commons.domain.DoLinkedToDaFilter;
11+
import org.lfenergy.compas.sct.commons.util.ActiveStatus;
1112

1213
import java.util.Optional;
1314

1415
public interface LnEditor {
1516

17+
Optional<ActiveStatus> getDaiModStValValue(TAnyLN tAnyLN);
18+
19+
Optional<TDAI> getDaiModStVal(TAnyLN tAnyLN);
20+
1621
Optional<TDAI> getDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDaFilter doLinkedToDaFilter);
1722

1823
void updateOrCreateDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDa doLinkedToDa);

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

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,20 @@
88
import lombok.Getter;
99
import lombok.NoArgsConstructor;
1010
import lombok.extern.slf4j.Slf4j;
11-
import org.lfenergy.compas.scl2007b4.model.*;
11+
import org.lfenergy.compas.scl2007b4.model.SCL;
12+
import org.lfenergy.compas.scl2007b4.model.TAnyLN;
13+
import org.lfenergy.compas.scl2007b4.model.TExtRef;
14+
import org.lfenergy.compas.scl2007b4.model.TLNodeType;
1215
import org.lfenergy.compas.sct.commons.DataSetService;
1316
import org.lfenergy.compas.sct.commons.ExtRefReaderService;
1417
import org.lfenergy.compas.sct.commons.LnodeTypeService;
1518
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
1619
import org.lfenergy.compas.sct.commons.scl.dtt.DataTypeTemplateAdapter;
1720
import org.lfenergy.compas.sct.commons.scl.dtt.LNodeTypeAdapter;
18-
import org.lfenergy.compas.sct.commons.scl.ln.AbstractLNAdapter;
1921
import org.lfenergy.compas.sct.commons.scl.ldevice.LDeviceAdapter;
22+
import org.lfenergy.compas.sct.commons.scl.ln.AbstractLNAdapter;
2023
import org.lfenergy.compas.sct.commons.scl.ln.LNAdapter;
21-
import org.lfenergy.compas.sct.commons.scl.ln.LnKey;
24+
import org.lfenergy.compas.sct.commons.scl.ln.LnId;
2225
import org.lfenergy.compas.sct.commons.util.Utils;
2326

2427
import java.util.HashSet;
@@ -152,14 +155,10 @@ public static <T extends TAnyLN> LNodeDTO from(AbstractLNAdapter<T> nodeAdapter,
152155

153156
public static LNodeDTO from(TAnyLN tAnyLN, LogicalNodeOptions options, String iedName, String ldInst, SCL scl) {
154157
log.info(Utils.entering());
155-
LnKey lnKey = switch (tAnyLN) {
156-
case LN0 ln0 -> new LnKey(ln0);
157-
case TLN tln -> new LnKey(tln);
158-
default -> throw new IllegalStateException("Unexpected value: " + tAnyLN);
159-
};
160-
String inst = lnKey.getInst();
161-
String lnClass = lnKey.getLnClass();
162-
String prefix = lnKey.getPrefix();
158+
LnId lnId = LnId.from(tAnyLN);
159+
String inst = lnId.lnInst();
160+
String lnClass = lnId.lnClass();
161+
String prefix = lnId.prefix();
163162
String lnType = tAnyLN.getLnType();
164163
LNodeDTO lNodeDTO = new LNodeDTO(inst, lnClass, prefix, lnType);
165164
if (options.isWithExtRef()) {
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// SPDX-FileCopyrightText: 2025 RTE FRANCE
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
package org.lfenergy.compas.sct.commons.scl.ln;
5+
6+
import org.apache.commons.lang3.StringUtils;
7+
import org.lfenergy.compas.scl2007b4.model.*;
8+
import org.lfenergy.compas.sct.commons.exception.ScdException;
9+
10+
import java.util.List;
11+
import java.util.Objects;
12+
13+
public record LnId(String lnClass, String lnInst, String prefix) {
14+
private static final String LN0_LNCLASS = TLLN0Enum.LLN_0.value();
15+
16+
/**
17+
* Id of LN0. All LN0 have the same lnClass, lnInst and prefix in SCD
18+
*/
19+
public static final LnId LN0_ID = new LnId(LN0_LNCLASS, "", "");
20+
21+
/**
22+
* Constructor
23+
*
24+
* @param lnClass always required
25+
* @param lnInst optional. It should be empty for LN0, and should be filled for LN. No verification is done because some Lnode GAPC do not have a lninst.
26+
* @param prefix optional. Is set to empty if null because empty is the default value on LN and the majority of the JAXB Element (LN, LNode, FCDA, ClientLN, but not on ExtRef and IEDName unfortunately)
27+
*/
28+
public LnId(String lnClass, String lnInst, String prefix) {
29+
if (StringUtils.isBlank(lnClass)) {
30+
throw new ScdException("lnClass is required");
31+
}
32+
this.lnClass = lnClass;
33+
this.lnInst = Objects.requireNonNullElse(lnInst, "");
34+
this.prefix = Objects.requireNonNullElse(prefix, "");
35+
}
36+
37+
/**
38+
* Alternative constructor with lnClass as a List instead of a String.
39+
* JAXB classes lnClass attribute are List, even though it can only contain one element.
40+
* This constructor makes it easier to create LnId from JAXB classes
41+
*
42+
* @param lnClass one element list containing the lnClass value of the LN
43+
* @param lnInst LN lnInst
44+
* @param prefix LN prefix
45+
*/
46+
public LnId(List<String> lnClass, String lnInst, String prefix) {
47+
this(lnClass == null || lnClass.isEmpty() ? null : lnClass.getFirst(), lnInst, prefix);
48+
}
49+
50+
/**
51+
* Extract id from LN element
52+
*
53+
* @param tAnyLN LN element
54+
* @return id
55+
*/
56+
public static LnId from(TAnyLN tAnyLN) {
57+
if (tAnyLN instanceof TLN0) {
58+
return LN0_ID;
59+
} else if (tAnyLN instanceof TLN tln) {
60+
return new LnId(tln.getLnClass(), tln.getInst(), tln.getPrefix());
61+
} else {
62+
throw new ScdException("Unexpected class : " + (tAnyLN != null ? tAnyLN.getClass() : null));
63+
}
64+
}
65+
66+
/**
67+
* Extract id from LNode element
68+
*
69+
* @param tlNode LNode element
70+
* @return id
71+
*/
72+
public static LnId from(TLNode tlNode) {
73+
if (tlNode.getLnClass().contains(LN0_LNCLASS)) {
74+
return LN0_ID;
75+
} else {
76+
return new LnId(tlNode.getLnClass(), tlNode.getLnInst(), tlNode.getPrefix());
77+
}
78+
}
79+
80+
81+
}

0 commit comments

Comments
 (0)