Skip to content

Commit 97f1065

Browse files
massifbenAliouDIAITE
authored andcommitted
feat(78): RSR-437 - update ExtRef iedName part 2/3
Signed-off-by: massifben <[email protected]> Signed-off-by: Aliou DIAITE <[email protected]>
1 parent 399e632 commit 97f1065

29 files changed

+1083
-337
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public class DataTypeName {
5656
public DataTypeName(String dataName){
5757
if(dataName == null) return;
5858
String[] tokens = dataName.split("\\.");
59-
name = tokens[0];
59+
this.name = tokens[0];
6060
if(tokens.length > 1){
6161
structNames.addAll(List.of(tokens).subList(1, tokens.length));
6262
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import java.util.ArrayList;
1212
import java.util.List;
13+
import java.util.Optional;
1314

1415
import static org.lfenergy.compas.sct.commons.util.CommonConstants.MOD_DO_NAME;
1516
import static org.lfenergy.compas.sct.commons.util.CommonConstants.STVAL;
@@ -340,4 +341,16 @@ public ResumedDataTemplate setVal(String daiValue) {
340341
this.setDaiValues(List.of(newDaiVal));
341342
return this;
342343
}
344+
345+
/**
346+
* Retrieve value of the DAI, if present. If multiples values are found,
347+
* the value with the lowest index is returned.
348+
* @return Return the DAI value with the lowest key from getDaName().getdaiValues() map,
349+
* or empty Optional if this DAI has no value.
350+
*/
351+
public Optional<String> findFirstValue() {
352+
return getDaName().getDaiValues().keySet().stream()
353+
.min(Long::compareTo)
354+
.map(key -> getDaName().getDaiValues().get(key));
355+
}
343356
}

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

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,14 @@ public class SclReport {
3030
/**
3131
* List of errors
3232
*/
33-
private List<ErrorDescription> errorDescriptionList = new ArrayList<>();
33+
private List<SclReportItem> sclReportItems = new ArrayList<>();
3434

3535
/**
3636
*
3737
* @return true the service succeeded, false otherwise
3838
*/
3939
public boolean isSuccess() {
40-
return errorDescriptionList.isEmpty();
40+
return sclReportItems.stream().noneMatch(SclReportItem::isFatal);
4141
}
4242

43-
@Getter
44-
@Setter
45-
@AllArgsConstructor
46-
@ToString
47-
@EqualsAndHashCode
48-
@Builder
49-
public static class ErrorDescription{
50-
private String xpath;
51-
private String message;
52-
}
5343
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// SPDX-FileCopyrightText: 2022 RTE FRANCE
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
package org.lfenergy.compas.sct.commons.dto;
6+
7+
import lombok.AllArgsConstructor;
8+
import lombok.EqualsAndHashCode;
9+
import lombok.Getter;
10+
11+
@Getter
12+
@EqualsAndHashCode
13+
@AllArgsConstructor
14+
public final class SclReportItem {
15+
private final String xpath;
16+
private final String message;
17+
private final boolean isFatal;
18+
19+
public static SclReportItem fatal(String xpath, String message) {
20+
return new SclReportItem(xpath, message, true);
21+
}
22+
23+
public static SclReportItem warning(String xpath, String message) {
24+
return new SclReportItem(xpath, message, false);
25+
}
26+
27+
}

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

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,95 @@
55
package org.lfenergy.compas.sct.commons.scl;
66

77
import lombok.experimental.UtilityClass;
8+
import org.apache.commons.lang3.StringUtils;
89
import org.lfenergy.compas.scl2007b4.model.SCL;
10+
import org.lfenergy.compas.scl2007b4.model.TCompasICDHeader;
11+
import org.lfenergy.compas.scl2007b4.model.TIED;
912
import org.lfenergy.compas.sct.commons.dto.SclReport;
13+
import org.lfenergy.compas.sct.commons.dto.SclReportItem;
1014
import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter;
11-
import org.lfenergy.compas.sct.commons.scl.ied.InputsAdapter;
1215
import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter;
1316
import org.lfenergy.compas.sct.commons.scl.ied.LN0Adapter;
17+
import org.lfenergy.compas.sct.commons.util.PrivateEnum;
1418

15-
import java.util.List;
19+
import java.util.*;
20+
import java.util.function.Function;
1621
import java.util.stream.Collectors;
1722

1823
@UtilityClass
1924
public class ExtRefService {
2025

2126
/**
2227
* Updates iedName attribute of all ExtRefs in the Scd.
28+
*
2329
* @return list of encountered errors
2430
*/
2531
public static SclReport updateAllExtRefIedNames(SCL scd) {
2632
SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
33+
List<SclReportItem> iedErrors = validateIed(sclRootAdapter);
34+
if (!iedErrors.isEmpty()) {
35+
return new SclReport(sclRootAdapter, iedErrors);
36+
}
37+
Map<String, IEDAdapter> icdSystemVersionToIed = sclRootAdapter.streamIEDAdapters()
38+
.collect(Collectors.toMap(
39+
iedAdapter -> PrivateService.extractCompasPrivate(iedAdapter.getCurrentElem(), TCompasICDHeader.class)
40+
.map(TCompasICDHeader::getICDSystemVersionUUID)
41+
.orElseThrow(), // Value presence is checked by method validateIed called above
42+
Function.identity()
43+
));
2744

28-
List<SclReport.ErrorDescription> errorDescriptions = sclRootAdapter.streamIEDAdapters()
45+
List<SclReportItem> extRefErrors = sclRootAdapter.streamIEDAdapters()
2946
.flatMap(IEDAdapter::streamLDeviceAdapters)
3047
.filter(LDeviceAdapter::hasLN0)
3148
.map(LDeviceAdapter::getLN0Adapter)
3249
.filter(LN0Adapter::hasInputs)
3350
.map(LN0Adapter::getInputsAdapter)
34-
.map(InputsAdapter::updateAllExtRefIedNames)
35-
.flatMap(List::stream)
36-
.collect(Collectors.toList());
37-
return SclReport.builder()
38-
.sclRootAdapter(sclRootAdapter)
39-
.errorDescriptionList(errorDescriptions).build();
51+
.map(inputsAdapter -> inputsAdapter.updateAllExtRefIedNames(icdSystemVersionToIed))
52+
.flatMap(List::stream).collect(Collectors.toList());
53+
54+
return new SclReport(sclRootAdapter, extRefErrors);
55+
}
56+
57+
private static List<SclReportItem> validateIed(SclRootAdapter sclRootAdapter) {
58+
List<SclReportItem> iedErrors = new ArrayList<>(checkIedCompasIcdHeaderAttributes(sclRootAdapter));
59+
iedErrors.addAll(checkIedUnityOfIcdSystemVersionUuid(sclRootAdapter));
60+
return iedErrors;
4061
}
4162

63+
private static List<SclReportItem> checkIedCompasIcdHeaderAttributes(SclRootAdapter sclRootAdapter) {
64+
return sclRootAdapter.streamIEDAdapters()
65+
.map(iedAdapter -> {
66+
Optional<TCompasICDHeader> compasPrivate = PrivateService.extractCompasPrivate(iedAdapter.getCurrentElem(), TCompasICDHeader.class);
67+
if (compasPrivate.isEmpty()) {
68+
return iedAdapter.buildFatalReportItem(String.format("IED has no Private %s element", PrivateEnum.COMPAS_ICDHEADER.getPrivateType()));
69+
}
70+
if (StringUtils.isBlank(compasPrivate.get().getICDSystemVersionUUID())
71+
|| StringUtils.isBlank(compasPrivate.get().getIEDName())) {
72+
return iedAdapter.buildFatalReportItem(String.format("IED private %s as no icdSystemVersionUUID or iedName attribute",
73+
PrivateEnum.COMPAS_ICDHEADER.getPrivateType()));
74+
}
75+
return null;
76+
}
77+
).filter(Objects::nonNull)
78+
.collect(Collectors.toList());
79+
}
4280

81+
private static List<SclReportItem> checkIedUnityOfIcdSystemVersionUuid(SclRootAdapter sclRootAdapter) {
82+
Map<String, List<TIED>> systemVersionToIedList = sclRootAdapter.getCurrentElem().getIED().stream()
83+
.collect(Collectors.groupingBy(ied -> PrivateService.extractCompasPrivate(ied, TCompasICDHeader.class)
84+
.map(TCompasICDHeader::getICDSystemVersionUUID)
85+
.orElse("")));
4386

87+
return systemVersionToIedList.entrySet().stream()
88+
.filter(entry -> StringUtils.isNotBlank(entry.getKey()))
89+
.filter(entry -> entry.getValue().size() > 1)
90+
.map(entry -> SclReportItem.fatal(entry.getValue().stream()
91+
.map(tied -> new IEDAdapter(sclRootAdapter, tied))
92+
.map(IEDAdapter::getXPath)
93+
.collect(Collectors.joining(", ")),
94+
"/IED/Private/compas:ICDHeader[@ICDSystemVersionUUID] must be unique" +
95+
" but the same ICDSystemVersionUUID was found on several IED."))
96+
.collect(Collectors.toList());
97+
}
4498

4599
}

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import lombok.Setter;
99
import org.apache.commons.lang3.tuple.Pair;
1010
import org.lfenergy.compas.scl2007b4.model.TCompasLDeviceStatus;
11-
import org.lfenergy.compas.sct.commons.util.STValEnum;
11+
import org.lfenergy.compas.sct.commons.util.LDeviceStatus;
1212

1313
import java.util.List;
1414
import java.util.Set;
@@ -38,15 +38,15 @@ public LDeviceActivation(List<Pair<String, String>> iedNameLdInstList) {
3838
* @param enumValues enum values
3939
*/
4040
public void checkLDeviceActivationStatus(String iedName, String ldInst, TCompasLDeviceStatus compasLDeviceStatus, Set<String> enumValues) {
41-
if (!enumValues.contains(STValEnum.ON.value) && !enumValues.contains(STValEnum.OFF.value)) {
41+
if (!enumValues.contains(LDeviceStatus.ON) && !enumValues.contains(LDeviceStatus.OFF)) {
4242
errorMessage = "The LDevice cannot be activated or desactivated because its BehaviourKind Enum contains NOT 'on' AND NOT 'off'.";
4343
}
44-
if (!enumValues.contains(STValEnum.ON.value) && enumValues.contains(STValEnum.OFF.value)) {
44+
if (!enumValues.contains(LDeviceStatus.ON) && enumValues.contains(LDeviceStatus.OFF)) {
4545
if (isDeclaredInSubstation(iedName, ldInst)) {
4646
errorMessage = "The LDevice cannot be set to 'on' but has been selected into SSD.";
4747
} else {
4848
isUpdatable = true;
49-
newVal = STValEnum.OFF.value;
49+
newVal = LDeviceStatus.OFF;
5050
}
5151
}
5252
if(compasLDeviceStatus.equals(TCompasLDeviceStatus.ACTIVE) ||
@@ -65,20 +65,20 @@ public void checkLDeviceActivationStatus(String iedName, String ldInst, TCompasL
6565
* @param enumValues enum values
6666
*/
6767
private void checkAuthorisationToActivateLDevice(String iedName, String ldInst, Set<String> enumValues) {
68-
if (!enumValues.contains(STValEnum.OFF.value) && enumValues.contains(STValEnum.ON.value)) {
68+
if (!enumValues.contains(LDeviceStatus.OFF) && enumValues.contains(LDeviceStatus.ON)) {
6969
if (isDeclaredInSubstation(iedName, ldInst)) {
7070
isUpdatable = true;
71-
newVal = STValEnum.ON.value;
71+
newVal = LDeviceStatus.ON;
7272
} else {
7373
errorMessage = "The LDevice cannot be set to 'off' but has not been selected into SSD.";
7474
}
7575
}
76-
if (enumValues.contains(STValEnum.ON.value) && enumValues.contains(STValEnum.OFF.value)) {
76+
if (enumValues.contains(LDeviceStatus.ON) && enumValues.contains(LDeviceStatus.OFF)) {
7777
isUpdatable = true;
7878
if (isDeclaredInSubstation(iedName, ldInst)) {
79-
newVal = STValEnum.ON.value;
79+
newVal = LDeviceStatus.ON;
8080
} else {
81-
newVal = STValEnum.OFF.value;
81+
newVal = LDeviceStatus.OFF;
8282
}
8383
}
8484

@@ -91,19 +91,19 @@ private void checkAuthorisationToActivateLDevice(String iedName, String ldInst,
9191
* @param enumValues enum values
9292
*/
9393
private void checkAuthorisationToDeactivateLDevice(String iedName, String ldInst, Set<String> enumValues) {
94-
if (!enumValues.contains(STValEnum.OFF.value) && enumValues.contains(STValEnum.ON.value)) {
94+
if (!enumValues.contains(LDeviceStatus.OFF) && enumValues.contains(LDeviceStatus.ON)) {
9595
if (isDeclaredInSubstation(iedName, ldInst)) {
9696
errorMessage = "The LDevice is not qualified into STD but has been selected into SSD.";
9797
} else {
9898
errorMessage = "The LDevice cannot be set to 'off' but has not been selected into SSD.";
9999
}
100100
}
101-
if (enumValues.contains(STValEnum.ON.value) && enumValues.contains(STValEnum.OFF.value)) {
101+
if (enumValues.contains(LDeviceStatus.ON) && enumValues.contains(LDeviceStatus.OFF)) {
102102
if (isDeclaredInSubstation(iedName, ldInst)) {
103103
errorMessage = "The LDevice is not qualified into STD but has been selected into SSD.";
104104
} else {
105105
isUpdatable = true;
106-
newVal = STValEnum.OFF.value;
106+
newVal = LDeviceStatus.OFF;
107107
}
108108
}
109109
}

0 commit comments

Comments
 (0)