diff --git a/sct-commons/pom.xml b/sct-commons/pom.xml
index 3b9236fa4..84043a920 100644
--- a/sct-commons/pom.xml
+++ b/sct-commons/pom.xml
@@ -195,6 +195,23 @@
false
+
+ cbcom
+
+ xjc
+
+
+
+
+
+
+ ${project.basedir}/src/main/resources/binding_configuration.xjb
+
+ org.lfenergy.compas.sct.commons.model.cbcom
+ true
+ false
+
+
diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ControlBlockService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ControlBlockService.java
index 5f28d9e61..1e67cce5e 100644
--- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ControlBlockService.java
+++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ControlBlockService.java
@@ -6,28 +6,33 @@
import org.apache.commons.lang3.StringUtils;
import org.lfenergy.compas.scl2007b4.model.SCL;
+import org.lfenergy.compas.scl2007b4.model.TCompasICDHeader;
+import org.lfenergy.compas.scl2007b4.model.TCompasSystemVersion;
+import org.lfenergy.compas.scl2007b4.model.TDurationInMilliSec;
import org.lfenergy.compas.sct.commons.api.ControlBlockEditor;
-import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings;
-import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings.NetworkRanges;
-import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings.RangesPerCbType;
-import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings.Settings;
-import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings.SettingsOrError;
import org.lfenergy.compas.sct.commons.dto.FcdaForDataSetsCreation;
import org.lfenergy.compas.sct.commons.dto.SclReportItem;
import org.lfenergy.compas.sct.commons.exception.ScdException;
+import org.lfenergy.compas.sct.commons.model.cbcom.*;
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
import org.lfenergy.compas.sct.commons.scl.ied.ControlBlockAdapter;
import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter;
import org.lfenergy.compas.sct.commons.scl.ldevice.LDeviceAdapter;
import org.lfenergy.compas.sct.commons.scl.ln.LNAdapter;
import org.lfenergy.compas.sct.commons.util.ControlBlockEnum;
+import org.lfenergy.compas.sct.commons.util.SclConstructorHelper;
import org.lfenergy.compas.sct.commons.util.Utils;
+import java.math.BigInteger;
import java.util.*;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ControlBlockService implements ControlBlockEditor {
+ private static final int MAX_VLAN_ID = 0x0FFF;
+ private static final int MAX_VLAN_PRIORITY = 7;
+ private static final String NONE = "none";
@Override
public List analyzeDataGroups(SCL scd) {
@@ -84,11 +89,10 @@ private List createDataSetAndControlBlocks(Stream
}
@Override
- public List configureNetworkForAllControlBlocks(SCL scd, ControlBlockNetworkSettings controlBlockNetworkSettings,
- RangesPerCbType rangesPerCbType) {
+ public List configureNetworkForAllControlBlocks(SCL scd, CBCom cbCom) {
List sclReportItems = new ArrayList<>();
- sclReportItems.addAll(configureNetworkForControlBlocks(scd, controlBlockNetworkSettings, rangesPerCbType.gse(), ControlBlockEnum.GSE));
- sclReportItems.addAll(configureNetworkForControlBlocks(scd, controlBlockNetworkSettings, rangesPerCbType.sampledValue(), ControlBlockEnum.SAMPLED_VALUE));
+ sclReportItems.addAll(configureNetworkForControlBlocks(scd, cbCom, TCBType.GOOSE));
+ sclReportItems.addAll(configureNetworkForControlBlocks(scd, cbCom, TCBType.SV));
return sclReportItems;
}
@@ -110,11 +114,26 @@ public void removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(final SCL scl)
.forEach(LNAdapter::removeAllControlBlocksAndDatasets);
}
+ private List configureNetworkForControlBlocks(SCL scd, CBCom cbCom, TCBType tcbType) {
+ TRange appIdRange = Optional.ofNullable(cbCom.getAppIdRanges()).map(AppIdRanges::getAppIdRange).stream()
+ .flatMap(Collection::stream)
+ .filter(tRange -> tcbType.equals(tRange.getCBType()))
+ .findFirst()
+ .orElseThrow(() -> new ScdException("Control Block Communication setting files does not contain AppIdRange for cbType " + tcbType.value()));
- private List configureNetworkForControlBlocks(SCL scd, ControlBlockNetworkSettings controlBlockNetworkSettings,
- NetworkRanges networkRanges, ControlBlockEnum controlBlockEnum) {
- PrimitiveIterator.OfLong appIdIterator = Utils.sequence(networkRanges.appIdStart(), networkRanges.appIdEnd());
- Iterator macAddressIterator = Utils.macAddressSequence(networkRanges.macAddressStart(), networkRanges.macAddressEnd());
+ TRange macRange = Optional.ofNullable(cbCom.getMacRanges()).map(MacRanges::getMacRange).stream()
+ .flatMap(Collection::stream)
+ .filter(tRange -> tcbType.equals(tRange.getCBType()))
+ .findFirst()
+ .orElseThrow(() -> new ScdException("Control Block Communication setting files does not contain MacRange for cbType " + tcbType.value()));
+
+ PrimitiveIterator.OfLong appIdIterator = Utils.sequence(Long.parseLong(appIdRange.getStart(), 16), Long.parseLong(appIdRange.getEnd(), 16));
+ Iterator macAddressIterator = Utils.macAddressSequence(macRange.getStart(), macRange.getEnd());
+
+ Map settingsByCriteria = Optional.ofNullable(cbCom.getVlans()).map(Vlans::getVlan).stream()
+ .flatMap(Collection::stream)
+ .filter(vlan -> tcbType.equals(vlan.getCBType()))
+ .collect(Collectors.toMap(this::vlanToCriteria, this::vlanToSetting));
SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
return sclRootAdapter.streamIEDAdapters()
@@ -122,38 +141,187 @@ private List configureNetworkForControlBlocks(SCL scd, ControlBlo
iedAdapter.streamLDeviceAdapters()
.filter(LDeviceAdapter::hasLN0)
.map(LDeviceAdapter::getLN0Adapter)
- .flatMap(ln0Adapter -> ln0Adapter.streamControlBlocks(controlBlockEnum))
- .map(controlBlockAdapter -> configureControlBlockNetwork(controlBlockNetworkSettings, appIdIterator, macAddressIterator, controlBlockAdapter)))
+ .flatMap(ln0Adapter -> ln0Adapter.streamControlBlocks(ControlBlockEnum.from(tcbType)))
+ .map(controlBlockAdapter -> configureControlBlockNetwork(settingsByCriteria, appIdIterator, macAddressIterator, controlBlockAdapter)))
.flatMap(Optional::stream)
.toList();
}
- private Optional configureControlBlockNetwork(ControlBlockNetworkSettings controlBlockNetworkSettings, PrimitiveIterator.OfLong appIdIterator, Iterator macAddressIterator, ControlBlockAdapter controlBlockAdapter) {
- SettingsOrError settingsOrError = controlBlockNetworkSettings.getNetworkSettings(controlBlockAdapter);
+ private Optional configureControlBlockNetwork(Map comSettingsByCriteria, PrimitiveIterator.OfLong appIdIterator, Iterator macAddressIterator, ControlBlockAdapter controlBlockAdapter) {
+ SettingsOrError settingsOrError = getNetworkSettings(controlBlockAdapter, comSettingsByCriteria);
if (settingsOrError.errorMessage() != null) {
return Optional.of(controlBlockAdapter.buildFatalReportItem(
- "Cannot configure network for this ControlBlock because: " + settingsOrError.errorMessage()));
+ "Cannot configure communication for this ControlBlock because: " + settingsOrError.errorMessage()));
}
Settings settings = settingsOrError.settings();
if (settings == null) {
return Optional.of(controlBlockAdapter.buildFatalReportItem(
- "Cannot configure network for this ControlBlock because no settings was provided"));
+ "Cannot configure communication for this ControlBlock because no settings was provided"));
}
if (settings.vlanId() == null) {
return Optional.of(controlBlockAdapter.buildFatalReportItem(
- "Cannot configure network for this ControlBlock because no Vlan Id was provided in the settings"));
+ "Cannot configure communication for this ControlBlock because no Vlan Id was provided in the settings"));
}
if (!appIdIterator.hasNext()) {
return Optional.of(controlBlockAdapter.buildFatalReportItem(
- "Cannot configure network for this ControlBlock because range of appId is exhausted"));
+ "Cannot configure communication for this ControlBlock because range of appId is exhausted"));
}
if (!macAddressIterator.hasNext()) {
return Optional.of(controlBlockAdapter.buildFatalReportItem(
- "Cannot configure network for this ControlBlock because range of MAC Address is exhausted"));
+ "Cannot configure communication for this ControlBlock because range of MAC Address is exhausted"));
}
return controlBlockAdapter.configureNetwork(appIdIterator.nextLong(), macAddressIterator.next(), settings.vlanId(), settings.vlanPriority(),
settings.minTime(), settings.maxTime());
}
+ public SettingsOrError getNetworkSettings(ControlBlockAdapter controlBlockAdapter, Map comSettingsByCriteria) {
+ TCBType cbType = controlBlockAdapter.getControlBlockEnum().toTCBType();
+ IEDAdapter iedAdapter = controlBlockAdapter.getParentIedAdapter();
+ Optional compasSystemVersion = iedAdapter.getCompasSystemVersion();
+ if (compasSystemVersion.isEmpty()) {
+ return new SettingsOrError(null, "No private COMPAS-SystemVersion found in this IED");
+ }
+ if (StringUtils.isBlank(compasSystemVersion.get().getMainSystemVersion())
+ || (StringUtils.isBlank(compasSystemVersion.get().getMinorSystemVersion()))) {
+ return new SettingsOrError(null, "Missing MainSystemVersion or MinorSystemVersion attribute in COMPAS-SystemVersion private of IED");
+ }
+ String systemVersionWithoutV = removeVFromSystemVersion(compasSystemVersion.get());
+ Optional compasICDHeader = iedAdapter.getCompasICDHeader();
+ if (compasICDHeader.isEmpty()) {
+ return new SettingsOrError(null, "No private COMPAS-ICDHeader found in this IED");
+ }
+ if (compasICDHeader.get().getIEDSystemVersioninstance() == null) {
+ return new SettingsOrError(null, "No IEDSystemVersioninstance in the COMPAS-ICDHeader of this IED");
+ }
+ TBayIntOrExt bayIntOrExt = controlBlockAdapter.getName().endsWith("I") ? TBayIntOrExt.BAY_INTERNAL : TBayIntOrExt.BAY_EXTERNAL;
+
+ Criteria criteria = new Criteria(cbType,
+ systemVersionWithoutV,
+ TIEDType.fromValue(compasICDHeader.get().getIEDType().value()),
+ TIEDRedundancy.fromValue(compasICDHeader.get().getIEDredundancy().value()),
+ compasICDHeader.get().getIEDSystemVersioninstance(),
+ bayIntOrExt);
+ Settings settings = comSettingsByCriteria.get(criteria);
+ return new SettingsOrError(settings, settings != null ? null : "No controlBlock communication settings found with these " + criteria);
+ }
+
+ private String removeVFromSystemVersion(TCompasSystemVersion compasSystemVersion) {
+ String[] minorVersionParts = compasSystemVersion.getMinorSystemVersion().split("\\.");
+ return (minorVersionParts.length == 3) ?
+ compasSystemVersion.getMainSystemVersion() + "." + minorVersionParts[0] + "." + minorVersionParts[1]
+ : null;
+ }
+
+ private Criteria vlanToCriteria(TVlan vlan) {
+ requireNotNull(vlan.getCBType(), "CBType");
+ requireNotBlank(vlan.getXY(), "XY");
+ requireNotBlank(vlan.getZW(), "ZW");
+ requireNotNull(vlan.getIEDType(), "IEDType");
+ requireNotNull(vlan.getIEDRedundancy(), "IEDRedundancy");
+ requireNotBlank(vlan.getIEDSystemVersionInstance(), "IEDSystemVersionInstance");
+ requireNotNull(vlan.getBayIntOrExt(), "BayIntOrExt");
+
+ return new Criteria(
+ vlan.getCBType(),
+ vlan.getXY() + "." + vlan.getZW(),
+ vlan.getIEDType(),
+ vlan.getIEDRedundancy(),
+ toIedSystemVersionInstance(vlan.getIEDSystemVersionInstance()),
+ vlan.getBayIntOrExt()
+ );
+ }
+
+ private Settings vlanToSetting(TVlan vlan) {
+ return new Settings(toVLanId(vlan.getVlanId()), toVlanPriority(vlan.getVlanPriority()), toDurationInMilliSec(vlan.getMinTime()), toDurationInMilliSec(vlan.getMaxTime()));
+ }
+
+ private void requireNotBlank(String str, String attribute) {
+ if (StringUtils.isBlank(str)) {
+ throw new ScdException("Error in Control Block communication setting file: vlan is missing attribute " + attribute);
+ }
+ }
+
+ private void requireNotNull(Object o, String attribute) {
+ if (Objects.isNull(o)) {
+ throw new ScdException("Error in Control Block communication setting file: vlan is missing attribute " + attribute);
+ }
+ }
+
+ private BigInteger toIedSystemVersionInstance(String strIedSystemVersionInstance) {
+ if (StringUtils.isBlank(strIedSystemVersionInstance)) {
+ return null;
+ }
+ BigInteger iedSystemVersionInstance;
+ try {
+ iedSystemVersionInstance = new BigInteger(strIedSystemVersionInstance);
+ } catch (NumberFormatException e) {
+ throw new ScdException("Error in Control Block communication setting file: IED System Version Instance must be an integer, but got : %s".formatted(strIedSystemVersionInstance));
+ }
+ return iedSystemVersionInstance;
+ }
+
+ private Integer toVLanId(String strVlanId) {
+ if (StringUtils.isBlank(strVlanId) || NONE.equalsIgnoreCase(strVlanId)) {
+ return null;
+ }
+ int vlanId;
+ try {
+ vlanId = Integer.parseInt(strVlanId);
+ } catch (NumberFormatException e) {
+ throw new ScdException("Error in Control Block communication setting file: VLAN ID must be an integer or '%s', but got : %s".formatted(NONE, strVlanId));
+ }
+ if (vlanId < 0 || vlanId > MAX_VLAN_ID) {
+ throw new ScdException("Error in Control Block communication setting file: VLAN ID must be between 0 and %d, but got : %s".formatted(MAX_VLAN_ID, strVlanId));
+ }
+ return vlanId;
+ }
+
+ private static Byte toVlanPriority(String strVlanPriority) {
+ if (StringUtils.isBlank(strVlanPriority) || NONE.equalsIgnoreCase(strVlanPriority)) {
+ return null;
+ }
+ byte vlanPriority;
+ try {
+ vlanPriority = Byte.parseByte(strVlanPriority);
+ } catch (NumberFormatException e) {
+ throw new ScdException("Error in Control Block communication setting file: VLAN Priority must be an integer or '%s', but got : %s".formatted(NONE, strVlanPriority));
+ }
+ if (vlanPriority < 0 || vlanPriority > MAX_VLAN_PRIORITY) {
+ throw new ScdException("Error in Control Block communication setting file: VLAN PRIORITY must be between 0 and %d, but got : %s".formatted(MAX_VLAN_PRIORITY, strVlanPriority));
+ }
+ return vlanPriority;
+ }
+
+ private TDurationInMilliSec toDurationInMilliSec(String strDuration) {
+ if (StringUtils.isBlank(strDuration) || NONE.equalsIgnoreCase(strDuration)) {
+ return null;
+ }
+ long duration;
+ try {
+ duration = Long.parseLong(strDuration);
+ } catch (NumberFormatException e) {
+ throw new ScdException("Error in Control Block communication setting file: VLAN MinTime and MaxTime must be an integer or '%s' got : %s".formatted(NONE, strDuration));
+ }
+ return SclConstructorHelper.newDurationInMilliSec(duration);
+ }
+
+ /**
+ * Key to search for a control block communication setting
+ */
+ public record Criteria(TCBType cbType, String systemVersionWithoutV, TIEDType iedType, TIEDRedundancy iedRedundancy, BigInteger iedSystemVersionInstance, TBayIntOrExt bayIntOrExt) {
+ }
+
+ /**
+ * Communication settings for ControlBlock
+ */
+ public record Settings(Integer vlanId, Byte vlanPriority, TDurationInMilliSec minTime, TDurationInMilliSec maxTime) {
+ }
+
+ /**
+ * Communication settings for ControlBlock or Error message
+ */
+ public record SettingsOrError(Settings settings, String errorMessage) {
+ }
+
}
diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/ControlBlockEditor.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/ControlBlockEditor.java
index 7406c23c3..8235dd5ea 100644
--- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/ControlBlockEditor.java
+++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/ControlBlockEditor.java
@@ -6,9 +6,9 @@
import org.lfenergy.compas.scl2007b4.model.SCL;
import org.lfenergy.compas.scl2007b4.model.TExtRef;
-import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings;
import org.lfenergy.compas.sct.commons.dto.FcdaForDataSetsCreation;
import org.lfenergy.compas.sct.commons.dto.SclReportItem;
+import org.lfenergy.compas.sct.commons.model.cbcom.CBCom;
import org.lfenergy.compas.sct.commons.util.Utils;
import java.util.List;
@@ -22,7 +22,7 @@
*
*
{@link ControlBlockEditor#createDataSetAndControlBlocks(SCL, Set) Create DataSet and ControlBlock based on the TExtRef}
*
{@link ControlBlockEditor#createDataSetAndControlBlocks(SCL, String, Set) Create DataSet and ControlBlock based on the TExtRef in given IED}
- *
{@link ControlBlockEditor#createDataSetAndControlBlocks(SCL, String,String, Set) Create DataSet and ControlBlock based on the TExtRef in given IED and LDevice}
+ *
{@link ControlBlockEditor#createDataSetAndControlBlocks(SCL, String, String, Set) Create DataSet and ControlBlock based on the TExtRef in given IED and LDevice}
*
{@link ControlBlockEditor#configureNetworkForAllControlBlocks Configure the network for the ControlBlocks}
*
{@link ControlBlockEditor#removeAllControlBlocksAndDatasetsAndExtRefSrcBindings Removes all ControlBlocks and DataSets for all LNs in SCL}
*
{@link ControlBlockEditor#analyzeDataGroups(SCL)} Checks Control Blocks, DataSets and FCDA number limitation into Access Points }
@@ -85,17 +85,11 @@ public interface ControlBlockEditor {
* - the Communication/SubNetwork/ConnectedAP/GSE element, for the GSEControl blocks
* - the Communication/SubNetwork/ConnectedAP/SMV element, for the SampledValueControl blocks
*
- * @param scd input SCD object. The object will be modified with the new DataGSESet and SMV elements
- * @param controlBlockNetworkSettings a method tha gives the network configuration information for a given ControlBlock
- * @param rangesPerCbType provide NetworkRanges for GSEControl and SampledValueControl. NetworkRanges contains :
- * start-end app APPID range (long value), start-end MAC-Addresses (Mac-Addresses values: Ex: "01-0C-CD-01-01-FF")
+ * @param scd input SCD object. The object will be modified with the new GSE and SMV elements
+ * @param cbCom communication settings to configure Control Block Communication
* @return list of encountered errors
* @see Utils#macAddressToLong(String) for the expected MAC address format
- * @see ControlBlockNetworkSettings
- * @see ControlBlockNetworkSettings.RangesPerCbType
- * @see ControlBlockNetworkSettings.NetworkRanges
*/
- List configureNetworkForAllControlBlocks(SCL scd, ControlBlockNetworkSettings controlBlockNetworkSettings,
- ControlBlockNetworkSettings.RangesPerCbType rangesPerCbType);
+ List configureNetworkForAllControlBlocks(SCL scd, CBCom cbCom);
}
diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ControlBlockNetworkSettings.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ControlBlockNetworkSettings.java
deleted file mode 100644
index 65fcb11f3..000000000
--- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ControlBlockNetworkSettings.java
+++ /dev/null
@@ -1,71 +0,0 @@
-// SPDX-FileCopyrightText: 2023 RTE FRANCE
-//
-// SPDX-License-Identifier: Apache-2.0
-
-package org.lfenergy.compas.sct.commons.dto;
-
-import org.lfenergy.compas.scl2007b4.model.TDurationInMilliSec;
-import org.lfenergy.compas.sct.commons.scl.ied.ControlBlockAdapter;
-
-/**
- * This interface has a single method which provides network settings for a ControlBlock.
- * These are used to create:
- * - the Communication/SubNetwork/ConnectedAP/GSE element, which is the network configuration of a GSEControl block
- * - the Communication/SubNetwork/ConnectedAP/SMV element, which is the network configuration of a SampledValueControl block
- * It is a FunctionalInterface, so it can be implemented with a lambda expression.
- *
- * @see org.lfenergy.compas.sct.commons.util.ControlBlockNetworkSettingsCsvHelper
- */
-@FunctionalInterface
-public interface ControlBlockNetworkSettings {
-
- /**
- * This method provides a vlanId, vlanPriority, minTime, maxTime for this ControlBlock.
- * vlanPriority will be ignored when vlanId is null.
- *
- * @param controlBlockAdapter ControlBlock for which we want to configure the communication section
- * @return network settings to use for configuring Communication section for this ControlBlock.
- * An error message can be provided (i.e. errorMessage not null) or a null settings, in order to avoid configuring the ControlBlock.
- */
- SettingsOrError getNetworkSettings(ControlBlockAdapter controlBlockAdapter);
-
- /**
- * Network settings for ControlBlock communication
- *
- * @param vlanId id of the vlan
- * @param vlanPriority priority for the vlan
- * @param minTime minTime for GSE communication element
- * @param maxTime maxTime for GSE communication element
- */
- record Settings(Integer vlanId, Byte vlanPriority, TDurationInMilliSec minTime, TDurationInMilliSec maxTime) {
- }
-
- /**
- * Network settings for ControlBlock communication or Error message
- *
- * @param settings Network settings for ControlBlock communication. Can be null when errorMessage is provided
- * @param errorMessage should be null if settings is provided
- */
- record SettingsOrError(Settings settings, String errorMessage) {
- }
-
- /**
- * NetworkRanges for GSEControl and SampledValueControl
- *
- * @param gse NetworkRanges for GSEControl
- * @param sampledValue NetworkRanges for SampledValueControl
- */
- record RangesPerCbType(NetworkRanges gse, NetworkRanges sampledValue) {
- }
-
- /**
- * Range of APPID and range of MAC-Address
- *
- * @param appIdStart range start for APPID (inclusive)
- * @param appIdEnd range end for APPID (inclusive)
- * @param macAddressStart range start for MAC-Addresses (inclusive). Ex: "01-0C-CD-01-00-00"
- * @param macAddressEnd range end for MAC-Addresses (inclusive). Ex: "01-0C-CD-01-01-FF"
- */
- record NetworkRanges(long appIdStart, long appIdEnd, String macAddressStart, String macAddressEnd) {
- }
-}
diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/ControlBlockEnum.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/ControlBlockEnum.java
index 23cb0bbcb..2283fb1a1 100644
--- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/ControlBlockEnum.java
+++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/ControlBlockEnum.java
@@ -6,6 +6,7 @@
import lombok.Getter;
import org.lfenergy.compas.scl2007b4.model.*;
+import org.lfenergy.compas.sct.commons.model.cbcom.TCBType;
import java.util.Arrays;
import java.util.Objects;
@@ -40,4 +41,20 @@ public static ControlBlockEnum from(Class extends TControl> tControlClass) {
.orElseThrow(() -> new IllegalArgumentException("Unsupported TControl class : " + tControlClass.getSimpleName()));
}
+ public static ControlBlockEnum from(TCBType tcbType) {
+ return switch (tcbType){
+ case GOOSE -> GSE;
+ case SV -> SAMPLED_VALUE;
+ default -> throw new IllegalArgumentException("Unsupported TCBType: " + tcbType);
+ };
+ }
+
+ public TCBType toTCBType(){
+ return switch (this){
+ case GSE -> TCBType.GOOSE;
+ case SAMPLED_VALUE -> TCBType.SV;
+ default -> throw new IllegalArgumentException("Cannot convert ControlBlockEnum " + this + " to TCBType");
+ };
+ }
+
}
diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/ControlBlockNetworkSettingsCsvHelper.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/ControlBlockNetworkSettingsCsvHelper.java
deleted file mode 100644
index dc4b2ff6a..000000000
--- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/ControlBlockNetworkSettingsCsvHelper.java
+++ /dev/null
@@ -1,204 +0,0 @@
-// SPDX-FileCopyrightText: 2023 RTE FRANCE
-//
-// SPDX-License-Identifier: Apache-2.0
-
-package org.lfenergy.compas.sct.commons.util;
-
-import com.opencsv.bean.CsvBindByPosition;
-import lombok.ToString;
-import org.apache.commons.lang3.StringUtils;
-import org.lfenergy.compas.scl2007b4.model.*;
-import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings;
-import org.lfenergy.compas.sct.commons.scl.ied.ControlBlockAdapter;
-import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter;
-
-import java.io.Reader;
-import java.math.BigInteger;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
-/**
- * This class is an implementation example for interface ControlBlockNetworkSettings.
- * It relies on a CSV file.
- * The first columns of the CSV file are the criteria to match the ControlBlock (controlBlockEnum, systemVersionWithoutV, iedType, iedRedundancy,
- * isBayInternal),
- * The last columns are the network settings for the matched ControlBlock (as described in {@link ControlBlockNetworkSettings.Settings}).
- *
- * @see CsvUtils
- */
-public class ControlBlockNetworkSettingsCsvHelper implements ControlBlockNetworkSettings {
-
- private static final int MAX_VLAN_ID = 0x0FFF;
- private static final int MAX_VLAN_PRIORITY = 7;
- private static final String NONE = "none";
-
- private final Map allSettings;
-
- /**
- * Constructor
- * Provide the CSV file as a Reader. For example, you can create a reader like this :
- * new InputStreamReader(getClass().getClassLoader().getResourceAsStream(fileName), StandardCharsets.UTF_8);
- *
- * @param csvSource a reader that provides the data as CSV. For example :
- */
- public ControlBlockNetworkSettingsCsvHelper(Reader csvSource) {
- allSettings = readCsvFile(csvSource);
- }
-
- private Map readCsvFile(Reader csvSource) {
- return CsvUtils.parseRows(csvSource, Row.class).stream()
- .distinct()
- .collect(Collectors.toMap(
- ControlBlockNetworkSettingsCsvHelper::rowToCriteria,
- ControlBlockNetworkSettingsCsvHelper::rowToSetting
- ));
- }
-
- @Override
- public SettingsOrError getNetworkSettings(ControlBlockAdapter controlBlockAdapter) {
- ControlBlockEnum controlBlockEnum = controlBlockAdapter.getControlBlockEnum();
- IEDAdapter iedAdapter = controlBlockAdapter.getParentIedAdapter();
- Optional compasSystemVersion = iedAdapter.getCompasSystemVersion();
- if (compasSystemVersion.isEmpty()) {
- return new SettingsOrError(null, "No private COMPAS-SystemVersion found in this IED");
- }
- String systemVersionWithoutV = removeVFromSystemVersion(compasSystemVersion.get());
- Optional compasICDHeader = iedAdapter.getCompasICDHeader();
- if (compasICDHeader.isEmpty()) {
- return new SettingsOrError(null, "No private COMPAS-ICDHeader found in this IED");
- }
- TCompasIEDType iedType = compasICDHeader.get().getIEDType();
- TCompasIEDRedundancy iedRedundancy = compasICDHeader.get().getIEDredundancy();
- BigInteger iedSystemVersionInstance = compasICDHeader.get().getIEDSystemVersioninstance();
- boolean isBayInternal = controlBlockAdapter.getName().endsWith("I");
-
- Criteria criteria = new Criteria(controlBlockEnum, systemVersionWithoutV, iedType, iedRedundancy, iedSystemVersionInstance, isBayInternal);
- Settings settings = findSettings(criteria);
- return settings != null ?
- new SettingsOrError(settings, null) :
- new SettingsOrError(null, "No row found with these criteria " + criteria);
- }
-
- private Settings findSettings(Criteria criteria) {
- Objects.requireNonNull(criteria);
- if (criteria.systemVersionWithoutV() == null
- || criteria.iedType() == null
- || criteria.iedRedundancy() == null
- || criteria.iedSystemVersionInstance == null) {
- return null;
- }
- return allSettings.get(criteria);
- }
-
- private static String removeVFromSystemVersion(TCompasSystemVersion compasSystemVersion) {
- if (StringUtils.isBlank(compasSystemVersion.getMainSystemVersion())
- || (StringUtils.isBlank(compasSystemVersion.getMinorSystemVersion()))) {
- return null;
- }
- String[] minorVersionParts = compasSystemVersion.getMinorSystemVersion().split("\\.");
- return (minorVersionParts.length == 3) ?
- compasSystemVersion.getMainSystemVersion() + "." + minorVersionParts[0] + "." + minorVersionParts[1]
- : null;
- }
-
- private static Criteria rowToCriteria(Row row) {
- if (StringUtils.isBlank(row.cbType)
- || StringUtils.isBlank(row.xy)
- || StringUtils.isBlank(row.zw)
- || StringUtils.isBlank(row.iedType)
- || StringUtils.isBlank(row.iedRedundancy)
- || StringUtils.isBlank(row.iedSystemVersionInstance)
- || StringUtils.isBlank(row.bindingType)
- ) {
- throw new IllegalArgumentException("At least one criteria is null in row " + row);
- }
- ControlBlockEnum controlBlockEnum = switch (row.cbType) {
- case "GOOSE" -> ControlBlockEnum.GSE;
- case "SV" -> ControlBlockEnum.SAMPLED_VALUE;
- default -> throw new IllegalArgumentException("Unsupported Control Block Type : " + row.cbType);
- };
- return new Criteria(
- controlBlockEnum,
- row.xy + "." + row.zw,
- TCompasIEDType.fromValue(row.iedType),
- TCompasIEDRedundancy.fromValue(row.iedRedundancy),
- new BigInteger(row.iedSystemVersionInstance),
- row.bindingType.equals("BAY_INTERNAL")
- );
- }
-
- private static Settings rowToSetting(Row row) {
- Integer vlanId = toVLanId(row.vlanId);
- Byte vlanPriority = toVlanPriority(row.vlanPriority);
- TDurationInMilliSec minTime = toDurationInMilliSec(row.minTime);
- TDurationInMilliSec maxTime = toDurationInMilliSec(row.maxTime);
- return new Settings(vlanId, vlanPriority, minTime, maxTime);
- }
-
- private static Byte toVlanPriority(String strVlanPriority) {
- if (StringUtils.isBlank(strVlanPriority) || NONE.equalsIgnoreCase(strVlanPriority)) {
- return null;
- }
- byte vlanPriority = Byte.parseByte(strVlanPriority);
- if (vlanPriority < 0 || vlanPriority > MAX_VLAN_PRIORITY) {
- throw new IllegalArgumentException("VLAN PRIORITY must be between 0 and %d, but got : %d".formatted(MAX_VLAN_PRIORITY, vlanPriority));
- }
- return vlanPriority;
- }
-
- private static Integer toVLanId(String strVlanId) {
- if (StringUtils.isBlank(strVlanId) || NONE.equalsIgnoreCase(strVlanId)) {
- return null;
- }
- int vlanId = Integer.parseInt(strVlanId);
- if (vlanId < 0 || vlanId > MAX_VLAN_ID) {
- throw new IllegalArgumentException("VLAN ID must be between 0 and %d, but got : %d".formatted(MAX_VLAN_ID, vlanId));
- }
- return vlanId;
- }
-
- private static TDurationInMilliSec toDurationInMilliSec(String duration) {
- if (StringUtils.isBlank(duration) || NONE.equalsIgnoreCase(duration)) {
- return null;
- }
- return SclConstructorHelper.newDurationInMilliSec(Long.parseLong(duration));
- }
-
- private record Criteria(
- ControlBlockEnum controlBlockEnum,
- String systemVersionWithoutV,
- TCompasIEDType iedType,
- TCompasIEDRedundancy iedRedundancy,
- BigInteger iedSystemVersionInstance,
- boolean isBayInternal) {
- }
-
- @ToString
- public static class Row {
- @CsvBindByPosition(position = 0)
- private String cbType;
- @CsvBindByPosition(position = 1)
- private String xy;
- @CsvBindByPosition(position = 2)
- private String zw;
- @CsvBindByPosition(position = 3)
- private String iedType;
- @CsvBindByPosition(position = 4)
- private String iedRedundancy;
- @CsvBindByPosition(position = 5)
- private String iedSystemVersionInstance;
- @CsvBindByPosition(position = 6)
- private String bindingType;
- @CsvBindByPosition(position = 7)
- private String vlanId;
- @CsvBindByPosition(position = 8)
- private String vlanPriority;
- @CsvBindByPosition(position = 9)
- private String minTime;
- @CsvBindByPosition(position = 10)
- private String maxTime;
- }
-
-}
diff --git a/sct-commons/src/main/resources/xsd/RCONF_CB_COM_Config_file_v1.xsd b/sct-commons/src/main/resources/xsd/RCONF_CB_COM_Config_file_v1.xsd
new file mode 100644
index 000000000..ed987e445
--- /dev/null
+++ b/sct-commons/src/main/resources/xsd/RCONF_CB_COM_Config_file_v1.xsd
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IED type to be used to identity the set of LDevice.inst handled by the IED
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ControlBlockServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ControlBlockServiceTest.java
index 9045762fa..a16a65867 100644
--- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ControlBlockServiceTest.java
+++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ControlBlockServiceTest.java
@@ -12,11 +12,11 @@
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.lfenergy.compas.scl2007b4.model.*;
-import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings;
import org.lfenergy.compas.sct.commons.dto.ControlBlockTarget;
import org.lfenergy.compas.sct.commons.dto.FcdaForDataSetsCreation;
import org.lfenergy.compas.sct.commons.dto.SclReportItem;
import org.lfenergy.compas.sct.commons.exception.ScdException;
+import org.lfenergy.compas.sct.commons.model.cbcom.*;
import org.lfenergy.compas.sct.commons.scl.SclElementAdapter;
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
import org.lfenergy.compas.sct.commons.scl.ied.DataSetAdapter;
@@ -32,22 +32,20 @@
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;
-import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.*;
import static org.lfenergy.compas.scl2007b4.model.TFCEnum.ST;
-import static org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings.*;
import static org.lfenergy.compas.sct.commons.testhelpers.SclHelper.*;
import static org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller.assertIsMarshallable;
import static org.lfenergy.compas.sct.commons.util.ControlBlockEnum.*;
-import static org.lfenergy.compas.sct.commons.util.SclConstructorHelper.newDurationInMilliSec;
@ExtendWith(MockitoExtension.class)
class ControlBlockServiceTest {
@@ -57,15 +55,6 @@ class ControlBlockServiceTest {
private Set allowedFcdas;
- private static final long GSE_APP_ID_MIN = 0x9;
- private static final long SMV_APP_ID_MIN = 0x400A;
- private static final String GSE_MAC_ADDRESS_PREFIX = "01-02-03-04-";
- private static final String SMV_MAC_ADDRESS_PREFIX = "0A-0B-0C-0D-";
- private static final NetworkRanges GSE_NETWORK_RANGES = new NetworkRanges(GSE_APP_ID_MIN, GSE_APP_ID_MIN + 10, GSE_MAC_ADDRESS_PREFIX + "00-FF", GSE_MAC_ADDRESS_PREFIX + "01-AA");
- private static final NetworkRanges SMV_NETWORK_RANGES = new NetworkRanges(SMV_APP_ID_MIN, SMV_APP_ID_MIN + 10, SMV_MAC_ADDRESS_PREFIX + "00-FF", SMV_MAC_ADDRESS_PREFIX + "01-AA");
- private static final RangesPerCbType RANGES_PER_CB_TYPE = new RangesPerCbType(GSE_NETWORK_RANGES, SMV_NETWORK_RANGES);
-
-
@BeforeEach
void init() {
allowedFcdas = new HashSet<>(CsvUtils.parseRows("FcdaCandidates.csv", StandardCharsets.UTF_8, FcdaForDataSetsCreation.class));
@@ -355,7 +344,6 @@ void createDataSetAndControlBlocks_when_targetLDeviceInst_is_provided_without_ta
}
-
@Test
void updateAllSourceDataSetsAndControlBlocks_should_sort_FCDA_inside_DataSet_and_avoid_duplicates() {
// Given
@@ -376,45 +364,73 @@ void updateAllSourceDataSetsAndControlBlocks_should_sort_FCDA_inside_DataSet_and
}
@Test
- void configureNetworkForAllControlBlocks_should_create_GSE_and_SMV_elements() {
+ void configureNetworkForAllControlBlocks_should_create_GSE_elements() {
// Given
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml");
+ CBCom cbCom = createCbCom();
+ // When
+ List sclReportItems = controlBlockService.configureNetworkForAllControlBlocks(scd, cbCom);
+ // Then
+ assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue();
+ TGSE gse1 = getCommunicationGSE(scd, "IED_NAME2", "CB_LD_INST21_GSI");
+ assertThat(gse1.getLdInst()).isEqualTo("LD_INST21");
+ assertThat(SclDuration.from(gse1.getMinTime())).isEqualTo(new SclDuration("10", "s", "m"));
+ assertThat(SclDuration.from(gse1.getMaxTime())).isEqualTo(new SclDuration("2000", "s", "m"));
+ assertThat(gse1.getAddress().getP()).extracting(TP::getType, TP::getValue).containsExactlyInAnyOrder(
+ Tuple.tuple("VLAN-PRIORITY", "1"),
+ Tuple.tuple("APPID", "0000"),
+ Tuple.tuple("MAC-Address", "01-0C-CD-01-00-00"),
+ Tuple.tuple("VLAN-ID", "12D")
+ );
+ TGSE gse2 = getCommunicationGSE(scd, "IED_NAME2", "CB_LD_INST21_GMI");
+ assertThat(gse2.getLdInst()).isEqualTo("LD_INST21");
+ assertThat(SclDuration.from(gse2.getMinTime())).isEqualTo(new SclDuration("10", "s", "m"));
+ assertThat(SclDuration.from(gse2.getMaxTime())).isEqualTo(new SclDuration("2000", "s", "m"));
+ assertThat(gse2.getAddress().getP()).extracting(TP::getType, TP::getValue).containsExactlyInAnyOrder(
+ Tuple.tuple("VLAN-PRIORITY", "1"),
+ Tuple.tuple("APPID", "0001"),
+ Tuple.tuple("MAC-Address", "01-0C-CD-01-00-01"),
+ Tuple.tuple("VLAN-ID", "12D")
+ );
+ TGSE gse3 = getCommunicationGSE(scd, "IED_NAME3", "CB_LD_INST31_GSE");
+ assertThat(gse3.getLdInst()).isEqualTo("LD_INST31");
+ assertThat(SclDuration.from(gse3.getMinTime())).isEqualTo(new SclDuration("10", "s", "m"));
+ assertThat(SclDuration.from(gse3.getMaxTime())).isEqualTo(new SclDuration("2000", "s", "m"));
+ assertThat(gse3.getAddress().getP()).extracting(TP::getType, TP::getValue).containsExactlyInAnyOrder(
+ Tuple.tuple("VLAN-PRIORITY", "2"),
+ Tuple.tuple("APPID", "0002"),
+ Tuple.tuple("MAC-Address", "01-0C-CD-01-00-02"),
+ Tuple.tuple("VLAN-ID", "12E")
+ );
+ MarshallerWrapper.assertValidateXmlSchema(scd);
+ }
- TDurationInMilliSec minTime = newDurationInMilliSec(10);
- TDurationInMilliSec maxTime = newDurationInMilliSec(2000);
- ControlBlockNetworkSettings controlBlockNetworkSettings = controlBlockAdapter -> new SettingsOrError(new Settings(0x1D6, (byte) 4, minTime, maxTime), null);
-
+ @Test
+ void configureNetworkForAllControlBlocks_should_create_SMV_elements() {
+ // Given
+ SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml");
+ CBCom cbCom = createCbCom();
// When
- List sclReportItems = controlBlockService.configureNetworkForAllControlBlocks(scd, controlBlockNetworkSettings, RANGES_PER_CB_TYPE);
+ List sclReportItems = controlBlockService.configureNetworkForAllControlBlocks(scd, cbCom);
// Then
assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue();
- TConnectedAP connectedAP = new SclRootAdapter(scd).findConnectedApAdapter("IED_NAME2", "AP_NAME").get().getCurrentElem();
- TGSE gse = connectedAP.getGSE().stream()
- .filter(tgse -> "CB_LD_INST21_GSI".equals(tgse.getCbName()))
- .findFirst().get();
- assertThat(gse.getLdInst()).isEqualTo("LD_INST21");
- assertThat(gse.getMinTime()).extracting(TDurationInMilliSec::getUnit, TDurationInMilliSec::getMultiplier, TDurationInMilliSec::getValue)
- .containsExactly("s", "m", new BigDecimal("10"));
- assertThat(gse.getMaxTime()).extracting(TDurationInMilliSec::getUnit, TDurationInMilliSec::getMultiplier, TDurationInMilliSec::getValue)
- .containsExactly("s", "m", new BigDecimal("2000"));
- assertThat(gse.getAddress().getP()).extracting(TP::getType, TP::getValue)
- .containsExactlyInAnyOrder(
- Tuple.tuple("VLAN-PRIORITY", "4"),
- Tuple.tuple("APPID", "0009"),
- Tuple.tuple("MAC-Address", "01-02-03-04-00-FF"),
- Tuple.tuple("VLAN-ID", "1D6")
- );
- TSMV smv = connectedAP.getSMV().stream()
- .filter(tsmv -> "CB_LD_INST21_SVI".equals(tsmv.getCbName()))
- .findFirst().get();
- assertThat(smv.getLdInst()).isEqualTo("LD_INST21");
- assertThat(smv.getAddress().getP()).extracting(TP::getType, TP::getValue)
- .containsExactlyInAnyOrder(
- Tuple.tuple("VLAN-PRIORITY", "4"),
- Tuple.tuple("APPID", "400A"),
- Tuple.tuple("MAC-Address", "0A-0B-0C-0D-00-FF"),
- Tuple.tuple("VLAN-ID", "1D6")
- );
+ TSMV smv1 = getCommunicationSMV(scd, "IED_NAME2", "CB_LD_INST21_SVI");
+ assertThat(smv1.getLdInst()).isEqualTo("LD_INST21");
+ assertThat(smv1.getAddress().getP()).extracting(TP::getType, TP::getValue).containsExactlyInAnyOrder(
+ Tuple.tuple("VLAN-PRIORITY", "3"),
+ Tuple.tuple("APPID", "4000"),
+ Tuple.tuple("MAC-Address", "01-0C-CD-04-00-00"),
+ Tuple.tuple("VLAN-ID", "12F")
+ );
+ assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue();
+ TSMV smv2 = getCommunicationSMV(scd, "IED_NAME3", "CB_LD_INST31_SVE");
+ assertThat(smv2.getLdInst()).isEqualTo("LD_INST31");
+ assertThat(smv2.getAddress().getP()).extracting(TP::getType, TP::getValue).containsExactlyInAnyOrder(
+ Tuple.tuple("VLAN-PRIORITY", "4"),
+ Tuple.tuple("APPID", "4001"),
+ Tuple.tuple("MAC-Address", "01-0C-CD-04-00-01"),
+ Tuple.tuple("VLAN-ID", "130")
+ );
MarshallerWrapper.assertValidateXmlSchema(scd);
}
@@ -422,12 +438,13 @@ void configureNetworkForAllControlBlocks_should_create_GSE_and_SMV_elements() {
void configureNetworkForAllControlBlocks_should_create_GSE_with_incremental_appid_and_mac_addresses() {
// Given
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml");
-
- TDurationInMilliSec minTime = newDurationInMilliSec(10);
- TDurationInMilliSec maxTime = newDurationInMilliSec(2000);
- ControlBlockNetworkSettings controlBlockNetworkSettings = controlBlockAdapter -> new SettingsOrError(new Settings(0x1D6, (byte) 4, minTime, maxTime), null);
+ CBCom cbCom = createCbCom();
+ cbCom.getAppIdRanges().getAppIdRange().get(0).setStart("0009");
+ cbCom.getAppIdRanges().getAppIdRange().get(0).setEnd("000B");
+ cbCom.getMacRanges().getMacRange().get(0).setStart("01-02-03-04-00-FF");
+ cbCom.getMacRanges().getMacRange().get(0).setEnd("01-02-03-04-01-01");
// When
- List sclReportItems = controlBlockService.configureNetworkForAllControlBlocks(scd, controlBlockNetworkSettings, RANGES_PER_CB_TYPE);
+ List sclReportItems = controlBlockService.configureNetworkForAllControlBlocks(scd, cbCom);
// Then
assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue();
assertThat(streamAllConnectedApGseP(scd, "APPID"))
@@ -438,19 +455,109 @@ void configureNetworkForAllControlBlocks_should_create_GSE_with_incremental_appi
@ParameterizedTest
@MethodSource("provideConfigureNetworkForAllControlBlocksErrors")
- void configureNetworkForAllControlBlocks_should_fail_when_no_settings_for_this_controlBlock(ControlBlockNetworkSettings controlBlockNetworkSettings,
- RangesPerCbType rangesPerCbType,
- String expectedMessage) {
+ void configureNetworkForAllControlBlocks_should_fail_when_no_settings_for_this_controlBlock(CBCom cbCom, String expectedMessage, String expectedXPath) {
// Given
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml");
// When
- List sclReportItems = controlBlockService.configureNetworkForAllControlBlocks(scd, controlBlockNetworkSettings, rangesPerCbType);
+ List sclReportItems = controlBlockService.configureNetworkForAllControlBlocks(scd, cbCom);
// Then
assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isFalse();
assertThat(sclReportItems)
- .extracting(SclReportItem::message, SclReportItem::xpath)
- .contains(Tuple.tuple(expectedMessage,
- "/SCL/IED[@name=\"IED_NAME2\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST21\"]/LN0/GSEControl[@name=\"CB_LD_INST21_GMI\"]"));
+ .contains(SclReportItem.error(expectedXPath, expectedMessage));
+ }
+
+ public static Stream provideConfigureNetworkForAllControlBlocksErrors() {
+ CBCom cbComWithNoVlan = createCbCom();
+ cbComWithNoVlan.getVlans().getVlan().clear();
+ CBCom cbComWithMissingVlanId = createCbCom();
+ cbComWithMissingVlanId.getVlans().getVlan().get(0).setVlanId(null);
+ CBCom cbComWithNotEnoughAppId = createCbCom();
+ cbComWithNotEnoughAppId.getAppIdRanges().getAppIdRange().get(0).setStart("0000");
+ cbComWithNotEnoughAppId.getAppIdRanges().getAppIdRange().get(0).setEnd("00001");
+ CBCom cbComWithNotEnoughMacAddress = createCbCom();
+ cbComWithNotEnoughMacAddress.getMacRanges().getMacRange().get(0).setStart("01-0C-CD-01-00-00");
+ cbComWithNotEnoughMacAddress.getMacRanges().getMacRange().get(0).setEnd("01-0C-CD-01-00-01");
+
+ return Stream.of(
+ Arguments.of(cbComWithNoVlan, "Cannot configure communication for this ControlBlock because: No controlBlock communication settings found with these Criteria[cbType=GOOSE, systemVersionWithoutV=01.00.009.001, iedType=BCU, iedRedundancy=A, iedSystemVersionInstance=1, bayIntOrExt=BAY_INTERNAL]",
+ "/SCL/IED[@name=\"IED_NAME2\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST21\"]/LN0/GSEControl[@name=\"CB_LD_INST21_GMI\"]"),
+ Arguments.of(cbComWithMissingVlanId, "Cannot configure communication for this ControlBlock because no Vlan Id was provided in the settings",
+ "/SCL/IED[@name=\"IED_NAME2\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST21\"]/LN0/GSEControl[@name=\"CB_LD_INST21_GMI\"]"),
+ Arguments.of(cbComWithNotEnoughAppId, "Cannot configure communication for this ControlBlock because range of appId is exhausted",
+ "/SCL/IED[@name=\"IED_NAME3\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST31\"]/LN0/GSEControl[@name=\"CB_LD_INST31_GSE\"]"),
+ Arguments.of(cbComWithNotEnoughMacAddress, "Cannot configure communication for this ControlBlock because range of MAC Address is exhausted",
+ "/SCL/IED[@name=\"IED_NAME3\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST31\"]/LN0/GSEControl[@name=\"CB_LD_INST31_GSE\"]")
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideBlankCriteria")
+ void configureNetworkForAllControlBlocks_when_setting_files_has_blank_criteria_should_throw_exception(Consumer setCriteriaBlank) {
+ // Given
+ SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml");
+ CBCom cbCom = createCbCom();
+ setCriteriaBlank.accept(cbCom.getVlans().getVlan().get(0));
+ //When & Then
+ assertThatThrownBy(() -> controlBlockService.configureNetworkForAllControlBlocks(scd, cbCom))
+ .isInstanceOf(ScdException.class)
+ .hasMessageStartingWith("Error in Control Block communication setting file: vlan is missing attribute ");
+ }
+
+ private static Stream provideBlankCriteria() {
+ return Stream.of(Arguments.of(
+ (Consumer) tVlan -> tVlan.setXY(null),
+ (Consumer) tVlan -> tVlan.setZW(null),
+ (Consumer) tVlan -> tVlan.setIEDType(null),
+ (Consumer) tVlan -> tVlan.setIEDRedundancy(null),
+ (Consumer) tVlan -> tVlan.setIEDSystemVersionInstance(null),
+ (Consumer) tVlan -> tVlan.setBayIntOrExt(null)
+ ));
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideMalformedNumbers")
+ void configureNetworkForAllControlBlocks_when_malformed_numbers_should_throw_exception(Consumer setMalformedNumber) {
+ // Given
+ SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml");
+ CBCom cbCom = createCbCom();
+ setMalformedNumber.accept(cbCom.getVlans().getVlan().get(0));
+ //When & Then
+ assertThatThrownBy(() -> controlBlockService.configureNetworkForAllControlBlocks(scd, cbCom))
+ .isInstanceOf(ScdException.class)
+ .hasMessageStartingWith("Error in Control Block communication setting file: ")
+ .hasMessageEndingWith("must be an integer, but got : XXX");
+ }
+
+ private static Stream provideMalformedNumbers() {
+ return Stream.of(Arguments.of(
+ (Consumer) tVlan -> tVlan.setIEDSystemVersionInstance("XXX"),
+ (Consumer) tVlan -> tVlan.setVlanId("XXX"),
+ (Consumer) tVlan -> tVlan.setVlanPriority("XXX"),
+ (Consumer) tVlan -> tVlan.setMinTime("XXX"),
+ (Consumer) tVlan -> tVlan.setMaxTime("XXX")
+ ));
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideOutOfBoundNumbers")
+ void configureNetworkForAllControlBlocks_when_out_of_bound_numbers_should_throw_exception(Consumer setMalformedNumber) {
+ // Given
+ SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml");
+ CBCom cbCom = createCbCom();
+ setMalformedNumber.accept(cbCom.getVlans().getVlan().get(0));
+ //When & Then
+ assertThatThrownBy(() -> controlBlockService.configureNetworkForAllControlBlocks(scd, cbCom))
+ .isInstanceOf(ScdException.class)
+ .hasMessageMatching("Error in Control Block communication setting file: VLAN (ID|Priority) must be between 0 and [0-9]+, but got : .*");
+ }
+
+ private static Stream provideOutOfBoundNumbers() {
+ return Stream.of(Arguments.of(
+ (Consumer) tVlan -> tVlan.setVlanId("4096"), // VlanId > MAX_VLAN_ID
+ (Consumer) tVlan -> tVlan.setVlanId("-1"), // VlanId < 0
+ (Consumer) tVlan -> tVlan.setVlanPriority("8"), // VlanPriority > MAX_VLAN_PRIORITY
+ (Consumer) tVlan -> tVlan.setVlanPriority("-1") // VlanPriority < 0
+ ));
}
@Test
@@ -493,30 +600,70 @@ void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_controlBlocks_and_D
assertIsMarshallable(scl);
}
- public static Stream provideConfigureNetworkForAllControlBlocksErrors() {
- Settings settingsWithNullVlanId = new Settings(null, (byte) 1, newDurationInMilliSec(1), newDurationInMilliSec(2));
- Settings settings = new Settings(1, (byte) 1, newDurationInMilliSec(1), newDurationInMilliSec(2));
- return Stream.of(
- Arguments.of((ControlBlockNetworkSettings) controlBlockAdapter -> new SettingsOrError(null, null),
- RANGES_PER_CB_TYPE,
- "Cannot configure network for this ControlBlock because no settings was provided"),
- Arguments.of((ControlBlockNetworkSettings) controlBlockAdapter -> new SettingsOrError(null, "Custom error message"),
- RANGES_PER_CB_TYPE,
- "Cannot configure network for this ControlBlock because: Custom error message"),
- Arguments.of((ControlBlockNetworkSettings) controlBlockAdapter -> new SettingsOrError(settingsWithNullVlanId, null),
- RANGES_PER_CB_TYPE,
- "Cannot configure network for this ControlBlock because no Vlan Id was provided in the settings"),
- Arguments.of((ControlBlockNetworkSettings) controlBlockAdapter -> new SettingsOrError(settings, null),
- new RangesPerCbType(
- new NetworkRanges(GSE_APP_ID_MIN, GSE_APP_ID_MIN, GSE_MAC_ADDRESS_PREFIX + "00-FF", GSE_MAC_ADDRESS_PREFIX + "01-AA"),
- SMV_NETWORK_RANGES),
- "Cannot configure network for this ControlBlock because range of appId is exhausted"),
- Arguments.of((ControlBlockNetworkSettings) controlBlockAdapter -> new SettingsOrError(settings, null),
- new RangesPerCbType(
- new NetworkRanges(GSE_APP_ID_MIN, GSE_APP_ID_MIN + 10, GSE_MAC_ADDRESS_PREFIX + "00-FF", GSE_MAC_ADDRESS_PREFIX + "00-FF"),
- SMV_NETWORK_RANGES),
- "Cannot configure network for this ControlBlock because range of MAC Address is exhausted")
- );
+ private static TGSE getCommunicationGSE(SCL scd, String iedName, String cbName) {
+ return new SclRootAdapter(scd).findConnectedApAdapter(iedName, "AP_NAME").orElseThrow()
+ .getCurrentElem()
+ .getGSE().stream()
+ .filter(tgse -> cbName.equals(tgse.getCbName()))
+ .findFirst().orElseThrow();
+ }
+
+ private static TSMV getCommunicationSMV(SCL scd, String iedName, String cbName) {
+ return new SclRootAdapter(scd).findConnectedApAdapter(iedName, "AP_NAME").orElseThrow()
+ .getCurrentElem()
+ .getSMV().stream()
+ .filter(tsmv -> cbName.equals(tsmv.getCbName()))
+ .findFirst().orElseThrow();
+ }
+
+ private static CBCom createCbCom() {
+ CBCom cbCom = new CBCom();
+ cbCom.setMacRanges(new MacRanges());
+ cbCom.setAppIdRanges(new AppIdRanges());
+ cbCom.setVlans(new Vlans());
+ cbCom.getMacRanges().getMacRange().add(newRange(TCBType.GOOSE, "01-0C-CD-01-00-00", "01-0C-CD-01-01-FF"));
+ cbCom.getMacRanges().getMacRange().add(newRange(TCBType.SV, "01-0C-CD-04-00-00", "01-0C-CD-04-FF-FF"));
+ cbCom.getAppIdRanges().getAppIdRange().add(newRange(TCBType.GOOSE, "0000", "4000"));
+ cbCom.getAppIdRanges().getAppIdRange().add(newRange(TCBType.SV, "4000", "7FFF"));
+ cbCom.getVlans().getVlan().addAll(List.of(
+ newVlan(TCBType.GOOSE, TBayIntOrExt.BAY_INTERNAL, "301", "1"),
+ newVlan(TCBType.GOOSE, TBayIntOrExt.BAY_EXTERNAL, "302", "2"),
+ newVlan(TCBType.SV, TBayIntOrExt.BAY_INTERNAL, "303", "3"),
+ newVlan(TCBType.SV, TBayIntOrExt.BAY_EXTERNAL, "304", "4")
+ ));
+ return cbCom;
+ }
+
+ private static TRange newRange(TCBType tcbType, String start, String end) {
+ TRange macRangeGSE = new TRange();
+ macRangeGSE.setCBType(tcbType);
+ macRangeGSE.setStart(start);
+ macRangeGSE.setEnd(end);
+ return macRangeGSE;
+ }
+
+ private static TVlan newVlan(TCBType tcbType, TBayIntOrExt tBayIntOrExt, String vlanId, String vlanPriority) {
+ TVlan gseVlan = new TVlan();
+ gseVlan.setCBType(tcbType);
+ gseVlan.setXY("01.00");
+ gseVlan.setZW("009.001");
+ gseVlan.setIEDType(TIEDType.BCU);
+ gseVlan.setIEDRedundancy(TIEDRedundancy.A);
+ gseVlan.setIEDSystemVersionInstance("1");
+ gseVlan.setBayIntOrExt(tBayIntOrExt);
+ gseVlan.setVlanId(vlanId);
+ gseVlan.setVlanPriority(vlanPriority);
+ gseVlan.setMinTime("10");
+ gseVlan.setMaxTime("2000");
+ return gseVlan;
}
+ /**
+ * Facilite la comparaison de TDurationInMilliSec
+ */
+ record SclDuration(String value, String unit, String multiplier) {
+ static SclDuration from(TDurationInMilliSec tDurationInMilliSec) {
+ return new SclDuration(tDurationInMilliSec.getValue().toString(), tDurationInMilliSec.getUnit(), tDurationInMilliSec.getMultiplier());
+ }
+ }
}
diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ControlBlockNetworkSettingsTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ControlBlockNetworkSettingsTest.java
deleted file mode 100644
index 89450f8d6..000000000
--- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ControlBlockNetworkSettingsTest.java
+++ /dev/null
@@ -1,235 +0,0 @@
-// SPDX-FileCopyrightText: 2023 RTE FRANCE
-//
-// SPDX-License-Identifier: Apache-2.0
-
-package org.lfenergy.compas.sct.commons.dto;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.EnumSource;
-import org.junit.jupiter.params.provider.MethodSource;
-import org.junit.jupiter.params.provider.ValueSource;
-import org.lfenergy.compas.scl2007b4.model.SCL;
-import org.lfenergy.compas.scl2007b4.model.TDurationInMilliSec;
-import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings.SettingsOrError;
-import org.lfenergy.compas.sct.commons.util.PrivateUtils;
-import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
-import org.lfenergy.compas.sct.commons.scl.ied.ControlBlockAdapter;
-import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter;
-import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller;
-import org.lfenergy.compas.sct.commons.util.ControlBlockEnum;
-import org.lfenergy.compas.sct.commons.util.ControlBlockNetworkSettingsCsvHelper;
-import org.lfenergy.compas.sct.commons.util.CsvUtils;
-import org.lfenergy.compas.sct.commons.util.PrivateEnum;
-
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.StringReader;
-import java.math.BigDecimal;
-import java.util.Objects;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings.Settings;
-import static org.lfenergy.compas.sct.commons.testhelpers.SclHelper.findControlBlock;
-import static org.lfenergy.compas.sct.commons.testhelpers.SclHelper.findIed;
-
-class ControlBlockNetworkSettingsTest {
-
- private ControlBlockNetworkSettings controlBlockNetworkSettings;
-
- @BeforeEach
- public void setUp() {
- String fileName = "ControlBlockCommunicationTemplates.csv";
- InputStream inputStream = Objects.requireNonNull(CsvUtils.class.getClassLoader().getResourceAsStream(fileName), "Resource not found: " + fileName);
- InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
- controlBlockNetworkSettings = new ControlBlockNetworkSettingsCsvHelper(inputStreamReader);
- }
-
- @ParameterizedTest
- @ValueSource(strings = {
- ";01.00;009.001;BCU;A;1;BAY_INTERNAL;300;4;10;2000",
- "GOOSE;;009.001;BCU;A;1;BAY_INTERNAL;300;4;10;2000",
- "GOOSE;01.00;;BCU;A;1;BAY_INTERNAL;300;4;10;2000",
- "GOOSE;01.00;009.001;;A;1;BAY_INTERNAL;300;4;10;2000",
- "GOOSE;01.00;009.001;BCU;;1;BAY_INTERNAL;300;4;10;2000",
- "GOOSE;01.00;009.001;BCU;A;;BAY_INTERNAL;300;4;10;2000",
- "GOOSE;01.00;009.001;BCU;A;1;;300;4;10;2000"
- })
- void constructor_when_csv_has_blank_criteria_cells_should_throw_exception(String row) {
- //Given
- StringReader stringReader = new StringReader(row);
- //When & Then
- assertThatThrownBy(() -> new ControlBlockNetworkSettingsCsvHelper(stringReader))
- .isInstanceOf(IllegalArgumentException.class)
- .hasMessageStartingWith("At least one criteria is null in row ControlBlockNetworkSettingsCsvHelper.Row")
- .hasMessageContaining("=null,");
- }
-
- @ParameterizedTest
- @ValueSource(strings = {
- "GOOSE;01.00;009.001;BCU;A;XXX;BAY_INTERNAL;300;4;10;2000",
- "GOOSE;01.00;009.001;BCU;A;1;BAY_INTERNAL;XXX;4;10;2000",
- "GOOSE;01.00;009.001;BCU;A;1;BAY_INTERNAL;300;XXX;10;2000",
- "GOOSE;01.00;009.001;BCU;A;1;BAY_INTERNAL;300;4;XXX;2000",
- "GOOSE;01.00;009.001;BCU;A;1;BAY_INTERNAL;300;4;10;XXX"
- })
- void constructor_when_csv_has_malformed_numbers_should_throw_exception(String row) {
- //Given
- StringReader stringReader = new StringReader(row);
- //When & Then
- assertThatThrownBy(() -> new ControlBlockNetworkSettingsCsvHelper(stringReader))
- .isInstanceOf(NumberFormatException.class)
- .hasMessage("For input string: \"XXX\"");
- }
-
- @ParameterizedTest
- @ValueSource(strings = {
- "GOOSE;01.00;009.001;BCU;A;1;BAY_INTERNAL;4096;4;10;2000", // VlanId > MAX_VLAN_ID
- "GOOSE;01.00;009.001;BCU;A;1;BAY_INTERNAL;-1;4;10;2000", // VlanId < 0
- "GOOSE;01.00;009.001;BCU;A;1;BAY_INTERNAL;300;8;10;2000", // VlanPriority > MAX_VLAN_PRIORITY
- "GOOSE;01.00;009.001;BCU;A;1;BAY_INTERNAL;300;-1;10;2000" // VlanPriority < 0
- })
- void constructor_when_csv_has_numbers_our_out_of_bound_should_throw_exception(String row) {
- //Given
- StringReader stringReader = new StringReader(row);
- //When & Then
- assertThatThrownBy(() -> new ControlBlockNetworkSettingsCsvHelper(stringReader))
- .isInstanceOf(IllegalArgumentException.class)
- .hasMessageContaining("must be between 0 and ");
- }
-
- @Test
- void constructor_when_unsupported_cbType_should_throw_exception() {
- //Given
- StringReader stringReader = new StringReader("CUSTOM_CB_TYPE;01.00;009.001;BCU;A;1;BAY_INTERNAL;1;4;10;2000");
- //When & Then
- assertThatThrownBy(() -> new ControlBlockNetworkSettingsCsvHelper(stringReader))
- .isInstanceOf(IllegalArgumentException.class)
- .hasMessage("Unsupported Control Block Type : CUSTOM_CB_TYPE");
- }
-
- @Test
- void getNetworkSettings_should_return_settings_for_bay_internal_controlBlock() {
- //Given
- SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml");
- ControlBlockAdapter controlBlockAdapter = findControlBlock(scd, "IED_NAME2", "LD_INST21", "CB_LD_INST21_GSI", ControlBlockEnum.GSE);
-
- //When
- SettingsOrError settingsOrError = controlBlockNetworkSettings.getNetworkSettings(controlBlockAdapter);
-
- //Then
- assertThat(settingsOrError.errorMessage()).isNull();
- Settings networkSettings = settingsOrError.settings();
- assertThat(networkSettings)
- .extracting(Settings::vlanId, Settings::vlanPriority)
- .containsExactly(300, (byte) 4);
- assertThat(networkSettings.minTime()).extracting(TDurationInMilliSec::getUnit, TDurationInMilliSec::getMultiplier, TDurationInMilliSec::getValue)
- .containsExactly("s", "m", new BigDecimal("10"));
- assertThat(networkSettings.maxTime()).extracting(TDurationInMilliSec::getUnit, TDurationInMilliSec::getMultiplier, TDurationInMilliSec::getValue)
- .containsExactly("s", "m", new BigDecimal("2000"));
- }
-
- @Test
- void getNetworkSettings_should_return_settings_for_bay_external_controlBlock() {
- //Given
- SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml");
- ControlBlockAdapter controlBlockAdapter = findControlBlock(scd, "IED_NAME3", "LD_INST31", "CB_LD_INST31_GSE", ControlBlockEnum.GSE);
-
- //When
- SettingsOrError settingsOrError = controlBlockNetworkSettings.getNetworkSettings(controlBlockAdapter);
-
- //Then
- assertThat(settingsOrError.errorMessage()).isNull();
- Settings networkSettings = settingsOrError.settings();
- assertThat(networkSettings)
- .extracting(Settings::vlanId, Settings::vlanPriority)
- .containsExactly(301, (byte) 5);
- assertThat(networkSettings.minTime()).extracting(TDurationInMilliSec::getUnit, TDurationInMilliSec::getMultiplier, TDurationInMilliSec::getValue)
- .containsExactly("s", "m", new BigDecimal("15"));
- assertThat(networkSettings.maxTime()).extracting(TDurationInMilliSec::getUnit, TDurationInMilliSec::getMultiplier, TDurationInMilliSec::getValue)
- .containsExactly("s", "m", new BigDecimal("5000"));
- }
-
- @Test
- void getNetworkSettings_should_return_vlanId_null_when_column_contains_none() {
- //Given
- SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml");
- ControlBlockAdapter controlBlockAdapter = findControlBlock(scd, "IED_NAME2", "LD_INST21", "CB_LD_INST21_SVI", ControlBlockEnum.SAMPLED_VALUE);
-
- //When
- SettingsOrError settingsOrError = controlBlockNetworkSettings.getNetworkSettings(controlBlockAdapter);
-
- //Then
- assertThat(settingsOrError.errorMessage()).isNull();
- Settings networkSettings = settingsOrError.settings();
- assertThat(networkSettings.vlanId()).isNull();
- assertThat(networkSettings.vlanPriority()).isNull();
- }
-
- @Test
- void getNetworkSettings_should_return_null_when_row_not_found_in_csv_file() {
- //Given
- SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml");
- SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
- findIed(sclRootAdapter.getCurrentElem(), "IED_NAME2").getCompasSystemVersion().get().setMainSystemVersion("99.99");
- ControlBlockAdapter controlBlockAdapter = findControlBlock(sclRootAdapter.getCurrentElem(), "IED_NAME2", "LD_INST21", "CB_LD_INST21_GSI", ControlBlockEnum.GSE);
-
- //When
- SettingsOrError settingsOrError = controlBlockNetworkSettings.getNetworkSettings(controlBlockAdapter);
-
- //Then
- assertThat(settingsOrError.errorMessage()).isEqualTo("No row found with these criteria Criteria[controlBlockEnum=GSE, systemVersionWithoutV=99.99.009.001, iedType=BCU, iedRedundancy=A, iedSystemVersionInstance=1, isBayInternal=true]");
- assertThat(settingsOrError.settings()).isNull();
- }
-
- @ParameterizedTest
- @EnumSource(value = PrivateEnum.class, mode = EnumSource.Mode.INCLUDE, names = {"COMPAS_ICDHEADER", "COMPAS_SYSTEM_VERSION"})
- void getNetworkSettings_should_return_null_when_missing_ied_private(PrivateEnum missingPrivate) {
- //Given
- SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml");
- SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
- PrivateUtils.removePrivates(findIed(sclRootAdapter.getCurrentElem(), "IED_NAME2").getCurrentElem(), missingPrivate);
- ControlBlockAdapter controlBlockAdapter = findControlBlock(sclRootAdapter.getCurrentElem(), "IED_NAME2", "LD_INST21", "CB_LD_INST21_GSI", ControlBlockEnum.GSE);
-
- //When
- SettingsOrError settingsOrError = controlBlockNetworkSettings.getNetworkSettings(controlBlockAdapter);
-
- //Then
- assertThat(settingsOrError.errorMessage()).isEqualTo("No private %s found in this IED".formatted(missingPrivate.getPrivateType()));
- assertThat(settingsOrError.settings()).isNull();
- }
-
- @ParameterizedTest
- @MethodSource("provideInvalidCompasAttributes")
- void getNetworkSettings_should_return_null_when_missing_ied_private_attributes(Consumer transformIedPrivate) {
- //Given
- SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml");
- ControlBlockAdapter controlBlockAdapter = findControlBlock(scd, "IED_NAME2", "LD_INST21", "CB_LD_INST21_GSI", ControlBlockEnum.GSE);
- IEDAdapter iedAdapter = findIed(scd, "IED_NAME2");
- transformIedPrivate.accept(iedAdapter);
-
- //When
- SettingsOrError settingsOrError = controlBlockNetworkSettings.getNetworkSettings(controlBlockAdapter);
-
- //Then
- assertThat(settingsOrError.errorMessage()).startsWith("No row found with these criteria ");
- assertThat(settingsOrError.settings()).isNull();
- }
-
- private static Stream provideInvalidCompasAttributes() {
- return Stream.of(
- Arguments.of((Consumer) iedAdapter -> iedAdapter.getCompasICDHeader().get().setIEDType(null)),
- Arguments.of((Consumer) iedAdapter -> iedAdapter.getCompasICDHeader().get().setIEDredundancy(null)),
- Arguments.of((Consumer) iedAdapter -> iedAdapter.getCompasICDHeader().get().setIEDSystemVersioninstance(null)),
- Arguments.of((Consumer) iedAdapter -> iedAdapter.getCompasSystemVersion().get().setMainSystemVersion(null)),
- Arguments.of((Consumer) iedAdapter -> iedAdapter.getCompasSystemVersion().get().setMinorSystemVersion(null)),
- Arguments.of((Consumer) iedAdapter -> iedAdapter.getCompasSystemVersion().get().setMinorSystemVersion("1")) // Invalid format for MinorSystemVersion
- );
- }
-
-}
diff --git a/sct-commons/src/test/resources/ControlBlockCommunicationTemplates.csv b/sct-commons/src/test/resources/ControlBlockCommunicationTemplates.csv
deleted file mode 100644
index 5d149af69..000000000
--- a/sct-commons/src/test/resources/ControlBlockCommunicationTemplates.csv
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-FileCopyrightText: 2022 RTE FRANCE
-#
-# SPDX-License-Identifier: Apache-2.0
-
-#CB Type;X.Y;Z.W;IedType;IedRedundancy;IedSystemVersionInstance;Bay Internal OR External;VLAN-ID;VLAN-PRIORITY;MINTIME;MAXTIME
-GOOSE;01.00;009.001;BCU;A;1;BAY_INTERNAL;300;4;10;2000
-SV;01.00;009.001;BCU;A;1;BAY_INTERNAL;None;None;;
-GOOSE;01.00;009.001;BCU;A;1;BAY_EXTERNAL;301;5;15;5000
-SV;01.00;009.001;BCU;A;1;BAY_EXTERNAL;None;None;;
diff --git a/sct-commons/src/test/resources/controlblockCommunication.xml b/sct-commons/src/test/resources/controlblockCommunication.xml
new file mode 100644
index 000000000..844fdfe2f
--- /dev/null
+++ b/sct-commons/src/test/resources/controlblockCommunication.xml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+