Skip to content

Commit 09da44f

Browse files
committed
feat(188): handle Report ExtRef when creating dataSet
Signed-off-by: massifben <[email protected]>
1 parent f1a200d commit 09da44f

File tree

7 files changed

+108
-46
lines changed

7 files changed

+108
-46
lines changed

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

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
import org.lfenergy.compas.sct.commons.util.Utils;
1818

1919
import java.util.*;
20+
import java.util.function.Predicate;
2021
import java.util.stream.Collectors;
21-
import java.util.stream.Stream;
2222

2323
import static org.lfenergy.compas.sct.commons.util.LDeviceStatus.OFF;
2424
import static org.lfenergy.compas.sct.commons.util.LDeviceStatus.ON;
@@ -44,6 +44,9 @@ public class InputsAdapter extends SclElementAdapter<LN0Adapter, TInputs> {
4444
private static final String MESSAGE_SERVICE_TYPE_MISSING_ON_EXTREF = "The signal ExtRef is missing ServiceType attribute";
4545
private static final String MESSAGE_INVALID_SERVICE_TYPE = "The signal ExtRef ServiceType attribute is unexpected : %s";
4646
private static final String MESSAGE_IED_IS_MISSING_PRIVATE_COMPAS_BAY_UUID = "IED is missing Private/compas:Bay@UUID attribute";
47+
private static final String MESSAGE_REPORT_EXTREF_DESC_MALFORMED = "ExtRef.serviceType=Report but ExtRef.desc attribute is malformed";
48+
private static final int EXTREF_DESC_DA_NAME_POSITION = -2;
49+
private static final String EXTREF_DESC_DELIMITER = "_";
4750

4851
/**
4952
* Constructor
@@ -296,29 +299,34 @@ private Optional<SclReportItem> updateSourceDataSetsAndControlBlocks(TExtRef ext
296299
return warningReportItem(extRef, String.format(MESSAGE_SOURCE_LN_NOT_FOUND, optionalSourceLDevice.get().getXPath()));
297300
}
298301

299-
//TODO: Don't forget to test this in issue #84 RSR-433
300-
List<ResumedDataTemplate> mxAndStSources = sourceDas.stream()
301-
.filter(da -> da.getFc() == TFCEnum.MX || da.getFc() == TFCEnum.ST).toList();
302-
303-
Stream<ResumedDataTemplate> sourceDaToProcess;
304-
switch (extRef.getServiceType()) {
305-
case GOOSE:
306-
case SMV:
307-
sourceDaToProcess = mxAndStSources.stream().filter(FcdaCandidates.SINGLETON::contains);
308-
break;
309-
case REPORT:
310-
//TODO: In issue RSR-608, replace with mxAndStSources.filter(...)
311-
sourceDaToProcess = Stream.empty();
312-
break;
313-
case POLL:
314-
default:
315-
return fatalReportItem(extRef, String.format(MESSAGE_INVALID_SERVICE_TYPE, extRef.getServiceType()));
316-
}
302+
Optional<SclReportItem> sclReportItem = removeFilteredSourceDas(extRef, sourceDas);
317303
//TODO: map to FCDA in issue #84 RSR-433 and remove print to console
318-
String daToPrint = sourceDaToProcess
304+
String daToPrint = sourceDas.stream()
319305
.map(da -> da.getFc() + "#" + da.getDataAttributes())
320306
.collect(Collectors.joining(","));
321307
System.out.print("," + (daToPrint.isEmpty() ? "--NO_VALID_SOURCE_DA--" : daToPrint));
308+
return sclReportItem;
309+
}
310+
311+
private Optional<SclReportItem> removeFilteredSourceDas(TExtRef extRef, final Set<ResumedDataTemplate> sourceDas) {
312+
//TODO: Don't forget to test this in issue #84 RSR-433
313+
sourceDas.removeIf(da -> da.getFc() != TFCEnum.MX && da.getFc() != TFCEnum.ST);
314+
return switch (extRef.getServiceType()) {
315+
case GOOSE, SMV -> {
316+
sourceDas.removeIf(Predicate.not(FcdaCandidates.SINGLETON::contains));
317+
yield Optional.empty();
318+
}
319+
case REPORT -> filterReportSourceDa(extRef, sourceDas);
320+
default -> fatalReportItem(extRef, String.format(MESSAGE_INVALID_SERVICE_TYPE, extRef.getServiceType()));
321+
};
322+
}
323+
324+
private Optional<SclReportItem> filterReportSourceDa(TExtRef extRef, Set<ResumedDataTemplate> sourceDas) {
325+
String daName = Utils.extractField(extRef.getDesc(), EXTREF_DESC_DELIMITER, EXTREF_DESC_DA_NAME_POSITION);
326+
if (StringUtils.isBlank(daName)) {
327+
return fatalReportItem(extRef, MESSAGE_REPORT_EXTREF_DESC_MALFORMED);
328+
}
329+
sourceDas.removeIf(resumedDataTemplate -> !resumedDataTemplate.getDaName().toString().equals(daName));
322330
return Optional.empty();
323331
}
324332

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,14 @@ public static boolean equalsOrBothBlank(String s1, String s2) {
140140
|| (StringUtils.isBlank(s1) && StringUtils.isBlank(s2));
141141
}
142142

143+
/**
144+
* Remove all digits at the end of the string, if any
145+
* @param s input string
146+
* @return s without digits at the end.
147+
* Guarantees that the last character of the return value is not a digit.
148+
* If s is composed only of digits, the result is an empty string
149+
* @see Character#isDigit(int)
150+
*/
143151
public static String removeTrailingDigits(String s) {
144152
Objects.requireNonNull(s);
145153
if (s.isEmpty()) {
@@ -151,4 +159,20 @@ public static String removeTrailingDigits(String s) {
151159
}
152160
return s.substring(0, digitsPos);
153161
}
162+
163+
/**
164+
* Split string s using regexDelimiter into an array, and return element at given index.
165+
* @param s string to split
166+
* @param regexDelimiter delimiter
167+
* @param index index of the element in the split array (0 being the first element).
168+
* If index is a negative integer, position is counted from the end (-1 behind the last element).
169+
* @return the element at position index in the split array, or null if index is out of bound
170+
* @see String#split(String)
171+
*/
172+
public static String extractField(String s, String regexDelimiter, int index) {
173+
Objects.requireNonNull(s);
174+
String[] split = s.split(regexDelimiter);
175+
int column = index < 0 ? split.length + index : index;
176+
return 0 <= column && column < split.length ? split[column] : null;
177+
}
154178
}

sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/InputsAdapterForDemoTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,10 @@ public static Stream<Arguments> provideUpdateAllSourceDataSetsAndControlBlocks()
9595
+ "ST#OtherDoName.daNameST",
9696
"ExtRef.desc=test ServiceType is SMV, no daName and DO contains ST and MX, but only ST is FCDA candidate,isBayInternal=true,"
9797
+ "ST#OtherDoName.daNameST"})),
98-
//TODO: issue 608 will change this
9998
Arguments.of(named("for Report, should ignore source DA",
10099
new String[]{
101-
"ExtRef.desc=test ServiceType is Report,isBayInternal=true,"
102-
+ NO_VALID_SOURCE_DA})),
100+
"ExtRef.desc=test ServiceType is Report_daReportST_1,isBayInternal=true,"
101+
+ "ST#DoName.daReportST"})),
103102
Arguments.of(named("should ignore instance number when checking FCDA Candidate file",
104103
new String[]{
105104
"ExtRef.desc=test no daName and doName with instance number,isBayInternal=true,"

sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/InputsAdapterTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,10 @@ void updateAllSourceDataSetsAndControlBlocks_should_report_ExtRef_attribute_miss
8888
"The signal ExtRef is missing ServiceType attribute"),
8989
SclReportItem.fatal("/SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST11\"]/LN0/Inputs/" +
9090
"ExtRef[@desc=\"ExtRef is ServiceType Poll\"]",
91-
"The signal ExtRef ServiceType attribute is unexpected : POLL")
91+
"The signal ExtRef ServiceType attribute is unexpected : POLL"),
92+
SclReportItem.fatal("/SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST11\"]/LN0/Inputs/" +
93+
"ExtRef[@desc=\"ExtRef is ServiceType Report with malformed desc attribute\"]",
94+
"ExtRef.serviceType=Report but ExtRef.desc attribute is malformed")
9295
);
9396
}
9497

sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/UtilsTest.java

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -200,26 +200,6 @@ void equalsOrBothBlank_should_be_true(String s1, String s2) {
200200
assertThat(result).isTrue();
201201
}
202202

203-
@ParameterizedTest
204-
@MethodSource("provideEqualsOrBothBlankNotMatchingSource")
205-
void equalsOrBothBlank_should_be_false(String s1, String s2) {
206-
// Given : parameters
207-
// When
208-
boolean result = Utils.equalsOrBothBlank(s1, s2);
209-
// Then
210-
assertThat(result).isFalse();
211-
}
212-
213-
@ParameterizedTest
214-
@MethodSource("provideRemoveTrailingDigitsSource")
215-
void removeTrailingDigits_should_remove_trailing_digits(String input, String expected) {
216-
// Given : parameter
217-
// When
218-
String result = Utils.removeTrailingDigits(input);
219-
// Then
220-
assertThat(result).isEqualTo(expected);
221-
}
222-
223203
public static Stream<Arguments> provideEqualsOrBothBlankMatchingSource() {
224204
return Stream.of(
225205
Arguments.of("a", "a"),
@@ -235,6 +215,16 @@ public static Stream<Arguments> provideEqualsOrBothBlankMatchingSource() {
235215
);
236216
}
237217

218+
@ParameterizedTest
219+
@MethodSource("provideEqualsOrBothBlankNotMatchingSource")
220+
void equalsOrBothBlank_should_be_false(String s1, String s2) {
221+
// Given : parameters
222+
// When
223+
boolean result = Utils.equalsOrBothBlank(s1, s2);
224+
// Then
225+
assertThat(result).isFalse();
226+
}
227+
238228
public static Stream<Arguments> provideEqualsOrBothBlankNotMatchingSource() {
239229
return Stream.of(
240230
Arguments.of("a", "b"),
@@ -247,6 +237,16 @@ public static Stream<Arguments> provideEqualsOrBothBlankNotMatchingSource() {
247237
);
248238
}
249239

240+
@ParameterizedTest
241+
@MethodSource("provideRemoveTrailingDigitsSource")
242+
void removeTrailingDigits_should_remove_trailing_digits(String input, String expected) {
243+
// Given : parameter
244+
// When
245+
String result = Utils.removeTrailingDigits(input);
246+
// Then
247+
assertThat(result).isEqualTo(expected);
248+
}
249+
250250
public static Stream<Arguments> provideRemoveTrailingDigitsSource() {
251251
return Stream.of(
252252
Arguments.of("a", "a"),
@@ -258,4 +258,29 @@ public static Stream<Arguments> provideRemoveTrailingDigitsSource() {
258258
Arguments.of("1", ""),
259259
Arguments.of("123", ""));
260260
}
261+
262+
@ParameterizedTest
263+
@MethodSource("provideExtractField")
264+
void extractField_should(String s, int index, String expected) {
265+
//Given : parameters
266+
//When
267+
String result = Utils.extractField(s, "_", index);
268+
//Then
269+
assertThat(result).isEqualTo(expected);
270+
}
271+
272+
public static Stream<Arguments> provideExtractField() {
273+
return Stream.of(
274+
Arguments.of("a", 0, "a"),
275+
Arguments.of("a", -1, "a"),
276+
Arguments.of("a_b", 0, "a"),
277+
Arguments.of("a_b", 1, "b"),
278+
Arguments.of("a_b", -1, "b"),
279+
Arguments.of("a_b", -2, "a"),
280+
Arguments.of("a_b_c", -2, "b"),
281+
Arguments.of("a", 1, null),
282+
Arguments.of("a", -2, null),
283+
Arguments.of("a_b_c", -4, null)
284+
);
285+
}
261286
}

sct-commons/src/test/resources/scd-extref-create-dataset-and-controlblocks/scd_create_dataset_and_controlblocks_extref_errors.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@
2626
<Private type="COMPAS-Flow">
2727
<compas:Flow dataStreamKey="ExtRef is missing ServiceType attribute" FlowID="1" FlowKind="BAY_INTERNAL" ExtRefiedName="IED_NAME2" ExtReflnClass="ANCR" ExtRefldinst="LD_INST21" ExtReflnInst="1" ExtRefprefix="" FlowStatus="ACTIVE"/>
2828
<compas:Flow dataStreamKey="ExtRef is ServiceType Poll" FlowID="1" FlowKind="BAY_INTERNAL" ExtRefiedName="IED_NAME2" ExtReflnClass="ANCR" ExtRefldinst="LD_INST21" ExtReflnInst="1" ExtRefprefix="" FlowStatus="ACTIVE"/>
29+
<compas:Flow dataStreamKey="ExtRef is ServiceType Report with malformed desc attribute" FlowID="1" FlowKind="BAY_INTERNAL" ExtRefiedName="IED_NAME2" ExtReflnClass="ANCR" ExtRefldinst="LD_INST21" ExtReflnInst="1" ExtRefprefix="" FlowStatus="ACTIVE"/>
2930
</Private>
3031
<ExtRef desc="ExtRef is missing ServiceType attribute" iedName="IED_NAME2" ldInst="LD_INST21" lnClass="ANCR" lnInst="1" doName="DoName1" daName="daName1" intAddr="INT_ADDR11" pDO="Do11.sdo11" pDA="da11.bda111.bda112.bda113"/>
3132
<ExtRef desc="ExtRef is ServiceType Poll" serviceType="Poll" iedName="IED_NAME2" ldInst="LD_INST21" lnClass="ANCR" lnInst="1" doName="DoName1" daName="daName1" intAddr="INT_ADDR11" pDO="Do11.sdo11" pDA="da11.bda111.bda112.bda113"/>
33+
<ExtRef desc="ExtRef is ServiceType Report with malformed desc attribute" serviceType="Report" iedName="IED_NAME2" ldInst="LD_INST21" lnClass="ANCR" lnInst="1" doName="DoName1" daName="daName1" intAddr="INT_ADDR11" pDO="Do11.sdo11" pDA="da11.bda111.bda112.bda113"/>
3234
</Inputs>
3335
</LN0>
3436
</LDevice>

sct-commons/src/test/resources/scd-extref-create-dataset-and-controlblocks/scd_create_dataset_and_controlblocks_success.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
<compas:Flow dataStreamKey="test daName BL" FlowID="1" FlowKind="BAY_INTERNAL" ExtRefiedName="IED_NAME2" ExtReflnClass="ANCR" ExtRefldinst="LD_INST21" ExtReflnInst="1" ExtRefprefix="" FlowStatus="ACTIVE"/>
3232
<compas:Flow dataStreamKey="test ServiceType is GOOSE, no daName and DO contains ST and MX, but only ST is FCDA candidate" FlowID="1" FlowKind="BAY_INTERNAL" ExtRefiedName="IED_NAME2" ExtReflnClass="ANCR" ExtRefldinst="LD_INST21" ExtReflnInst="1" ExtRefprefix="" FlowStatus="ACTIVE"/>
3333
<compas:Flow dataStreamKey="test ServiceType is SMV, no daName and DO contains ST and MX, but only ST is FCDA candidate" FlowID="1" FlowKind="BAY_INTERNAL" ExtRefiedName="IED_NAME2" ExtReflnClass="ANCR" ExtRefldinst="LD_INST21" ExtReflnInst="1" ExtRefprefix="" FlowStatus="ACTIVE"/>
34-
<compas:Flow dataStreamKey="test ServiceType is Report" FlowID="1" FlowKind="BAY_INTERNAL" ExtRefiedName="IED_NAME2" ExtReflnClass="ANCR" ExtRefldinst="LD_INST21" ExtReflnInst="1" ExtRefprefix="" FlowStatus="ACTIVE"/>
34+
<compas:Flow dataStreamKey="test ServiceType is Report_daReportST_1" FlowID="1" FlowKind="BAY_INTERNAL" ExtRefiedName="IED_NAME2" ExtReflnClass="ANCR" ExtRefldinst="LD_INST21" ExtReflnInst="1" ExtRefprefix="" FlowStatus="ACTIVE"/>
3535
<compas:Flow dataStreamKey="test no daName and doName with instance number" FlowID="1" FlowKind="BAY_INTERNAL" ExtRefiedName="IED_NAME2" ExtReflnClass="ANCR" ExtRefldinst="LD_INST21" ExtReflnInst="1" ExtRefprefix="" FlowStatus="ACTIVE"/>
3636
<compas:Flow dataStreamKey="test no daName and doName with instance number and SDO" FlowID="1" FlowKind="BAY_INTERNAL" ExtRefiedName="IED_NAME2" ExtReflnClass="ANCR" ExtRefldinst="LD_INST21" ExtReflnInst="1" ExtRefprefix="" FlowStatus="ACTIVE"/>
3737
<compas:Flow dataStreamKey="test ignore internal binding" FlowID="1" FlowKind="BAY_INTERNAL" ExtRefiedName="IED_NAME1" ExtReflnClass="ANCR" ExtRefldinst="LD_INST12" ExtReflnInst="1" ExtRefprefix="" FlowStatus="ACTIVE"/>
@@ -52,7 +52,7 @@
5252
<!-- ServiceType = SMV should keep only FCDA candidates -->
5353
<ExtRef desc="test ServiceType is SMV, no daName and DO contains ST and MX, but only ST is FCDA candidate" iedName="IED_NAME2" ldInst="LD_INST21" lnClass="ANCR" lnInst="1" doName="OtherDoName" serviceType="SMV" intAddr="INT_ADDR11" pDO="Do11.sdo11" pDA="da11.bda111.bda112.bda113"/>
5454
<!-- ServiceType = Report -->
55-
<ExtRef desc="test ServiceType is Report" iedName="IED_NAME2" ldInst="LD_INST21" lnClass="ANCR" lnInst="1" doName="DoName" daName="daNameST" serviceType="Report" intAddr="INT_ADDR11" pDO="Do11.sdo11" pDA="da11.bda111.bda112.bda113"/>
55+
<ExtRef desc="test ServiceType is Report_daReportST_1" iedName="IED_NAME2" ldInst="LD_INST21" lnClass="ANCR" lnInst="1" doName="DoName" serviceType="Report" intAddr="INT_ADDR11" pDO="Do11.sdo11" pDA="da11.bda111.bda112.bda113"/>
5656
<!-- doName with instance number => instance number should be ignored when checking FCDA Candidates -->
5757
<ExtRef desc="test no daName and doName with instance number" iedName="IED_NAME2" ldInst="LD_INST21" lnClass="ANCR" lnInst="1" doName="DoWithInst1" serviceType="GOOSE" intAddr="INT_ADDR11" pDO="Do11.sdo11" pDA="da11.bda111.bda112.bda113"/>
5858
<!-- doName with instance number and SDO => instance number should be ignored when checking FCDA Candidates -->
@@ -140,6 +140,7 @@
140140
<DA fc="ST" name="daNameST" bType="BOOLEAN"/>
141141
<DA fc="MX" name="daNameMX" bType="BOOLEAN"/>
142142
<DA fc="BL" name="daNameBL" bType="BOOLEAN"/>
143+
<DA fc="ST" name="daReportST" bType="BOOLEAN"/>
143144
</DOType>
144145
<DOType cdc="ENC" id="Do2">
145146
<SDO name="subDo" type="Do1"/>

0 commit comments

Comments
 (0)