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/xsd/RCONF_CB_COM_Config_file_v1.xsd + + + ${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 @@ *
    *
  1. {@link ControlBlockEditor#createDataSetAndControlBlocks(SCL, Set) Create DataSet and ControlBlock based on the TExtRef}
  2. *
  3. {@link ControlBlockEditor#createDataSetAndControlBlocks(SCL, String, Set) Create DataSet and ControlBlock based on the TExtRef in given IED}
  4. - *
  5. {@link ControlBlockEditor#createDataSetAndControlBlocks(SCL, String,String, Set) Create DataSet and ControlBlock based on the TExtRef in given IED and LDevice}
  6. + *
  7. {@link ControlBlockEditor#createDataSetAndControlBlocks(SCL, String, String, Set) Create DataSet and ControlBlock based on the TExtRef in given IED and LDevice}
  8. *
  9. {@link ControlBlockEditor#configureNetworkForAllControlBlocks Configure the network for the ControlBlocks}
  10. *
  11. {@link ControlBlockEditor#removeAllControlBlocksAndDatasetsAndExtRefSrcBindings Removes all ControlBlocks and DataSets for all LNs in SCL}
  12. *
  13. {@link ControlBlockEditor#analyzeDataGroups(SCL)} Checks Control Blocks, DataSets and FCDA number limitation into Access Points }
  14. @@ -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 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +